From 6a65534baf702a63b27637e6ac350c393cb7dd16 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 18 Oct 2004 09:00:48 -0700 Subject: [PATCH] [PATCH] sh: Broken-out CPU subtype probing Previously we could do subtype parsing and cache configuration in the same location.. but with the introduction of things like the SH7705 where we use SH-3 style probing with SH-4 style caches, this is no longer the case. As such, we move the probe code to a saner place. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/kernel/cpu/sh2/Makefile | 2 + arch/sh/kernel/cpu/sh2/probe.c | 39 +++++++++ arch/sh/kernel/cpu/sh3/Makefile | 2 +- arch/sh/kernel/cpu/sh3/probe.c | 97 ++++++++++++++++++++++ arch/sh/kernel/cpu/sh4/Makefile | 3 +- arch/sh/kernel/cpu/sh4/probe.c | 138 ++++++++++++++++++++++++++++++++ arch/sh/mm/cache-sh2.c | 24 +----- arch/sh/mm/cache-sh3.c | 75 ++--------------- arch/sh/mm/cache-sh4.c | 129 ++--------------------------- 9 files changed, 291 insertions(+), 218 deletions(-) create mode 100644 arch/sh/kernel/cpu/sh2/probe.c create mode 100644 arch/sh/kernel/cpu/sh3/probe.c create mode 100644 arch/sh/kernel/cpu/sh4/probe.c diff --git a/arch/sh/kernel/cpu/sh2/Makefile b/arch/sh/kernel/cpu/sh2/Makefile index eb38f91d17261..389353fba608f 100644 --- a/arch/sh/kernel/cpu/sh2/Makefile +++ b/arch/sh/kernel/cpu/sh2/Makefile @@ -2,3 +2,5 @@ # Makefile for the Linux/SuperH SH-2 backends. # +obj-y := probe.o + diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c new file mode 100644 index 0000000000000..f17a2a0d588ed --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -0,0 +1,39 @@ +/* + * arch/sh/kernel/cpu/sh2/probe.c + * + * CPU Subtype Probing for SH-2. + * + * Copyright (C) 2002 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + + +#include +#include +#include + +int __init detect_cpu_and_cache_system(void) +{ + /* + * For now, assume SH7604 .. fix this later. + */ + cpu_data->type = CPU_SH7604; + cpu_data->dcache.ways = 4; + cpu_data->dcache.way_shift = 6; + cpu_data->dcache.sets = 64; + cpu_data->dcache.entry_shift = 4; + cpu_data->dcache.linesz = L1_CACHE_BYTES; + cpu_data->dcache.flags = 0; + + /* + * SH-2 doesn't have separate caches + */ + cpu_data->dcache.flags |= SH_CACHE_COMBINED; + cpu_data->icache = cpu_data->dcache; + + return 0; +} + diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index 196c5f07e118d..a64532e4dc636 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -2,5 +2,5 @@ # Makefile for the Linux/SuperH SH-3 backends. # -obj-y := ex.o +obj-y := ex.o probe.o diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c new file mode 100644 index 0000000000000..5cdc886386012 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/probe.c @@ -0,0 +1,97 @@ +/* + * arch/sh/kernel/cpu/sh3/probe.c + * + * CPU Subtype Probing for SH-3. + * + * Copyright (C) 1999, 2000 Niibe Yutaka + * Copyright (C) 2002 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include + +int __init detect_cpu_and_cache_system(void) +{ + unsigned long addr0, addr1, data0, data1, data2, data3; + + jump_to_P2(); + /* + * Check if the entry shadows or not. + * When shadowed, it's 128-entry system. + * Otherwise, it's 256-entry system. + */ + addr0 = CACHE_OC_ADDRESS_ARRAY + (3 << 12); + addr1 = CACHE_OC_ADDRESS_ARRAY + (1 << 12); + + /* First, write back & invalidate */ + data0 = ctrl_inl(addr0); + ctrl_outl(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0); + data1 = ctrl_inl(addr1); + ctrl_outl(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1); + + /* Next, check if there's shadow or not */ + data0 = ctrl_inl(addr0); + data0 ^= SH_CACHE_VALID; + ctrl_outl(data0, addr0); + data1 = ctrl_inl(addr1); + data2 = data1 ^ SH_CACHE_VALID; + ctrl_outl(data2, addr1); + data3 = ctrl_inl(addr0); + + /* Lastly, invaliate them. */ + ctrl_outl(data0&~SH_CACHE_VALID, addr0); + ctrl_outl(data2&~SH_CACHE_VALID, addr1); + + back_to_P1(); + + cpu_data->dcache.ways = 4; + cpu_data->dcache.entry_shift = 4; + cpu_data->dcache.linesz = L1_CACHE_BYTES; + cpu_data->dcache.flags = 0; + + /* + * 7709A/7729 has 16K cache (256-entry), while 7702 has only + * 2K(direct) 7702 is not supported (yet) + */ + if (data0 == data1 && data2 == data3) { /* Shadow */ + cpu_data->dcache.way_incr = (1 << 11); + cpu_data->dcache.entry_mask = 0x7f0; + cpu_data->dcache.sets = 128; + cpu_data->type = CPU_SH7708; + + cpu_data->flags |= CPU_HAS_MMU_PAGE_ASSOC; + } else { /* 7709A or 7729 */ + cpu_data->dcache.way_incr = (1 << 12); + cpu_data->dcache.entry_mask = 0xff0; + cpu_data->dcache.sets = 256; + cpu_data->type = CPU_SH7729; + +#if defined(CONFIG_CPU_SUBTYPE_SH7705) + cpu_data->type = CPU_SH7705; + +#if defined(CONFIG_SH7705_CACHE_32KB) + cpu_data->dcache.way_incr = (1 << 13); + cpu_data->dcache.entry_mask = 0x1ff0; + cpu_data->dcache.sets = 512; + ctrl_outl(CCR_CACHE_32KB, CCR3); +#else + ctrl_outl(CCR_CACHE_16KB, CCR3); +#endif +#endif + } + + /* + * SH-3 doesn't have separate caches + */ + cpu_data->dcache.flags |= SH_CACHE_COMBINED; + cpu_data->icache = cpu_data->dcache; + + return 0; +} + diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index fd59761431057..ead1071eac738 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile @@ -2,8 +2,9 @@ # Makefile for the Linux/SuperH SH-4 backends. # -obj-y := fpu.o ex.o +obj-y := ex.o probe.o +obj-$(CONFIG_SH_FPU) += fpu.o obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += irq_intc2.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c new file mode 100644 index 0000000000000..42427b79697bf --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -0,0 +1,138 @@ +/* + * arch/sh/kernel/cpu/sh4/probe.c + * + * CPU Subtype Probing for SH-4. + * + * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2003 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include + +int __init detect_cpu_and_cache_system(void) +{ + unsigned long pvr, prr, cvr; + unsigned long size; + + static unsigned long sizes[16] = { + [1] = (1 << 12), + [2] = (1 << 13), + [4] = (1 << 14), + [8] = (1 << 15), + [9] = (1 << 16) + }; + + pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff; + prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff; + cvr = (ctrl_inl(CCN_CVR)); + + /* + * Setup some sane SH-4 defaults for the icache + */ + cpu_data->icache.way_incr = (1 << 13); + cpu_data->icache.entry_shift = 5; + cpu_data->icache.entry_mask = 0x1fe0; + cpu_data->icache.sets = 256; + cpu_data->icache.ways = 1; + cpu_data->icache.linesz = L1_CACHE_BYTES; + + /* + * And again for the dcache .. + */ + cpu_data->dcache.way_incr = (1 << 14); + cpu_data->dcache.entry_shift = 5; + cpu_data->dcache.entry_mask = 0x3fe0; + cpu_data->dcache.sets = 512; + cpu_data->dcache.ways = 1; + cpu_data->dcache.linesz = L1_CACHE_BYTES; + + /* Set the FPU flag, virtually all SH-4's have one */ + cpu_data->flags |= CPU_HAS_FPU; + + /* + * Probe the underlying processor version/revision and + * adjust cpu_data setup accordingly. + */ + switch (pvr) { + case 0x205: + cpu_data->type = CPU_SH7750; + cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER; + break; + case 0x206: + cpu_data->type = CPU_SH7750S; + cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER; + break; + case 0x1100: + cpu_data->type = CPU_SH7751; + break; + case 0x2000: + cpu_data->type = CPU_SH73180; + cpu_data->icache.ways = 4; + cpu_data->dcache.ways = 4; + cpu_data->flags &= ~CPU_HAS_FPU; + break; + case 0x8000: + cpu_data->type = CPU_ST40RA; + break; + case 0x8100: + cpu_data->type = CPU_ST40GX1; + break; + case 0x700: + cpu_data->type = CPU_SH4_501; + cpu_data->icache.ways = 2; + cpu_data->dcache.ways = 2; + + /* No FPU on the SH4-500 series.. */ + cpu_data->flags &= ~CPU_HAS_FPU; + break; + case 0x600: + cpu_data->type = CPU_SH4_202; + cpu_data->icache.ways = 2; + cpu_data->dcache.ways = 2; + break; + case 0x500 ... 0x501: + switch (prr) { + case 0x10: cpu_data->type = CPU_SH7750R; break; + case 0x11: cpu_data->type = CPU_SH7751R; break; + case 0x50: cpu_data->type = CPU_SH7760; break; + } + + cpu_data->icache.ways = 2; + cpu_data->dcache.ways = 2; + + break; + default: + cpu_data->type = CPU_SH_NONE; + break; + } + + /* + * On anything that's not a direct-mapped cache, look to the CVR + * for I/D-cache specifics. + */ + if (cpu_data->icache.ways > 1) { + size = sizes[(cvr >> 20) & 0xf]; + cpu_data->icache.way_incr = (size >> 1); + cpu_data->icache.sets = (size >> 6); + cpu_data->icache.entry_mask = + (cpu_data->icache.way_incr - (1 << 5)); + } + + if (cpu_data->dcache.ways > 1) { + size = sizes[(cvr >> 16) & 0xf]; + cpu_data->dcache.way_incr = (size >> 1); + cpu_data->dcache.sets = (size >> 6); + cpu_data->dcache.entry_mask = + (cpu_data->dcache.way_incr - (1 << 5)); + } + + return 0; +} + diff --git a/arch/sh/mm/cache-sh2.c b/arch/sh/mm/cache-sh2.c index ee5b452b19ac4..2689cb24ea2b9 100644 --- a/arch/sh/mm/cache-sh2.c +++ b/arch/sh/mm/cache-sh2.c @@ -24,7 +24,7 @@ unsigned long __get_oc_addr(unsigned long set, unsigned long way) { unsigned long ccr; - + /* * On SH-2 the way bit isn't tracked in the address field * if we're doing address array access .. instead, we need @@ -48,25 +48,3 @@ unsigned long __get_oc_addr(unsigned long set, unsigned long way) return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift); } -int __init detect_cpu_and_cache_system(void) -{ - /* - * For now, assume SH7604 .. fix this later. - */ - cpu_data->type = CPU_SH7604; - cpu_data->dcache.ways = 4; - cpu_data->dcache.way_shift = 6; - cpu_data->dcache.sets = 64; - cpu_data->dcache.entry_shift = 4; - cpu_data->dcache.linesz = L1_CACHE_BYTES; - cpu_data->dcache.flags = 0; - - /* - * SH-2 doesn't have separate caches - */ - cpu_data->dcache.flags |= SH_CACHE_COMBINED; - cpu_data->icache = cpu_data->dcache; - - return 0; -} - diff --git a/arch/sh/mm/cache-sh3.c b/arch/sh/mm/cache-sh3.c index b03d5e441029c..838731fc608dd 100644 --- a/arch/sh/mm/cache-sh3.c +++ b/arch/sh/mm/cache-sh3.c @@ -1,9 +1,10 @@ -/* $Id: cache-sh3.c,v 1.9 2004/05/02 01:46:30 sugioka Exp $ - * - * linux/arch/sh/mm/cache-sh3.c +/* + * arch/sh/mm/cache-sh3.c * * Copyright (C) 1999, 2000 Niibe Yutaka * Copyright (C) 2002 Paul Mundt + * + * Released under the terms of the GNU GPL v2.0. */ #include @@ -21,72 +22,6 @@ #include #include -int __init detect_cpu_and_cache_system(void) -{ - unsigned long addr0, addr1, data0, data1, data2, data3; - - jump_to_P2(); - /* - * Check if the entry shadows or not. - * When shadowed, it's 128-entry system. - * Otherwise, it's 256-entry system. - */ - addr0 = CACHE_OC_ADDRESS_ARRAY + (3 << 12); - addr1 = CACHE_OC_ADDRESS_ARRAY + (1 << 12); - - /* First, write back & invalidate */ - data0 = ctrl_inl(addr0); - ctrl_outl(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0); - data1 = ctrl_inl(addr1); - ctrl_outl(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1); - - /* Next, check if there's shadow or not */ - data0 = ctrl_inl(addr0); - data0 ^= SH_CACHE_VALID; - ctrl_outl(data0, addr0); - data1 = ctrl_inl(addr1); - data2 = data1 ^ SH_CACHE_VALID; - ctrl_outl(data2, addr1); - data3 = ctrl_inl(addr0); - - /* Lastly, invaliate them. */ - ctrl_outl(data0&~SH_CACHE_VALID, addr0); - ctrl_outl(data2&~SH_CACHE_VALID, addr1); - - back_to_P1(); - - cpu_data->dcache.ways = 4; - cpu_data->dcache.entry_shift = 4; - cpu_data->dcache.linesz = L1_CACHE_BYTES; - cpu_data->dcache.flags = 0; - - /* - * 7709A/7729 has 16K cache (256-entry), while 7702 has only - * 2K(direct) 7702 is not supported (yet) - */ - if (data0 == data1 && data2 == data3) { /* Shadow */ - cpu_data->dcache.way_incr = (1 << 11); - cpu_data->dcache.entry_mask = 0x7f0; - cpu_data->dcache.sets = 128; - cpu_data->type = CPU_SH7708; - - cpu_data->flags |= CPU_HAS_MMU_PAGE_ASSOC; - } else { /* 7709A or 7729 */ - cpu_data->dcache.way_incr = (1 << 12); - cpu_data->dcache.entry_mask = 0xff0; - cpu_data->dcache.sets = 256; - cpu_data->type = CPU_SH7729; - } - - /* - * SH-3 doesn't have separate caches - */ - cpu_data->dcache.flags |= SH_CACHE_COMBINED; - cpu_data->icache = cpu_data->dcache; - - return 0; -} - /* * Write back the dirty D-caches, but not invalidate them. * @@ -116,7 +51,7 @@ void __flush_wback_region(void *start, int size) addr = addrstart | (v & cpu_data->dcache.entry_mask); local_irq_save(flags); data = ctrl_inl(addr); - + if ((data & CACHE_PHYSADDR_MASK) == (p & CACHE_PHYSADDR_MASK)) { data &= ~SH_CACHE_UPDATED; diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index adb99d833d230..a877087d00dae 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c @@ -1,10 +1,13 @@ -/* $Id: cache-sh4.c,v 1.26 2004/02/19 12:47:24 lethal Exp $ - * - * linux/arch/sh/mm/cache-sh4.c +/* + * arch/sh/mm/cache-sh4.c * * Copyright (C) 1999, 2000, 2002 Niibe Yutaka * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt * Copyright (C) 2003 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. */ #include @@ -28,126 +31,6 @@ static void __flush_cache_4096_all_ex(unsigned long start); extern void __flush_dcache_all(void); static void __flush_dcache_all_ex(void); -int __init detect_cpu_and_cache_system(void) -{ - unsigned long pvr, prr, cvr; - unsigned long size; - - static unsigned long sizes[16] = { - [1] = (1 << 12), - [2] = (1 << 13), - [4] = (1 << 14), - [8] = (1 << 15), - [9] = (1 << 16) - }; - - pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff; - prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff; - cvr = (ctrl_inl(CCN_CVR)); - - /* - * Setup some sane SH-4 defaults for the icache - */ - cpu_data->icache.way_incr = (1 << 13); - cpu_data->icache.entry_shift = 5; - cpu_data->icache.entry_mask = 0x1fe0; - cpu_data->icache.sets = 256; - cpu_data->icache.ways = 1; - cpu_data->icache.linesz = L1_CACHE_BYTES; - - /* - * And again for the dcache .. - */ - cpu_data->dcache.way_incr = (1 << 14); - cpu_data->dcache.entry_shift = 5; - cpu_data->dcache.entry_mask = 0x3fe0; - cpu_data->dcache.sets = 512; - cpu_data->dcache.ways = 1; - cpu_data->dcache.linesz = L1_CACHE_BYTES; - - /* Set the FPU flag, virtually all SH-4's have one */ - cpu_data->flags |= CPU_HAS_FPU; - - /* - * Probe the underlying processor version/revision and - * adjust cpu_data setup accordingly. - */ - switch (pvr) { - case 0x205: - cpu_data->type = CPU_SH7750; - cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG; - break; - case 0x206: - cpu_data->type = CPU_SH7750S; - - /* - * FIXME: This is needed for 7750, but do we need it for the - * 7750S too? For now, assume we do.. -- PFM - */ - cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG; - - break; - case 0x1100: - cpu_data->type = CPU_SH7751; - break; - case 0x8000: - cpu_data->type = CPU_ST40RA; - break; - case 0x8100: - cpu_data->type = CPU_ST40GX1; - break; - case 0x700: - cpu_data->type = CPU_SH4_501; - cpu_data->icache.ways = 2; - cpu_data->dcache.ways = 2; - - /* No FPU on the SH4-500 series.. */ - cpu_data->flags &= ~CPU_HAS_FPU; - break; - case 0x600: - cpu_data->type = CPU_SH4_202; - cpu_data->icache.ways = 2; - cpu_data->dcache.ways = 2; - break; - case 0x500 ... 0x501: - switch (prr) { - case 0x10: cpu_data->type = CPU_SH7750R; break; - case 0x11: cpu_data->type = CPU_SH7751R; break; - case 0x50: cpu_data->type = CPU_SH7760; break; - } - - cpu_data->icache.ways = 2; - cpu_data->dcache.ways = 2; - - break; - default: - cpu_data->type = CPU_SH_NONE; - break; - } - - /* - * On anything that's not a direct-mapped cache, look to the CVR - * for I/D-cache specifics. - */ - if (cpu_data->icache.ways > 1) { - size = sizes[(cvr >> 20) & 0xf]; - cpu_data->icache.way_incr = size / cpu_data->icache.ways; - cpu_data->icache.sets = (size >> 6); - cpu_data->icache.entry_mask = - ((size / cpu_data->icache.ways) - (1 << 5)); - } - - if (cpu_data->dcache.ways > 1) { - size = sizes[(cvr >> 16) & 0xf]; - cpu_data->dcache.way_incr = size / cpu_data->dcache.ways; - cpu_data->dcache.sets = (size >> 6); - cpu_data->dcache.entry_mask = - ((size / cpu_data->dcache.ways) - (1 << 5)); - } - - return 0; -} - /* * SH-4 has virtually indexed and physically tagged cache. */ -- 2.53.0