diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index df6339d7bf72fbff5a085ea675e202793625ba04..2ef6f652bc500dd65e1b409fe465039c3622daaa 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -186,6 +186,12 @@ config CPU_SH2A select CPU_SH2 select UNCACHED_MAPPING +config CPU_J2 + bool + select CPU_SH2 + select OF + select OF_EARLY_FLATTREE + config CPU_SH3 bool select CPU_HAS_INTEVT @@ -252,6 +258,10 @@ config CPU_SUBTYPE_SH7619 select CPU_SH2 select SYS_SUPPORTS_SH_CMT +config CPU_SUBTYPE_J2 + bool "Support J2 processor" + select CPU_J2 + # SH-2A Processor Support config CPU_SUBTYPE_SH7201 diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 3b2c8b4827d0b9b82d81a1acb352ad360a38cd95..00476662ac2c07ba1e0a3bb427e114ae2f5a7650 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -31,6 +31,7 @@ isa-y := $(isa-y)-up endif cflags-$(CONFIG_CPU_SH2) := $(call cc-option,-m2,) +cflags-$(CONFIG_CPU_J2) := $(call cc-option,-mj2,) cflags-$(CONFIG_CPU_SH2A) += $(call cc-option,-m2a,) \ $(call cc-option,-m2a-nofpu,) \ $(call cc-option,-m4-nofpu,) diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h index 1506897648aa17ce0d594b2d1068fc7988a70095..f9a09942a32d37249b43ec4139762aaafa16443d 100644 --- a/arch/sh/include/asm/processor.h +++ b/arch/sh/include/asm/processor.h @@ -15,7 +15,7 @@ */ enum cpu_type { /* SH-2 types */ - CPU_SH7619, + CPU_SH7619, CPU_J2, /* SH-2A types */ CPU_SH7201, CPU_SH7203, CPU_SH7206, CPU_SH7263, CPU_SH7264, CPU_SH7269, diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index bfd9e2798008051a6b18c69ccf0357d9bfd13210..c8b3be1b54e6e810e4f116fe2264d7a79f267b14 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -106,7 +106,7 @@ void __attribute__ ((weak)) l2_cache_init(void) /* * Generic first-level cache init */ -#ifdef CONFIG_SUPERH32 +#if defined(CONFIG_SUPERH32) && !defined(CONFIG_CPU_J2) static void cache_init(void) { unsigned long ccr, flags; diff --git a/arch/sh/kernel/cpu/proc.c b/arch/sh/kernel/cpu/proc.c index 9e6624c9108bcf77bbc525909195c2a0cb6e5d69..4df4b284f5915bcbb21a6e2fd809bf7baa44c75d 100644 --- a/arch/sh/kernel/cpu/proc.c +++ b/arch/sh/kernel/cpu/proc.c @@ -27,6 +27,7 @@ static const char *cpu_name[] = { [CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723", [CPU_SH7366] = "SH7366", [CPU_SH7724] = "SH7724", [CPU_SH7372] = "SH7372", [CPU_SH7734] = "SH7734", + [CPU_J2] = "J2", [CPU_SH_NONE] = "Unknown" }; diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S index a1505956ef28b4f0fd694cc4d1c609281b782811..16bde0efaca37b68dd696f1164bbd8b11e64a319 100644 --- a/arch/sh/kernel/cpu/sh2/entry.S +++ b/arch/sh/kernel/cpu/sh2/entry.S @@ -147,6 +147,11 @@ ENTRY(exception_handler) mov #31,r8 cmp/hs r8,r9 bt trap_entry ! 64 > vec >= 31 is trap +#ifdef CONFIG_CPU_J2 + mov #16,r8 + cmp/hs r8,r9 + bt interrupt_entry ! 31 > vec >= 16 is interrupt +#endif mov.l 4f,r8 mov r9,r4 diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index 6c687ae812ef6aa89087d3bced828ee580d2a325..152184007964002d740dc149c687ddc960748b85 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -10,10 +10,27 @@ * for more details. */ #include +#include +#include +#include #include #include -void cpu_probe(void) +#if defined(CONFIG_CPU_J2) +extern u32 __iomem *j2_ccr_base; +static int __init scan_cache(unsigned long node, const char *uname, + int depth, void *data) +{ + if (!of_flat_dt_is_compatible(node, "jcore,cache")) + return 0; + + j2_ccr_base = (u32 __iomem *)of_flat_dt_translate_address(node); + + return 1; +} +#endif + +void __ref cpu_probe(void) { #if defined(CONFIG_CPU_SUBTYPE_SH7619) boot_cpu_data.type = CPU_SH7619; @@ -24,10 +41,28 @@ void cpu_probe(void) boot_cpu_data.dcache.linesz = L1_CACHE_BYTES; boot_cpu_data.dcache.flags = 0; #endif + +#if defined(CONFIG_CPU_J2) + unsigned cpu = hard_smp_processor_id(); + if (cpu == 0) of_scan_flat_dt(scan_cache, NULL); + if (j2_ccr_base) __raw_writel(0x80000303, j2_ccr_base + 4*cpu); + if (cpu != 0) return; + boot_cpu_data.type = CPU_J2; + + /* These defaults are appropriate for the original/current + * J2 cache. Once there is a proper framework for getting cache + * info from device tree, we should switch to that. */ + boot_cpu_data.dcache.ways = 1; + boot_cpu_data.dcache.sets = 256; + boot_cpu_data.dcache.entry_shift = 5; + boot_cpu_data.dcache.linesz = 32; + boot_cpu_data.dcache.flags = 0; +#else /* * SH-2 doesn't have separate caches */ boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED; +#endif boot_cpu_data.icache = boot_cpu_data.dcache; boot_cpu_data.family = CPU_FAMILY_SH2; } diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index cee6b9999d86011781e6a973270967c7e937762f..92c3bd96aee56fea8df2c393d1810b827849da57 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile @@ -4,7 +4,8 @@ obj-y := alignment.o cache.o init.o consistent.o mmap.o -cacheops-$(CONFIG_CPU_SH2) := cache-sh2.o +cacheops-$(CONFIG_CPU_J2) := cache-j2.o +cacheops-$(CONFIG_CPU_SUBTYPE_SH7619) := cache-sh2.o cacheops-$(CONFIG_CPU_SH2A) := cache-sh2a.o cacheops-$(CONFIG_CPU_SH3) := cache-sh3.o cacheops-$(CONFIG_CPU_SH4) := cache-sh4.o flush-sh4.o diff --git a/arch/sh/mm/cache-j2.c b/arch/sh/mm/cache-j2.c new file mode 100644 index 0000000000000000000000000000000000000000..391698bcac5b2f840f5e29b1d6ebb80f6128b1ae --- /dev/null +++ b/arch/sh/mm/cache-j2.c @@ -0,0 +1,65 @@ +/* + * arch/sh/mm/cache-j2.c + * + * Copyright (C) 2015-2016 Smart Energy Instruments, Inc. + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define ICACHE_ENABLE 0x1 +#define DCACHE_ENABLE 0x2 +#define CACHE_ENABLE (ICACHE_ENABLE | DCACHE_ENABLE) +#define ICACHE_FLUSH 0x100 +#define DCACHE_FLUSH 0x200 +#define CACHE_FLUSH (ICACHE_FLUSH | DCACHE_FLUSH) + +u32 __iomem *j2_ccr_base; + +static void j2_flush_icache(void *args) +{ + unsigned cpu; + for_each_possible_cpu(cpu) + __raw_writel(CACHE_ENABLE | ICACHE_FLUSH, j2_ccr_base + cpu); +} + +static void j2_flush_dcache(void *args) +{ + unsigned cpu; + for_each_possible_cpu(cpu) + __raw_writel(CACHE_ENABLE | DCACHE_FLUSH, j2_ccr_base + cpu); +} + +static void j2_flush_both(void *args) +{ + unsigned cpu; + for_each_possible_cpu(cpu) + __raw_writel(CACHE_ENABLE | CACHE_FLUSH, j2_ccr_base + cpu); +} + +void __init j2_cache_init(void) +{ + if (!j2_ccr_base) + return; + + local_flush_cache_all = j2_flush_both; + local_flush_cache_mm = j2_flush_both; + local_flush_cache_dup_mm = j2_flush_both; + local_flush_cache_page = j2_flush_both; + local_flush_cache_range = j2_flush_both; + local_flush_dcache_page = j2_flush_dcache; + local_flush_icache_range = j2_flush_icache; + local_flush_icache_page = j2_flush_icache; + local_flush_cache_sigtramp = j2_flush_icache; + + pr_info("Initial J2 CCR is %.8x\n", __raw_readl(j2_ccr_base)); +} diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c index 776d664a40c5f2fd4298f25b5ec010605ac0532d..70cc52f2fab82860b920978e7f1a6a16acdf3203 100644 --- a/arch/sh/mm/cache.c +++ b/arch/sh/mm/cache.c @@ -309,7 +309,11 @@ void __init cpu_cache_init(void) if (unlikely(cache_disabled)) goto skip; - if (boot_cpu_data.family == CPU_FAMILY_SH2) { + if (boot_cpu_data.type == CPU_J2) { + extern void __weak j2_cache_init(void); + + j2_cache_init(); + } else if (boot_cpu_data.family == CPU_FAMILY_SH2) { extern void __weak sh2_cache_init(void); sh2_cache_init();