From c8eae71dc81af15809d87d7aabb94810cea9577d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 12 Jun 2007 13:04:09 +0100 Subject: [MIPS] 20K: Handle WAIT related bugs according to errata information We used to avoid the WAIT entirely on the 20K but really only need to do this on early revs of the 20K. Without this a 20K was a bit of a power hog. Well, in the lower power power hog category ;-) Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'arch/mips/kernel/cpu-probe.c') diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index ab755ea26c6..0fc90ba16ae 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -137,7 +137,6 @@ static inline void check_wait(void) case CPU_4KEC: case CPU_4KSC: case CPU_5KC: -/* case CPU_20KC:*/ case CPU_24K: case CPU_25KF: case CPU_34K: @@ -156,6 +155,17 @@ static inline void check_wait(void) if (allow_au1k_wait) cpu_wait = au1k_wait; break; + case CPU_20KC: + /* + * WAIT on Rev1.0 has E1, E2, E3 and E16. + * WAIT on Rev2.0 and Rev3.0 has E16. + * Rev3.1 WAIT is nop, why bother + */ + if ((c->processor_id & 0xff) <= 0x64) + break; + + cpu_wait = r4k_wait; + break; case CPU_RM9000: if ((c->processor_id & 0x00ff) >= 0x40) cpu_wait = r4k_wait; -- cgit v1.2.3-70-g09d2 From 4b3e975e4a06f1710693c5aa51b8f98facfa9863 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 21 Jun 2007 00:22:34 +0100 Subject: [MIPS] Fix scheduling latency issue on 24K, 34K and 74K cores The idle loop goes to sleep using the WAIT instruction if !need_resched(). This has is suffering from from a race condition that if if just after need_resched has returned 0 an interrupt might set TIF_NEED_RESCHED but we've just completed the test so go to sleep anyway. This would be trivial to fix by just disabling interrupts during that sequence as in: local_irq_disable(); if (!need_resched()) __asm__("wait"); local_irq_enable(); but the processor architecture leaves it undefined if a processor calling WAIT with interrupts disabled will ever restart its pipeline and indeed some processors have made use of the freedom provided by the architecture definition. This has been resolved and the Config7.WII bit indicates that the use of WAIT is safe on 24K, 24KE and 34K cores. It also is safe on 74K starting revision 2.1.0 so enable the use of WAIT with interrupts disabled for 74K based on a c0_prid of at least that. Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 15 +++++++++++++-- include/asm-mips/mipsregs.h | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'arch/mips/kernel/cpu-probe.c') diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 0fc90ba16ae..b12eeee0e97 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -137,13 +137,24 @@ static inline void check_wait(void) case CPU_4KEC: case CPU_4KSC: case CPU_5KC: - case CPU_24K: case CPU_25KF: + case CPU_PR4450: + cpu_wait = r4k_wait; + break; + + case CPU_24K: case CPU_34K: + cpu_wait = r4k_wait; + if (read_c0_config7() & MIPS_CONF7_WII) + cpu_wait = r4k_wait_irqoff; + break; + case CPU_74K: - case CPU_PR4450: cpu_wait = r4k_wait; + if ((c->processor_id & 0xff) >= PRID_REV_ENCODE_332(2, 1, 0)) + cpu_wait = r4k_wait_irqoff; break; + case CPU_TX49XX: cpu_wait = r4k_wait_irqoff; break; diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h index 9985cb7c16e..89c81922d47 100644 --- a/include/asm-mips/mipsregs.h +++ b/include/asm-mips/mipsregs.h @@ -534,6 +534,8 @@ #define MIPS_CONF3_LPA (_ULCAST_(1) << 7) #define MIPS_CONF3_DSP (_ULCAST_(1) << 10) +#define MIPS_CONF7_WII (_ULCAST_(1) << 31) + /* * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register. */ -- cgit v1.2.3-70-g09d2 From a36920200c5b89d56120a5e839fe4a603d51b16c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 10 Jul 2007 17:33:02 +0100 Subject: [MIPS] Enable support for the userlocal hardware register Which will cut down the cost of RDHWR $29 which is used to obtain the TLS pointer and so far being emulated in software down to a single cycle operation. Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 2 ++ arch/mips/kernel/syscall.c | 5 ++--- arch/mips/kernel/traps.c | 9 ++++++++- include/asm-mips/cpu-features.h | 4 ++++ include/asm-mips/cpu.h | 1 + include/asm-mips/mipsregs.h | 6 +++++- include/asm-mips/system.h | 2 ++ 7 files changed, 24 insertions(+), 5 deletions(-) (limited to 'arch/mips/kernel/cpu-probe.c') diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index b12eeee0e97..27fc1843423 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -588,6 +588,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->options |= MIPS_CPU_VEIC; if (config3 & MIPS_CONF3_MT) c->ases |= MIPS_ASE_MIPSMT; + if (config3 & MIPS_CONF3_ULRI) + c->options |= MIPS_CPU_ULRI; return config3 & MIPS_CONF_M; } diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 9dd5a2df8ea..b947c61c0cc 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -272,9 +272,8 @@ asmlinkage int sys_set_thread_area(unsigned long addr) struct thread_info *ti = task_thread_info(current); ti->tp_value = addr; - - /* If some future MIPS implementation has this register in hardware, - * we will need to update it here (and in context switches). */ + if (cpu_has_userlocal) + write_c0_userlocal(addr); return 0; } diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c598e890a88..9b19a84d11e 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1341,7 +1341,14 @@ void __init per_cpu_trap_init(void) set_c0_status(ST0_MX); #ifdef CONFIG_CPU_MIPSR2 - write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */ + if (cpu_has_mips_r2) { + unsigned int enable = 0x0000000f; + + if (cpu_has_userlocal) + enable |= (1 << 29); + + write_c0_hwrena(enable); + } #endif #ifdef CONFIG_MIPS_MT_SMTC diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h index 5e4bed123b4..d95a83e3e1d 100644 --- a/include/asm-mips/cpu-features.h +++ b/include/asm-mips/cpu-features.h @@ -150,6 +150,10 @@ #define cpu_has_mipsmt (cpu_data[0].ases & MIPS_ASE_MIPSMT) #endif +#ifndef cpu_has_userlocal +#define cpu_has_userlocal (cpu_data[0].options & MIPS_CPU_ULRI) +#endif + #ifdef CONFIG_32BIT # ifndef cpu_has_nofpuex # define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX) diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h index 2924069075e..49c1f001186 100644 --- a/include/asm-mips/cpu.h +++ b/include/asm-mips/cpu.h @@ -257,6 +257,7 @@ #define MIPS_CPU_PREFETCH 0x00080000 /* CPU has usable prefetch */ #define MIPS_CPU_VINT 0x00100000 /* CPU supports MIPSR2 vectored interrupts */ #define MIPS_CPU_VEIC 0x00200000 /* CPU supports MIPSR2 external interrupt controller mode */ +#define MIPS_CPU_ULRI 0x00400000 /* CPU has ULRI feature */ /* * CPU ASE encodings diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h index 89c81922d47..668db02c280 100644 --- a/include/asm-mips/mipsregs.h +++ b/include/asm-mips/mipsregs.h @@ -7,7 +7,7 @@ * Copyright (C) 2000 Silicon Graphics, Inc. * Modified for further R[236]000 support by Paul M. Antoine, 1996. * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2000, 07 MIPS Technologies, Inc. * Copyright (C) 2003, 2004 Maciej W. Rozycki */ #ifndef _ASM_MIPSREGS_H @@ -533,6 +533,7 @@ #define MIPS_CONF3_VEIC (_ULCAST_(1) << 6) #define MIPS_CONF3_LPA (_ULCAST_(1) << 7) #define MIPS_CONF3_DSP (_ULCAST_(1) << 10) +#define MIPS_CONF3_ULRI (_ULCAST_(1) << 13) #define MIPS_CONF7_WII (_ULCAST_(1) << 31) @@ -772,6 +773,9 @@ do { \ #define read_c0_context() __read_ulong_c0_register($4, 0) #define write_c0_context(val) __write_ulong_c0_register($4, 0, val) +#define read_c0_userlocal() __read_ulong_c0_register($4, 2) +#define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val) + #define read_c0_pagemask() __read_32bit_c0_register($5, 0) #define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val) diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index 9b3a8dd2c3d..be64fc55562 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h @@ -67,6 +67,8 @@ do { \ (last) = resume(prev, next, task_thread_info(next)); \ if (cpu_has_dsp) \ __restore_dsp(current); \ + if (cpu_has_userlocal) \ + write_c0_userlocal(task_thread_info(current)->tp_value);\ } while(0) /* -- cgit v1.2.3-70-g09d2 From 2a21c7300b53b744d16903256a172d9cbcfdd03e Mon Sep 17 00:00:00 2001 From: Fuxin Zhang Date: Wed, 6 Jun 2007 14:52:43 +0800 Subject: [MIPS] define Hit_Invalidate_I to Index_Invalidate_I for loongson2 Signed-off-by: Fuxin Zhang Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 22 ++++++++++++++++++ arch/mips/Makefile | 1 + arch/mips/kernel/Makefile | 13 ++++++----- arch/mips/kernel/cpu-probe.c | 8 +++++++ arch/mips/kernel/proc.c | 1 + arch/mips/lib/Makefile | 1 + arch/mips/mm/Makefile | 1 + arch/mips/mm/c-r4k.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ arch/mips/mm/tlb-r4k.c | 23 ++++++++++++++++++- arch/mips/mm/tlbex.c | 8 ++++--- include/asm-mips/cacheops.h | 4 ++++ include/asm-mips/cpu.h | 7 +++++- include/asm-mips/module.h | 2 ++ 13 files changed, 134 insertions(+), 11 deletions(-) (limited to 'arch/mips/kernel/cpu-probe.c') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 624c31cd807..c8d954d6f2c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -894,6 +894,16 @@ choice prompt "CPU type" default CPU_R4X00 +config CPU_LOONGSON2 + bool "Loongson 2" + depends on SYS_HAS_CPU_LOONGSON2 + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + help + The Loongson 2E processor implements the MIPS III instruction set + with many extensions. + config CPU_MIPS32_R1 bool "MIPS32 Release 1" depends on SYS_HAS_CPU_MIPS32_R1 @@ -1104,6 +1114,9 @@ config CPU_SB1 endchoice +config SYS_HAS_CPU_LOONGSON2 + bool + config SYS_HAS_CPU_MIPS32_R1 bool @@ -1438,6 +1451,15 @@ config CPU_HAS_SMARTMIPS config CPU_HAS_WB bool +config 64BIT_CONTEXT + bool "Save 64bit integer registers" + depends on 32BIT && CPU_LOONGSON2 + help + Loongson2 CPU is 64bit , when used in 32BIT mode, its integer + registers can still be accessed as 64bit, mainly for multimedia + instructions. We must have all 64bit save/restored to make sure + those instructions to get correct result. + # # Vectored interrupt mode is an R2 feature # diff --git a/arch/mips/Makefile b/arch/mips/Makefile index fc09769b3dd..1e4579cc54e 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -118,6 +118,7 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON2) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ -Wa,-mips32 -Wa,--trap cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index bb25dd8ce43..73983eee143 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -14,14 +14,15 @@ binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \ obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_MODULES) += mips_ksyms.o module.o +obj-$(CONFIG_CPU_LOONGSON2) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o -obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o -obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R4000) += r4k_fpu.o r4k_switch.o -obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R4300) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R4X00) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R5000) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R5432) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R8000) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_RM7000) += r4k_fpu.o r4k_switch.o @@ -29,9 +30,9 @@ obj-$(CONFIG_CPU_RM9000) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_NEVADA) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R10000) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_SB1) += r4k_fpu.o r4k_switch.o -obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o -obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o -obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o +obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 27fc1843423..23d8a3b7dd7 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -485,6 +485,14 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c) MIPS_CPU_LLSC; c->tlbsize = 64; break; + case PRID_IMP_LOONGSON2: + c->cputype = CPU_LOONGSON2; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | + MIPS_CPU_FPU | MIPS_CPU_LLSC | + MIPS_CPU_32FPR; + c->tlbsize = 64; + break; } } diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index eb7730d6793..ec04f5a1a5e 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -83,6 +83,7 @@ static const char *cpu_name[] = { [CPU_VR4181A] = "NEC VR4181A", [CPU_SR71000] = "Sandcraft SR71000", [CPU_PR4450] = "Philips PR4450", + [CPU_LOONGSON2] = "ICT Loongson-2", }; diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 1a484e430b3..91ed1eb3310 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -8,6 +8,7 @@ lib-y += csum_partial.o memcpy.o memcpy-inatomic.o memset.o strlen_user.o \ obj-y += iomap.o obj-$(CONFIG_PCI) += iomap-pci.o +obj-$(CONFIG_CPU_LOONGSON2) += dump_tlb.o obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile index 293697b1560..19a0e544c4e 100644 --- a/arch/mips/mm/Makefile +++ b/arch/mips/mm/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o obj-$(CONFIG_64BIT) += pgtable-64.o obj-$(CONFIG_HIGHMEM) += highmem.o +obj-$(CONFIG_CPU_LOONGSON2) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index df04a315d83..be96231dccb 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -335,6 +335,10 @@ static void r4k_flush_cache_all(void) static inline void local_r4k___flush_cache_all(void * args) { +#if defined(CONFIG_CPU_LOONGSON2) + r4k_blast_scache(); + return; +#endif r4k_blast_dcache(); r4k_blast_icache(); @@ -848,6 +852,24 @@ static void __init probe_pcache(void) c->options |= MIPS_CPU_PREFETCH; break; + case CPU_LOONGSON2: + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + if (prid & 0x3) + c->icache.ways = 4; + else + c->icache.ways = 2; + c->icache.waybit = 0; + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + if (prid & 0x3) + c->dcache.ways = 4; + else + c->dcache.ways = 2; + c->dcache.waybit = 0; + break; + default: if (!(config & MIPS_CONF_M)) panic("Don't know how to probe P-caches on this cpu."); @@ -963,6 +985,14 @@ static void __init probe_pcache(void) break; } +#ifdef CONFIG_CPU_LOONGSON2 + /* + * LOONGSON2 has 4 way icache, but when using indexed cache op, + * one op will act on all 4 ways + */ + c->icache.ways = 1; +#endif + printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n", icache_size >> 10, cpu_has_vtag_icache ? "virtually tagged" : "physically tagged", @@ -1036,6 +1066,24 @@ static int __init probe_scache(void) return 1; } +#if defined(CONFIG_CPU_LOONGSON2) +static void __init loongson2_sc_init(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + + scache_size = 512*1024; + c->scache.linesz = 32; + c->scache.ways = 4; + c->scache.waybit = 0; + c->scache.waysize = scache_size / (c->scache.ways); + c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways); + pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n", + scache_size >> 10, way_string[c->scache.ways], c->scache.linesz); + + c->options |= MIPS_CPU_INCLUSIVE_CACHES; +} +#endif + extern int r5k_sc_init(void); extern int rm7k_sc_init(void); extern int mips_sc_init(void); @@ -1085,6 +1133,12 @@ static void __init setup_scache(void) #endif return; +#if defined(CONFIG_CPU_LOONGSON2) + case CPU_LOONGSON2: + loongson2_sc_init(); + return; +#endif + default: if (c->isa_level == MIPS_CPU_ISA_M32R1 || c->isa_level == MIPS_CPU_ISA_M32R2 || diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 65160d4984d..dcd6913dc1f 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -48,6 +48,22 @@ extern void build_tlb_refill_handler(void); #endif /* CONFIG_MIPS_MT_SMTC */ +#if defined(CONFIG_CPU_LOONGSON2) +/* + * LOONGSON2 has a 4 entry itlb which is a subset of dtlb, + * unfortrunately, itlb is not totally transparent to software. + */ +#define FLUSH_ITLB write_c0_diag(4); + +#define FLUSH_ITLB_VM(vma) { if ((vma)->vm_flags & VM_EXEC) write_c0_diag(4); } + +#else + +#define FLUSH_ITLB +#define FLUSH_ITLB_VM(vma) + +#endif + void local_flush_tlb_all(void) { unsigned long flags; @@ -73,6 +89,7 @@ void local_flush_tlb_all(void) } tlbw_use_hazard(); write_c0_entryhi(old_ctx); + FLUSH_ITLB; EXIT_CRITICAL(flags); } @@ -136,6 +153,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, } else { drop_mmu_context(mm, cpu); } + FLUSH_ITLB; EXIT_CRITICAL(flags); } } @@ -178,6 +196,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) } else { local_flush_tlb_all(); } + FLUSH_ITLB; EXIT_CRITICAL(flags); } @@ -210,6 +229,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) finish: write_c0_entryhi(oldpid); + FLUSH_ITLB_VM(vma); EXIT_CRITICAL(flags); } } @@ -241,7 +261,7 @@ void local_flush_tlb_one(unsigned long page) tlbw_use_hazard(); } write_c0_entryhi(oldpid); - + FLUSH_ITLB; EXIT_CRITICAL(flags); } @@ -293,6 +313,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) else tlb_write_indexed(); tlbw_use_hazard(); + FLUSH_ITLB_VM(vma); EXIT_CRITICAL(flags); } diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index e7149290d1c..4ec0964b839 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -893,6 +893,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l, case CPU_4KSC: case CPU_20KC: case CPU_25KF: + case CPU_LOONGSON2: tlbw(p); break; @@ -1276,7 +1277,8 @@ static void __init build_r4000_tlb_refill_handler(void) * need three, with the second nop'ed and the third being * unused. */ -#ifdef CONFIG_32BIT + /* Loongson2 ebase is different than r4k, we have more space */ +#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2) if ((p - tlb_handler) > 64) panic("TLB refill handler space exceeded"); #else @@ -1289,7 +1291,7 @@ static void __init build_r4000_tlb_refill_handler(void) /* * Now fold the handler in the TLB refill handler space. */ -#ifdef CONFIG_32BIT +#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2) f = final_handler; /* Simplest case, just copy the handler. */ copy_handler(relocs, labels, tlb_handler, p, f); @@ -1336,7 +1338,7 @@ static void __init build_r4000_tlb_refill_handler(void) final_len); f = final_handler; -#ifdef CONFIG_64BIT +#if defined(CONFIG_64BIT) && !defined(CONFIG_CPU_LOONGSON2) if (final_len > 32) final_len = 64; else diff --git a/include/asm-mips/cacheops.h b/include/asm-mips/cacheops.h index c4a1ec31ff6..df7f2deb3b5 100644 --- a/include/asm-mips/cacheops.h +++ b/include/asm-mips/cacheops.h @@ -20,7 +20,11 @@ #define Index_Load_Tag_D 0x05 #define Index_Store_Tag_I 0x08 #define Index_Store_Tag_D 0x09 +#if defined(CONFIG_CPU_LOONGSON2) +#define Hit_Invalidate_I 0x00 +#else #define Hit_Invalidate_I 0x10 +#endif #define Hit_Invalidate_D 0x11 #define Hit_Writeback_Inv_D 0x15 diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h index 49c1f001186..a3623954dad 100644 --- a/include/asm-mips/cpu.h +++ b/include/asm-mips/cpu.h @@ -89,6 +89,8 @@ #define PRID_IMP_34K 0x9500 #define PRID_IMP_24KE 0x9600 #define PRID_IMP_74K 0x9700 +#define PRID_IMP_LOONGSON1 0x4200 +#define PRID_IMP_LOONGSON2 0x6300 /* * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE @@ -211,7 +213,10 @@ #define CPU_SB1A 62 #define CPU_74K 63 #define CPU_R14000 64 -#define CPU_LAST 64 +#define CPU_LOONGSON1 65 +#define CPU_LOONGSON2 66 + +#define CPU_LAST 66 /* * ISA Level encodings diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h index c5ef324fd69..de6d09ebbd8 100644 --- a/include/asm-mips/module.h +++ b/include/asm-mips/module.h @@ -112,6 +112,8 @@ search_module_dbetables(unsigned long addr) #define MODULE_PROC_FAMILY "RM9000 " #elif defined CONFIG_CPU_SB1 #define MODULE_PROC_FAMILY "SB1 " +#elif defined CONFIG_CPU_LOONGSON2 +#define MODULE_PROC_FAMILY "LOONGSON2 " #else #error MODULE_PROC_FAMILY undefined for your processor configuration #endif -- cgit v1.2.3-70-g09d2 From 9267a30d1dc7dcd7cadb5eb6a5bbfed703feeefa Mon Sep 17 00:00:00 2001 From: Marc St-Jean Date: Thu, 14 Jun 2007 15:55:31 -0600 Subject: [MIPS] PMC MSP71xx mips common Patch to add mips common support for the PMC-Sierra MSP71xx devices. Signed-off-by: Marc St-Jean Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 35 +++++++++++++++++++++++++++++++++ arch/mips/Makefile | 11 ++++++++++- arch/mips/kernel/cpu-probe.c | 20 +++++++++++++++++++ arch/mips/kernel/head.S | 5 ++++- arch/mips/kernel/traps.c | 6 ++++++ arch/mips/pmc-sierra/Kconfig | 46 ++++++++++++++++++++++++++++++++++++++++++++ include/asm-mips/bootinfo.h | 12 ++++++++++++ include/asm-mips/cpu.h | 2 ++ include/asm-mips/mipsregs.h | 33 +++++++++++++++++++++++++++++++ include/asm-mips/war.h | 11 +++++++++++ 10 files changed, 179 insertions(+), 2 deletions(-) (limited to 'arch/mips/kernel/cpu-probe.c') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 3994f611ec2..2076d472ea9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -250,6 +250,7 @@ config MIPS_SIM select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select IRQ_CPU + select BOOT_RAW select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2 select SYS_HAS_EARLY_PRINTK @@ -333,6 +334,27 @@ config MACH_VR41XX select SYS_HAS_CPU_VR41XX select GENERIC_HARDIRQS_NO__DO_IRQ +config PMC_MSP + bool "PMC-Sierra MSP chipsets" + depends on EXPERIMENTAL + select DMA_NONCOHERENT + select SWAP_IO_SPACE + select NO_EXCEPT_FILL + select BOOT_RAW + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_KGDB + select IRQ_CPU + select SERIAL_8250 + select SERIAL_8250_CONSOLE + help + This adds support for the PMC-Sierra family of Multi-Service + Processor System-On-A-Chips. These parts include a number + of integrated peripherals, interfaces and DSPs in addition to + a variety of MIPS cores. + config PMC_YOSEMITE bool "PMC-Sierra Yosemite eval board" select DMA_COHERENT @@ -706,6 +728,9 @@ config ARC config ARCH_MAY_HAVE_PC_FDC bool +config BOOT_RAW + bool + config DMA_COHERENT bool @@ -812,6 +837,12 @@ config IRQ_CPU_RM7K config IRQ_CPU_RM9K bool +config IRQ_MSP_SLP + bool + +config IRQ_MSP_CIC + bool + config IRQ_MV64340 bool @@ -825,6 +856,9 @@ config MIPS_BOARDS_GEN config PCI_GT64XXX_PCI0 bool +config NO_EXCEPT_FILL + bool + config MIPS_TX3927 bool select HAS_TXX9_SERIAL @@ -886,6 +920,7 @@ config MIPS_L1_CACHE_SHIFT int default "4" if MACH_DECSTATION || SNI_RM default "7" if SGI_IP27 + default "4" if PMC_MSP4200_EVAL default "5" config HAVE_STD_PC_SERIAL_PORT diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 6642ee5fdc4..2b9af2fd550 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -342,6 +342,14 @@ core-$(CONFIG_MOMENCO_OCELOT) += arch/mips/gt64120/common/ \ cflags-$(CONFIG_MOMENCO_OCELOT) += -Iinclude/asm-mips/mach-ocelot load-$(CONFIG_MOMENCO_OCELOT) += 0xffffffff80100000 +# +# PMC-Sierra MSP SOCs +# +core-$(CONFIG_PMC_MSP) += arch/mips/pmc-sierra/msp71xx/ +cflags-$(CONFIG_PMC_MSP) += -Iinclude/asm-mips/pmc-sierra/msp71xx \ + -mno-branch-likely +load-$(CONFIG_PMC_MSP) += 0xffffffff80100000 + # # PMC-Sierra Yosemite # @@ -595,7 +603,8 @@ JIFFIES = jiffies_64 endif AFLAGS += $(cflags-y) -CFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) \ + -D"VMLINUX_LOAD_ADDRESS=$(load-y)" LDFLAGS += -m $(ld-emul) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 23d8a3b7dd7..c6b8b074a81 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -186,9 +186,29 @@ static inline void check_wait(void) } } +static inline void check_errata(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + + switch (c->cputype) { + case CPU_34K: + /* + * Erratum "RPS May Cause Incorrect Instruction Execution" + * This code only handles VPE0, any SMP/SMTC/RTOS code + * making use of VPE1 will be responsable for that VPE. + */ + if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2) + write_c0_config7(read_c0_config7() | MIPS_CONF7_RPS); + break; + default: + break; + } +} + void __init check_bugs32(void) { check_wait(); + check_errata(); } /* diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 1f096aa35bc..f78538eceef 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -129,16 +130,18 @@ #endif .endm +#ifndef CONFIG_NO_EXCEPT_FILL /* * Reserved space for exception handlers. * Necessary for machines which link their kernels at KSEG0. */ .fill 0x400 +#endif EXPORT(stext) # used for profiling EXPORT(_stext) -#ifndef CONFIG_MIPS_SIM +#ifdef CONFIG_BOOT_RAW /* * Give us a fighting chance of running if execution beings at the * kernel load address. This is needed because this platform does diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 9b19a84d11e..80ea4fa95bd 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -69,6 +69,7 @@ extern asmlinkage void handle_reserved(void); extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int has_fpu); +void (*board_watchpoint_handler)(struct pt_regs *regs); void (*board_be_init)(void); int (*board_be_handler)(struct pt_regs *regs, int is_fixup); void (*board_nmi_handler_setup)(void); @@ -833,6 +834,11 @@ asmlinkage void do_mdmx(struct pt_regs *regs) asmlinkage void do_watch(struct pt_regs *regs) { + if (board_watchpoint_handler) { + (*board_watchpoint_handler)(regs); + return; + } + /* * We use the watch exception where available to detect stack * overflows. diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig index 24d514c9dff..abbd0bbfabd 100644 --- a/arch/mips/pmc-sierra/Kconfig +++ b/arch/mips/pmc-sierra/Kconfig @@ -1,3 +1,49 @@ +choice + prompt "PMC-Sierra MSP SOC type" + depends on PMC_MSP + +config PMC_MSP4200_EVAL + bool "PMC-Sierra MSP4200 Eval Board" + select IRQ_MSP_SLP + select HW_HAS_PCI + +config PMC_MSP4200_GW + bool "PMC-Sierra MSP4200 VoIP Gateway" + select IRQ_MSP_SLP + select HW_HAS_PCI + +config PMC_MSP7120_EVAL + bool "PMC-Sierra MSP7120 Eval Board" + select SYS_SUPPORTS_MULTITHREADING + select IRQ_MSP_CIC + select HW_HAS_PCI + +config PMC_MSP7120_GW + bool "PMC-Sierra MSP7120 Residential Gateway" + select SYS_SUPPORTS_MULTITHREADING + select IRQ_MSP_CIC + select HW_HAS_PCI + +config PMC_MSP7120_FPGA + bool "PMC-Sierra MSP7120 FPGA" + select SYS_SUPPORTS_MULTITHREADING + select IRQ_MSP_CIC + select HW_HAS_PCI + +endchoice + +menu "Options for PMC-Sierra MSP chipsets" + depends on PMC_MSP + +config PMC_MSP_EMBEDDED_ROOTFS + bool "Root filesystem embedded in kernel image" + select MTD + select MTD_BLOCK + select MTD_PMC_MSP_RAMROOT + select MTD_RAM + +endmenu + config HYPERTRANSPORT bool "Hypertransport Support for PMC-Sierra Yosemite" depends on PMC_YOSEMITE diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h index 12f9d7139eb..94fc9be1aab 100644 --- a/include/asm-mips/bootinfo.h +++ b/include/asm-mips/bootinfo.h @@ -213,6 +213,18 @@ #define MACH_GROUP_LEMOTE 27 #define MACH_LEMOTE_FULONG 0 +/* + * Valid machtype for group PMC-MSP + */ +#define MACH_GROUP_MSP 26 /* PMC-Sierra MSP boards/CPUs */ +#define MACH_MSP4200_EVAL 0 /* PMC-Sierra MSP4200 Evaluation */ +#define MACH_MSP4200_GW 1 /* PMC-Sierra MSP4200 Gateway demo */ +#define MACH_MSP4200_FPGA 2 /* PMC-Sierra MSP4200 Emulation */ +#define MACH_MSP7120_EVAL 3 /* PMC-Sierra MSP7120 Evaluation */ +#define MACH_MSP7120_GW 4 /* PMC-Sierra MSP7120 Residential GW */ +#define MACH_MSP7120_FPGA 5 /* PMC-Sierra MSP7120 Emulation */ +#define MACH_MSP_OTHER 255 /* PMC-Sierra unknown board type */ + #define CL_SIZE COMMAND_LINE_SIZE const char *get_system_type(void); diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h index a3623954dad..3857358fb6d 100644 --- a/include/asm-mips/cpu.h +++ b/include/asm-mips/cpu.h @@ -109,6 +109,7 @@ * Definitions for 7:0 on legacy processors */ +#define PRID_REV_MASK 0x00ff #define PRID_REV_TX4927 0x0022 #define PRID_REV_TX4937 0x0030 @@ -125,6 +126,7 @@ #define PRID_REV_VR4122 0x0070 #define PRID_REV_VR4181A 0x0070 /* Same as VR4122 */ #define PRID_REV_VR4130 0x0080 +#define PRID_REV_34K_V1_0_2 0x0022 /* * Older processors used to encode processor version and revision in two diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h index 668db02c280..706b3691f57 100644 --- a/include/asm-mips/mipsregs.h +++ b/include/asm-mips/mipsregs.h @@ -15,6 +15,7 @@ #include #include +#include /* * The following macros are especially useful for __asm__ @@ -537,6 +538,9 @@ #define MIPS_CONF7_WII (_ULCAST_(1) << 31) +#define MIPS_CONF7_RPS (_ULCAST_(1) << 2) + + /* * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register. */ @@ -1298,10 +1302,39 @@ static inline void tlb_probe(void) static inline void tlb_read(void) { +#if MIPS34K_MISSED_ITLB_WAR + int res = 0; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips32r2 \n" + " .word 0x41610001 # dvpe $1 \n" + " move %0, $1 \n" + " ehb \n" + " .set pop \n" + : "=r" (res)); + + instruction_hazard(); +#endif + __asm__ __volatile__( ".set noreorder\n\t" "tlbr\n\t" ".set reorder"); + +#if MIPS34K_MISSED_ITLB_WAR + if ((res & _ULCAST_(1))) + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips32r2 \n" + " .word 0x41600021 # evpe \n" + " ehb \n" + " .set pop \n"); +#endif } static inline void tlb_write_indexed(void) diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h index c507f1b8014..45cb8272483 100644 --- a/include/asm-mips/war.h +++ b/include/asm-mips/war.h @@ -197,6 +197,14 @@ #define R10000_LLSC_WAR 1 #endif +/* + * 34K core erratum: "Problems Executing the TLBR Instruction" + */ +#if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \ + defined(CONFIG_PMC_MSP7120_FPGA) +#define MIPS34K_MISSED_ITLB_WAR 1 +#endif + /* * Workarounds default to off */ @@ -236,5 +244,8 @@ #ifndef R10000_LLSC_WAR #define R10000_LLSC_WAR 0 #endif +#ifndef MIPS34K_MISSED_ITLB_WAR +#define MIPS34K_MISSED_ITLB_WAR 0 +#endif #endif /* _ASM_WAR_H */ -- cgit v1.2.3-70-g09d2