MIPS: Add CPU support for Loongson1B
Loongson 1B is a 32-bit SoC designed by Institute of Computing Technology
(ICT) and the Chinese Academy of Sciences (CAS), which implements the
MIPS32 release 2 instruction set.
[ralf@linux-mips.org: But which is not strictly a MIPS32 compliant device
which also is why it identifies itself with the Legacy Vendor ID in the
PrID register. When applying the patch I shoveled some code around to
keep things in alphabetical order and avoid forward declarations.]
Signed-off-by: Kelvin Cheung <keguang.zhang@gmail.com>
Cc: To: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: wuzhangjin@gmail.com
Cc: zhzhl555@gmail.com
Cc: Kelvin Cheung <keguang.zhang@gmail.com>
Patchwork: https://patchwork.linux-mips.org/patch/3976/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 95e40c1..f21b7c0 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -197,6 +197,7 @@
#define PRID_REV_VR4181A 0x0070 /* Same as VR4122 */
#define PRID_REV_VR4130 0x0080
#define PRID_REV_34K_V1_0_2 0x0022
+#define PRID_REV_LOONGSON1B 0x0020
#define PRID_REV_LOONGSON2E 0x0002
#define PRID_REV_LOONGSON2F 0x0003
@@ -261,7 +262,7 @@
*/
CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
- CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_M14KC,
+ CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC,
/*
* MIPS64 class processors
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index 5300080..7531ecd 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -117,6 +117,8 @@
#define MODULE_PROC_FAMILY "RM9000 "
#elif defined CONFIG_CPU_SB1
#define MODULE_PROC_FAMILY "SB1 "
+#elif defined CONFIG_CPU_LOONGSON1
+#define MODULE_PROC_FAMILY "LOONGSON1 "
#elif defined CONFIG_CPU_LOONGSON2
#define MODULE_PROC_FAMILY "LOONGSON2 "
#elif defined CONFIG_CPU_CAVIUM_OCTEON
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index f4630e1..1b51046 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -190,6 +190,7 @@
case CPU_CAVIUM_OCTEON_PLUS:
case CPU_CAVIUM_OCTEON2:
case CPU_JZRISC:
+ case CPU_LOONGSON1:
case CPU_XLR:
case CPU_XLP:
cpu_wait = r4k_wait;
@@ -330,6 +331,154 @@
#endif
}
+static char unknown_isa[] __cpuinitdata = KERN_ERR \
+ "Unsupported ISA type, c0.config0: %d.";
+
+static inline unsigned int decode_config0(struct cpuinfo_mips *c)
+{
+ unsigned int config0;
+ int isa;
+
+ config0 = read_c0_config();
+
+ if (((config0 & MIPS_CONF_MT) >> 7) == 1)
+ c->options |= MIPS_CPU_TLB;
+ isa = (config0 & MIPS_CONF_AT) >> 13;
+ switch (isa) {
+ case 0:
+ switch ((config0 & MIPS_CONF_AR) >> 10) {
+ case 0:
+ c->isa_level = MIPS_CPU_ISA_M32R1;
+ break;
+ case 1:
+ c->isa_level = MIPS_CPU_ISA_M32R2;
+ break;
+ default:
+ goto unknown;
+ }
+ break;
+ case 2:
+ switch ((config0 & MIPS_CONF_AR) >> 10) {
+ case 0:
+ c->isa_level = MIPS_CPU_ISA_M64R1;
+ break;
+ case 1:
+ c->isa_level = MIPS_CPU_ISA_M64R2;
+ break;
+ default:
+ goto unknown;
+ }
+ break;
+ default:
+ goto unknown;
+ }
+
+ return config0 & MIPS_CONF_M;
+
+unknown:
+ panic(unknown_isa, config0);
+}
+
+static inline unsigned int decode_config1(struct cpuinfo_mips *c)
+{
+ unsigned int config1;
+
+ config1 = read_c0_config1();
+
+ if (config1 & MIPS_CONF1_MD)
+ c->ases |= MIPS_ASE_MDMX;
+ if (config1 & MIPS_CONF1_WR)
+ c->options |= MIPS_CPU_WATCH;
+ if (config1 & MIPS_CONF1_CA)
+ c->ases |= MIPS_ASE_MIPS16;
+ if (config1 & MIPS_CONF1_EP)
+ c->options |= MIPS_CPU_EJTAG;
+ if (config1 & MIPS_CONF1_FP) {
+ c->options |= MIPS_CPU_FPU;
+ c->options |= MIPS_CPU_32FPR;
+ }
+ if (cpu_has_tlb)
+ c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1;
+
+ return config1 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_config2(struct cpuinfo_mips *c)
+{
+ unsigned int config2;
+
+ config2 = read_c0_config2();
+
+ if (config2 & MIPS_CONF2_SL)
+ c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+
+ return config2 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_config3(struct cpuinfo_mips *c)
+{
+ unsigned int config3;
+
+ config3 = read_c0_config3();
+
+ if (config3 & MIPS_CONF3_SM)
+ c->ases |= MIPS_ASE_SMARTMIPS;
+ if (config3 & MIPS_CONF3_DSP)
+ c->ases |= MIPS_ASE_DSP;
+ if (config3 & MIPS_CONF3_VINT)
+ c->options |= MIPS_CPU_VINT;
+ if (config3 & MIPS_CONF3_VEIC)
+ 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;
+}
+
+static inline unsigned int decode_config4(struct cpuinfo_mips *c)
+{
+ unsigned int config4;
+
+ config4 = read_c0_config4();
+
+ if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT
+ && cpu_has_tlb)
+ c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
+
+ c->kscratch_mask = (config4 >> 16) & 0xff;
+
+ return config4 & MIPS_CONF_M;
+}
+
+static void __cpuinit decode_configs(struct cpuinfo_mips *c)
+{
+ int ok;
+
+ /* MIPS32 or MIPS64 compliant CPU. */
+ c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
+ MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
+
+ c->scache.flags = MIPS_CACHE_NOT_PRESENT;
+
+ ok = decode_config0(c); /* Read Config registers. */
+ BUG_ON(!ok); /* Arch spec violation! */
+ if (ok)
+ ok = decode_config1(c);
+ if (ok)
+ ok = decode_config2(c);
+ if (ok)
+ ok = decode_config3(c);
+ if (ok)
+ ok = decode_config4(c);
+
+ mips_probe_watch_registers(c);
+
+ if (cpu_has_mips_r2)
+ c->core = read_c0_ebase() & 0x3ff;
+}
+
#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
| MIPS_CPU_COUNTER)
@@ -638,155 +787,19 @@
MIPS_CPU_32FPR;
c->tlbsize = 64;
break;
- }
-}
+ case PRID_IMP_LOONGSON1:
+ decode_configs(c);
-static char unknown_isa[] __cpuinitdata = KERN_ERR \
- "Unsupported ISA type, c0.config0: %d.";
+ c->cputype = CPU_LOONGSON1;
-static inline unsigned int decode_config0(struct cpuinfo_mips *c)
-{
- unsigned int config0;
- int isa;
-
- config0 = read_c0_config();
-
- if (((config0 & MIPS_CONF_MT) >> 7) == 1)
- c->options |= MIPS_CPU_TLB;
- isa = (config0 & MIPS_CONF_AT) >> 13;
- switch (isa) {
- case 0:
- switch ((config0 & MIPS_CONF_AR) >> 10) {
- case 0:
- c->isa_level = MIPS_CPU_ISA_M32R1;
+ switch (c->processor_id & PRID_REV_MASK) {
+ case PRID_REV_LOONGSON1B:
+ __cpu_name[cpu] = "Loongson 1B";
break;
- case 1:
- c->isa_level = MIPS_CPU_ISA_M32R2;
- break;
- default:
- goto unknown;
}
+
break;
- case 2:
- switch ((config0 & MIPS_CONF_AR) >> 10) {
- case 0:
- c->isa_level = MIPS_CPU_ISA_M64R1;
- break;
- case 1:
- c->isa_level = MIPS_CPU_ISA_M64R2;
- break;
- default:
- goto unknown;
- }
- break;
- default:
- goto unknown;
}
-
- return config0 & MIPS_CONF_M;
-
-unknown:
- panic(unknown_isa, config0);
-}
-
-static inline unsigned int decode_config1(struct cpuinfo_mips *c)
-{
- unsigned int config1;
-
- config1 = read_c0_config1();
-
- if (config1 & MIPS_CONF1_MD)
- c->ases |= MIPS_ASE_MDMX;
- if (config1 & MIPS_CONF1_WR)
- c->options |= MIPS_CPU_WATCH;
- if (config1 & MIPS_CONF1_CA)
- c->ases |= MIPS_ASE_MIPS16;
- if (config1 & MIPS_CONF1_EP)
- c->options |= MIPS_CPU_EJTAG;
- if (config1 & MIPS_CONF1_FP) {
- c->options |= MIPS_CPU_FPU;
- c->options |= MIPS_CPU_32FPR;
- }
- if (cpu_has_tlb)
- c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1;
-
- return config1 & MIPS_CONF_M;
-}
-
-static inline unsigned int decode_config2(struct cpuinfo_mips *c)
-{
- unsigned int config2;
-
- config2 = read_c0_config2();
-
- if (config2 & MIPS_CONF2_SL)
- c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
-
- return config2 & MIPS_CONF_M;
-}
-
-static inline unsigned int decode_config3(struct cpuinfo_mips *c)
-{
- unsigned int config3;
-
- config3 = read_c0_config3();
-
- if (config3 & MIPS_CONF3_SM)
- c->ases |= MIPS_ASE_SMARTMIPS;
- if (config3 & MIPS_CONF3_DSP)
- c->ases |= MIPS_ASE_DSP;
- if (config3 & MIPS_CONF3_VINT)
- c->options |= MIPS_CPU_VINT;
- if (config3 & MIPS_CONF3_VEIC)
- 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;
-}
-
-static inline unsigned int decode_config4(struct cpuinfo_mips *c)
-{
- unsigned int config4;
-
- config4 = read_c0_config4();
-
- if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT
- && cpu_has_tlb)
- c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
-
- c->kscratch_mask = (config4 >> 16) & 0xff;
-
- return config4 & MIPS_CONF_M;
-}
-
-static void __cpuinit decode_configs(struct cpuinfo_mips *c)
-{
- int ok;
-
- /* MIPS32 or MIPS64 compliant CPU. */
- c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
- MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
-
- c->scache.flags = MIPS_CACHE_NOT_PRESENT;
-
- ok = decode_config0(c); /* Read Config registers. */
- BUG_ON(!ok); /* Arch spec violation! */
- if (ok)
- ok = decode_config1(c);
- if (ok)
- ok = decode_config2(c);
- if (ok)
- ok = decode_config3(c);
- if (ok)
- ok = decode_config4(c);
-
- mips_probe_watch_registers(c);
-
- if (cpu_has_mips_r2)
- c->core = read_c0_ebase() & 0x3ff;
}
static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index eb5e394..2f28d3b 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1559,6 +1559,11 @@
mipspmu.general_event_map = &mipsxxcore_event_map;
mipspmu.cache_event_map = &mipsxxcore_cache_map;
break;
+ case CPU_LOONGSON1:
+ mipspmu.name = "mips/loongson1";
+ mipspmu.general_event_map = &mipsxxcore_event_map;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map;
+ break;
case CPU_CAVIUM_OCTEON:
case CPU_CAVIUM_OCTEON_PLUS:
case CPU_CAVIUM_OCTEON2:
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index c3c2935..9be3df1 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1253,6 +1253,7 @@
case CPU_5KC:
case CPU_5KE:
+ case CPU_LOONGSON1:
write_c0_ecc(0x80000000);
back_to_back_c0_hazard();
/* Set the PE bit (bit 31) in the c0_errctl register. */
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index b6e3782..f80480a 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -85,6 +85,7 @@
case CPU_34K:
case CPU_1004K:
case CPU_74K:
+ case CPU_LOONGSON1:
case CPU_SB1:
case CPU_SB1A:
case CPU_R10000:
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 4d80a85..056da62 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -374,6 +374,10 @@
op_model_mipsxx_ops.cpu_type = "mips/sb1";
break;
+ case CPU_LOONGSON1:
+ op_model_mipsxx_ops.cpu_type = "mips/loongson1";
+ break;
+
default:
printk(KERN_ERR "Profiling unsupported for this CPU\n");