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>
This commit is contained in:
parent
28a33cbc24
commit
2fa36399e6
|
@ -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 @@ 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
Loading…
Reference in New Issue