aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Kconfig22
-rw-r--r--arch/mips/Makefile1
-rw-r--r--arch/mips/kernel/Makefile13
-rw-r--r--arch/mips/kernel/cpu-probe.c8
-rw-r--r--arch/mips/kernel/proc.c1
-rw-r--r--arch/mips/lib/Makefile1
-rw-r--r--arch/mips/mm/Makefile1
-rw-r--r--arch/mips/mm/c-r4k.c54
-rw-r--r--arch/mips/mm/tlb-r4k.c23
-rw-r--r--arch/mips/mm/tlbex.c8
10 files changed, 122 insertions, 10 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 624c31cd8077..c8d954d6f2c4 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -894,6 +894,16 @@ choice
894 prompt "CPU type" 894 prompt "CPU type"
895 default CPU_R4X00 895 default CPU_R4X00
896 896
897config CPU_LOONGSON2
898 bool "Loongson 2"
899 depends on SYS_HAS_CPU_LOONGSON2
900 select CPU_SUPPORTS_32BIT_KERNEL
901 select CPU_SUPPORTS_64BIT_KERNEL
902 select CPU_SUPPORTS_HIGHMEM
903 help
904 The Loongson 2E processor implements the MIPS III instruction set
905 with many extensions.
906
897config CPU_MIPS32_R1 907config CPU_MIPS32_R1
898 bool "MIPS32 Release 1" 908 bool "MIPS32 Release 1"
899 depends on SYS_HAS_CPU_MIPS32_R1 909 depends on SYS_HAS_CPU_MIPS32_R1
@@ -1104,6 +1114,9 @@ config CPU_SB1
1104 1114
1105endchoice 1115endchoice
1106 1116
1117config SYS_HAS_CPU_LOONGSON2
1118 bool
1119
1107config SYS_HAS_CPU_MIPS32_R1 1120config SYS_HAS_CPU_MIPS32_R1
1108 bool 1121 bool
1109 1122
@@ -1438,6 +1451,15 @@ config CPU_HAS_SMARTMIPS
1438config CPU_HAS_WB 1451config CPU_HAS_WB
1439 bool 1452 bool
1440 1453
1454config 64BIT_CONTEXT
1455 bool "Save 64bit integer registers"
1456 depends on 32BIT && CPU_LOONGSON2
1457 help
1458 Loongson2 CPU is 64bit , when used in 32BIT mode, its integer
1459 registers can still be accessed as 64bit, mainly for multimedia
1460 instructions. We must have all 64bit save/restored to make sure
1461 those instructions to get correct result.
1462
1441# 1463#
1442# Vectored interrupt mode is an R2 feature 1464# Vectored interrupt mode is an R2 feature
1443# 1465#
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index fc09769b3dd4..1e4579cc54ef 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -118,6 +118,7 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap
118cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap 118cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap
119cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap 119cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap
120cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap 120cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
121cflags-$(CONFIG_CPU_LOONGSON2) += -march=r4600 -Wa,--trap
121cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ 122cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
122 -Wa,-mips32 -Wa,--trap 123 -Wa,-mips32 -Wa,--trap
123cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ 124cflags-$(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 bb25dd8ce437..73983eee1431 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 \
14obj-$(CONFIG_STACKTRACE) += stacktrace.o 14obj-$(CONFIG_STACKTRACE) += stacktrace.o
15obj-$(CONFIG_MODULES) += mips_ksyms.o module.o 15obj-$(CONFIG_MODULES) += mips_ksyms.o module.o
16 16
17obj-$(CONFIG_CPU_LOONGSON2) += r4k_fpu.o r4k_switch.o
18obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o
19obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o
17obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o 20obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
18obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
19obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o
20obj-$(CONFIG_CPU_R4000) += r4k_fpu.o r4k_switch.o 21obj-$(CONFIG_CPU_R4000) += r4k_fpu.o r4k_switch.o
21obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o
22obj-$(CONFIG_CPU_R4300) += r4k_fpu.o r4k_switch.o 22obj-$(CONFIG_CPU_R4300) += r4k_fpu.o r4k_switch.o
23obj-$(CONFIG_CPU_R4X00) += r4k_fpu.o r4k_switch.o 23obj-$(CONFIG_CPU_R4X00) += r4k_fpu.o r4k_switch.o
24obj-$(CONFIG_CPU_R5000) += r4k_fpu.o r4k_switch.o 24obj-$(CONFIG_CPU_R5000) += r4k_fpu.o r4k_switch.o
25obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
25obj-$(CONFIG_CPU_R5432) += r4k_fpu.o r4k_switch.o 26obj-$(CONFIG_CPU_R5432) += r4k_fpu.o r4k_switch.o
26obj-$(CONFIG_CPU_R8000) += r4k_fpu.o r4k_switch.o 27obj-$(CONFIG_CPU_R8000) += r4k_fpu.o r4k_switch.o
27obj-$(CONFIG_CPU_RM7000) += r4k_fpu.o r4k_switch.o 28obj-$(CONFIG_CPU_RM7000) += r4k_fpu.o r4k_switch.o
@@ -29,9 +30,9 @@ obj-$(CONFIG_CPU_RM9000) += r4k_fpu.o r4k_switch.o
29obj-$(CONFIG_CPU_NEVADA) += r4k_fpu.o r4k_switch.o 30obj-$(CONFIG_CPU_NEVADA) += r4k_fpu.o r4k_switch.o
30obj-$(CONFIG_CPU_R10000) += r4k_fpu.o r4k_switch.o 31obj-$(CONFIG_CPU_R10000) += r4k_fpu.o r4k_switch.o
31obj-$(CONFIG_CPU_SB1) += r4k_fpu.o r4k_switch.o 32obj-$(CONFIG_CPU_SB1) += r4k_fpu.o r4k_switch.o
32obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o 33obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
33obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o 34obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o
34obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o 35obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o
35 36
36obj-$(CONFIG_SMP) += smp.o 37obj-$(CONFIG_SMP) += smp.o
37 38
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 27fc1843423e..23d8a3b7dd75 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)
485 MIPS_CPU_LLSC; 485 MIPS_CPU_LLSC;
486 c->tlbsize = 64; 486 c->tlbsize = 64;
487 break; 487 break;
488 case PRID_IMP_LOONGSON2:
489 c->cputype = CPU_LOONGSON2;
490 c->isa_level = MIPS_CPU_ISA_III;
491 c->options = R4K_OPTS |
492 MIPS_CPU_FPU | MIPS_CPU_LLSC |
493 MIPS_CPU_32FPR;
494 c->tlbsize = 64;
495 break;
488 } 496 }
489} 497}
490 498
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index eb7730d67934..ec04f5a1a5ea 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -83,6 +83,7 @@ static const char *cpu_name[] = {
83 [CPU_VR4181A] = "NEC VR4181A", 83 [CPU_VR4181A] = "NEC VR4181A",
84 [CPU_SR71000] = "Sandcraft SR71000", 84 [CPU_SR71000] = "Sandcraft SR71000",
85 [CPU_PR4450] = "Philips PR4450", 85 [CPU_PR4450] = "Philips PR4450",
86 [CPU_LOONGSON2] = "ICT Loongson-2",
86}; 87};
87 88
88 89
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 1a484e430b3c..91ed1eb33102 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 \
8obj-y += iomap.o 8obj-y += iomap.o
9obj-$(CONFIG_PCI) += iomap-pci.o 9obj-$(CONFIG_PCI) += iomap-pci.o
10 10
11obj-$(CONFIG_CPU_LOONGSON2) += dump_tlb.o
11obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o 12obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
12obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o 13obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
13obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o 14obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 293697b15603..19a0e544c4e9 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o
9obj-$(CONFIG_64BIT) += pgtable-64.o 9obj-$(CONFIG_64BIT) += pgtable-64.o
10obj-$(CONFIG_HIGHMEM) += highmem.o 10obj-$(CONFIG_HIGHMEM) += highmem.o
11 11
12obj-$(CONFIG_CPU_LOONGSON2) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
12obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o 13obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
13obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o 14obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
14obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o 15obj-$(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 df04a315d830..be96231dccb6 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)
335 335
336static inline void local_r4k___flush_cache_all(void * args) 336static inline void local_r4k___flush_cache_all(void * args)
337{ 337{
338#if defined(CONFIG_CPU_LOONGSON2)
339 r4k_blast_scache();
340 return;
341#endif
338 r4k_blast_dcache(); 342 r4k_blast_dcache();
339 r4k_blast_icache(); 343 r4k_blast_icache();
340 344
@@ -848,6 +852,24 @@ static void __init probe_pcache(void)
848 c->options |= MIPS_CPU_PREFETCH; 852 c->options |= MIPS_CPU_PREFETCH;
849 break; 853 break;
850 854
855 case CPU_LOONGSON2:
856 icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
857 c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
858 if (prid & 0x3)
859 c->icache.ways = 4;
860 else
861 c->icache.ways = 2;
862 c->icache.waybit = 0;
863
864 dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
865 c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
866 if (prid & 0x3)
867 c->dcache.ways = 4;
868 else
869 c->dcache.ways = 2;
870 c->dcache.waybit = 0;
871 break;
872
851 default: 873 default:
852 if (!(config & MIPS_CONF_M)) 874 if (!(config & MIPS_CONF_M))
853 panic("Don't know how to probe P-caches on this cpu."); 875 panic("Don't know how to probe P-caches on this cpu.");
@@ -963,6 +985,14 @@ static void __init probe_pcache(void)
963 break; 985 break;
964 } 986 }
965 987
988#ifdef CONFIG_CPU_LOONGSON2
989 /*
990 * LOONGSON2 has 4 way icache, but when using indexed cache op,
991 * one op will act on all 4 ways
992 */
993 c->icache.ways = 1;
994#endif
995
966 printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n", 996 printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
967 icache_size >> 10, 997 icache_size >> 10,
968 cpu_has_vtag_icache ? "virtually tagged" : "physically tagged", 998 cpu_has_vtag_icache ? "virtually tagged" : "physically tagged",
@@ -1036,6 +1066,24 @@ static int __init probe_scache(void)
1036 return 1; 1066 return 1;
1037} 1067}
1038 1068
1069#if defined(CONFIG_CPU_LOONGSON2)
1070static void __init loongson2_sc_init(void)
1071{
1072 struct cpuinfo_mips *c = &current_cpu_data;
1073
1074 scache_size = 512*1024;
1075 c->scache.linesz = 32;
1076 c->scache.ways = 4;
1077 c->scache.waybit = 0;
1078 c->scache.waysize = scache_size / (c->scache.ways);
1079 c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
1080 pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
1081 scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
1082
1083 c->options |= MIPS_CPU_INCLUSIVE_CACHES;
1084}
1085#endif
1086
1039extern int r5k_sc_init(void); 1087extern int r5k_sc_init(void);
1040extern int rm7k_sc_init(void); 1088extern int rm7k_sc_init(void);
1041extern int mips_sc_init(void); 1089extern int mips_sc_init(void);
@@ -1085,6 +1133,12 @@ static void __init setup_scache(void)
1085#endif 1133#endif
1086 return; 1134 return;
1087 1135
1136#if defined(CONFIG_CPU_LOONGSON2)
1137 case CPU_LOONGSON2:
1138 loongson2_sc_init();
1139 return;
1140#endif
1141
1088 default: 1142 default:
1089 if (c->isa_level == MIPS_CPU_ISA_M32R1 || 1143 if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
1090 c->isa_level == MIPS_CPU_ISA_M32R2 || 1144 c->isa_level == MIPS_CPU_ISA_M32R2 ||
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 65160d4984d9..dcd6913dc1ff 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);
48 48
49#endif /* CONFIG_MIPS_MT_SMTC */ 49#endif /* CONFIG_MIPS_MT_SMTC */
50 50
51#if defined(CONFIG_CPU_LOONGSON2)
52/*
53 * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
54 * unfortrunately, itlb is not totally transparent to software.
55 */
56#define FLUSH_ITLB write_c0_diag(4);
57
58#define FLUSH_ITLB_VM(vma) { if ((vma)->vm_flags & VM_EXEC) write_c0_diag(4); }
59
60#else
61
62#define FLUSH_ITLB
63#define FLUSH_ITLB_VM(vma)
64
65#endif
66
51void local_flush_tlb_all(void) 67void local_flush_tlb_all(void)
52{ 68{
53 unsigned long flags; 69 unsigned long flags;
@@ -73,6 +89,7 @@ void local_flush_tlb_all(void)
73 } 89 }
74 tlbw_use_hazard(); 90 tlbw_use_hazard();
75 write_c0_entryhi(old_ctx); 91 write_c0_entryhi(old_ctx);
92 FLUSH_ITLB;
76 EXIT_CRITICAL(flags); 93 EXIT_CRITICAL(flags);
77} 94}
78 95
@@ -136,6 +153,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
136 } else { 153 } else {
137 drop_mmu_context(mm, cpu); 154 drop_mmu_context(mm, cpu);
138 } 155 }
156 FLUSH_ITLB;
139 EXIT_CRITICAL(flags); 157 EXIT_CRITICAL(flags);
140 } 158 }
141} 159}
@@ -178,6 +196,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
178 } else { 196 } else {
179 local_flush_tlb_all(); 197 local_flush_tlb_all();
180 } 198 }
199 FLUSH_ITLB;
181 EXIT_CRITICAL(flags); 200 EXIT_CRITICAL(flags);
182} 201}
183 202
@@ -210,6 +229,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
210 229
211 finish: 230 finish:
212 write_c0_entryhi(oldpid); 231 write_c0_entryhi(oldpid);
232 FLUSH_ITLB_VM(vma);
213 EXIT_CRITICAL(flags); 233 EXIT_CRITICAL(flags);
214 } 234 }
215} 235}
@@ -241,7 +261,7 @@ void local_flush_tlb_one(unsigned long page)
241 tlbw_use_hazard(); 261 tlbw_use_hazard();
242 } 262 }
243 write_c0_entryhi(oldpid); 263 write_c0_entryhi(oldpid);
244 264 FLUSH_ITLB;
245 EXIT_CRITICAL(flags); 265 EXIT_CRITICAL(flags);
246} 266}
247 267
@@ -293,6 +313,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
293 else 313 else
294 tlb_write_indexed(); 314 tlb_write_indexed();
295 tlbw_use_hazard(); 315 tlbw_use_hazard();
316 FLUSH_ITLB_VM(vma);
296 EXIT_CRITICAL(flags); 317 EXIT_CRITICAL(flags);
297} 318}
298 319
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index e7149290d1cb..4ec0964b8394 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,
893 case CPU_4KSC: 893 case CPU_4KSC:
894 case CPU_20KC: 894 case CPU_20KC:
895 case CPU_25KF: 895 case CPU_25KF:
896 case CPU_LOONGSON2:
896 tlbw(p); 897 tlbw(p);
897 break; 898 break;
898 899
@@ -1276,7 +1277,8 @@ static void __init build_r4000_tlb_refill_handler(void)
1276 * need three, with the second nop'ed and the third being 1277 * need three, with the second nop'ed and the third being
1277 * unused. 1278 * unused.
1278 */ 1279 */
1279#ifdef CONFIG_32BIT 1280 /* Loongson2 ebase is different than r4k, we have more space */
1281#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
1280 if ((p - tlb_handler) > 64) 1282 if ((p - tlb_handler) > 64)
1281 panic("TLB refill handler space exceeded"); 1283 panic("TLB refill handler space exceeded");
1282#else 1284#else
@@ -1289,7 +1291,7 @@ static void __init build_r4000_tlb_refill_handler(void)
1289 /* 1291 /*
1290 * Now fold the handler in the TLB refill handler space. 1292 * Now fold the handler in the TLB refill handler space.
1291 */ 1293 */
1292#ifdef CONFIG_32BIT 1294#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
1293 f = final_handler; 1295 f = final_handler;
1294 /* Simplest case, just copy the handler. */ 1296 /* Simplest case, just copy the handler. */
1295 copy_handler(relocs, labels, tlb_handler, p, f); 1297 copy_handler(relocs, labels, tlb_handler, p, f);
@@ -1336,7 +1338,7 @@ static void __init build_r4000_tlb_refill_handler(void)
1336 final_len); 1338 final_len);
1337 1339
1338 f = final_handler; 1340 f = final_handler;
1339#ifdef CONFIG_64BIT 1341#if defined(CONFIG_64BIT) && !defined(CONFIG_CPU_LOONGSON2)
1340 if (final_len > 32) 1342 if (final_len > 32)
1341 final_len = 64; 1343 final_len = 64;
1342 else 1344 else