Commit 5a846aba authored by Rich Felker's avatar Rich Felker

sh: add support for J-Core J2 processor

At the CPU/ISA level, the J2 is compatible with SH-2, and thus the
changes to add J2 support build on existing SH-2 support. However, J2
does not duplicate the memory-mapped SH-2 features like the cache
interface. Instead, the cache interfaces is described in the device
tree, and new code is added to be able to access the flat device tree
at early boot before it is unflattened.

Support is also added for receiving interrupts on trap numbers in the
range 16 to 31, since the J-Core aic1 interrupt controller generates
these traps. This range was unused but nominally for hardware
exceptions on SH-2, and a few values in this range were used for
exceptions on SH-2A, but SH-2A has its own version of the relevant
code.

No individual cpu subtypes are added for J2 since the intent moving
forward is to represent SoCs with device tree rather than as
hard-coded subtypes in the kernel. The CPU_SUBTYPE_J2 Kconfig item
exists only to fit into the existing cpu selection mechanism until it
is overhauled.
Signed-off-by: default avatarRich Felker <dalias@libc.org>
parent 03767daa
...@@ -186,6 +186,12 @@ config CPU_SH2A ...@@ -186,6 +186,12 @@ config CPU_SH2A
select CPU_SH2 select CPU_SH2
select UNCACHED_MAPPING select UNCACHED_MAPPING
config CPU_J2
bool
select CPU_SH2
select OF
select OF_EARLY_FLATTREE
config CPU_SH3 config CPU_SH3
bool bool
select CPU_HAS_INTEVT select CPU_HAS_INTEVT
...@@ -252,6 +258,10 @@ config CPU_SUBTYPE_SH7619 ...@@ -252,6 +258,10 @@ config CPU_SUBTYPE_SH7619
select CPU_SH2 select CPU_SH2
select SYS_SUPPORTS_SH_CMT select SYS_SUPPORTS_SH_CMT
config CPU_SUBTYPE_J2
bool "Support J2 processor"
select CPU_J2
# SH-2A Processor Support # SH-2A Processor Support
config CPU_SUBTYPE_SH7201 config CPU_SUBTYPE_SH7201
......
...@@ -31,6 +31,7 @@ isa-y := $(isa-y)-up ...@@ -31,6 +31,7 @@ isa-y := $(isa-y)-up
endif endif
cflags-$(CONFIG_CPU_SH2) := $(call cc-option,-m2,) cflags-$(CONFIG_CPU_SH2) := $(call cc-option,-m2,)
cflags-$(CONFIG_CPU_J2) := $(call cc-option,-mj2,)
cflags-$(CONFIG_CPU_SH2A) += $(call cc-option,-m2a,) \ cflags-$(CONFIG_CPU_SH2A) += $(call cc-option,-m2a,) \
$(call cc-option,-m2a-nofpu,) \ $(call cc-option,-m2a-nofpu,) \
$(call cc-option,-m4-nofpu,) $(call cc-option,-m4-nofpu,)
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
*/ */
enum cpu_type { enum cpu_type {
/* SH-2 types */ /* SH-2 types */
CPU_SH7619, CPU_SH7619, CPU_J2,
/* SH-2A types */ /* SH-2A types */
CPU_SH7201, CPU_SH7203, CPU_SH7206, CPU_SH7263, CPU_SH7264, CPU_SH7269, CPU_SH7201, CPU_SH7203, CPU_SH7206, CPU_SH7263, CPU_SH7264, CPU_SH7269,
......
...@@ -106,7 +106,7 @@ void __attribute__ ((weak)) l2_cache_init(void) ...@@ -106,7 +106,7 @@ void __attribute__ ((weak)) l2_cache_init(void)
/* /*
* Generic first-level cache init * Generic first-level cache init
*/ */
#ifdef CONFIG_SUPERH32 #if defined(CONFIG_SUPERH32) && !defined(CONFIG_CPU_J2)
static void cache_init(void) static void cache_init(void)
{ {
unsigned long ccr, flags; unsigned long ccr, flags;
......
...@@ -27,6 +27,7 @@ static const char *cpu_name[] = { ...@@ -27,6 +27,7 @@ static const char *cpu_name[] = {
[CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723", [CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723",
[CPU_SH7366] = "SH7366", [CPU_SH7724] = "SH7724", [CPU_SH7366] = "SH7366", [CPU_SH7724] = "SH7724",
[CPU_SH7372] = "SH7372", [CPU_SH7734] = "SH7734", [CPU_SH7372] = "SH7372", [CPU_SH7734] = "SH7734",
[CPU_J2] = "J2",
[CPU_SH_NONE] = "Unknown" [CPU_SH_NONE] = "Unknown"
}; };
......
...@@ -147,6 +147,11 @@ ENTRY(exception_handler) ...@@ -147,6 +147,11 @@ ENTRY(exception_handler)
mov #31,r8 mov #31,r8
cmp/hs r8,r9 cmp/hs r8,r9
bt trap_entry ! 64 > vec >= 31 is trap 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.l 4f,r8
mov r9,r4 mov r9,r4
......
...@@ -10,10 +10,27 @@ ...@@ -10,10 +10,27 @@
* for more details. * for more details.
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/of_fdt.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/cache.h> #include <asm/cache.h>
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) #if defined(CONFIG_CPU_SUBTYPE_SH7619)
boot_cpu_data.type = CPU_SH7619; boot_cpu_data.type = CPU_SH7619;
...@@ -24,10 +41,28 @@ void cpu_probe(void) ...@@ -24,10 +41,28 @@ void cpu_probe(void)
boot_cpu_data.dcache.linesz = L1_CACHE_BYTES; boot_cpu_data.dcache.linesz = L1_CACHE_BYTES;
boot_cpu_data.dcache.flags = 0; boot_cpu_data.dcache.flags = 0;
#endif #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 * SH-2 doesn't have separate caches
*/ */
boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED; boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
#endif
boot_cpu_data.icache = boot_cpu_data.dcache; boot_cpu_data.icache = boot_cpu_data.dcache;
boot_cpu_data.family = CPU_FAMILY_SH2; boot_cpu_data.family = CPU_FAMILY_SH2;
} }
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
obj-y := alignment.o cache.o init.o consistent.o mmap.o 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_SH2A) := cache-sh2a.o
cacheops-$(CONFIG_CPU_SH3) := cache-sh3.o cacheops-$(CONFIG_CPU_SH3) := cache-sh3.o
cacheops-$(CONFIG_CPU_SH4) := cache-sh4.o flush-sh4.o cacheops-$(CONFIG_CPU_SH4) := cache-sh4.o flush-sh4.o
......
/*
* 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 <linux/init.h>
#include <linux/mm.h>
#include <linux/cpumask.h>
#include <asm/cache.h>
#include <asm/addrspace.h>
#include <asm/processor.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
#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));
}
...@@ -309,7 +309,11 @@ void __init cpu_cache_init(void) ...@@ -309,7 +309,11 @@ void __init cpu_cache_init(void)
if (unlikely(cache_disabled)) if (unlikely(cache_disabled))
goto skip; 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); extern void __weak sh2_cache_init(void);
sh2_cache_init(); sh2_cache_init();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment