MIPS: Add CPU support for Loongson1B
authorKelvin Cheung <keguang.zhang@gmail.com>
Wed, 20 Jun 2012 19:05:32 +0000 (20:05 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 23 Jul 2012 12:57:04 +0000 (13:57 +0100)
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>
arch/mips/include/asm/cpu.h
arch/mips/include/asm/module.h
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/kernel/traps.c
arch/mips/oprofile/common.c
arch/mips/oprofile/op_model_mipsxx.c

index 95e40c1..f21b7c0 100644 (file)
 #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 @@ enum cpu_type_enum {
         */
        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
index 5300080..7531ecd 100644 (file)
@@ -117,6 +117,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_LOONGSON1
+#define MODULE_PROC_FAMILY "LOONGSON1 "
 #elif defined CONFIG_CPU_LOONGSON2
 #define MODULE_PROC_FAMILY "LOONGSON2 "
 #elif defined CONFIG_CPU_CAVIUM_OCTEON
index f4630e1..1b51046 100644 (file)
@@ -190,6 +190,7 @@ void __init check_wait(void)
        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 @@ static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
 #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 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                             MIPS_CPU_32FPR;
                c->tlbsize = 64;
                break;
-       }
-}
-
-static char unknown_isa[] __cpuinitdata = KERN_ERR \
-       "Unsupported ISA type, c0.config0: %d.";
+       case PRID_IMP_LOONGSON1:
+               decode_configs(c);
 
-static inline unsigned int decode_config0(struct cpuinfo_mips *c)
-{
-       unsigned int config0;
-       int isa;
+               c->cputype = CPU_LOONGSON1;
 
-       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;
+               switch (c->processor_id & PRID_REV_MASK) {
+               case PRID_REV_LOONGSON1B:
+                       __cpu_name[cpu] = "Loongson 1B";
                        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;
+               break;
        }
-       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)
index eb5e394..2f28d3b 100644 (file)
@@ -1559,6 +1559,11 @@ init_hw_perf_events(void)
                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:
index c3c2935..9be3df1 100644 (file)
@@ -1253,6 +1253,7 @@ static inline void parity_protection_init(void)
 
        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. */
index b6e3782..f80480a 100644 (file)
@@ -85,6 +85,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        case CPU_34K:
        case CPU_1004K:
        case CPU_74K:
+       case CPU_LOONGSON1:
        case CPU_SB1:
        case CPU_SB1A:
        case CPU_R10000:
index 4d80a85..056da62 100644 (file)
@@ -374,6 +374,10 @@ static int __init mipsxx_init(void)
                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");