MIPS: Loongson: Add basic Loongson-3 CPU support

Basic Loongson-3 CPU support include CPU probing and TLB/cache
initializing.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
Tested-by: Alex Smith <alex.smith@imgtec.com>
Reviewed-by: Alex Smith <alex.smith@imgtec.com>
Cc: John Crispin <john@phrozen.org>
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: linux-mips@linux-mips.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Patchwork: https://patchwork.linux-mips.org/patch/6630
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
Huacai Chen 2014-03-21 18:44:00 +08:00 committed by Ralf Baechle
parent 152ebb44ef
commit c579d310b9
5 changed files with 76 additions and 5 deletions

View file

@ -20,6 +20,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
case CPU_LOONGSON2: case CPU_LOONGSON2:
#endif #endif
#ifdef CONFIG_SYS_HAS_CPU_LOONGSON3
case CPU_LOONGSON3:
#endif
#ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B #ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
case CPU_LOONGSON1: case CPU_LOONGSON1:
#endif #endif

View file

@ -735,16 +735,22 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
c->tlbsize = 64; c->tlbsize = 64;
break; break;
case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */ case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */
c->cputype = CPU_LOONGSON2;
__cpu_name[cpu] = "ICT Loongson-2";
switch (c->processor_id & PRID_REV_MASK) { switch (c->processor_id & PRID_REV_MASK) {
case PRID_REV_LOONGSON2E: case PRID_REV_LOONGSON2E:
c->cputype = CPU_LOONGSON2;
__cpu_name[cpu] = "ICT Loongson-2";
set_elf_platform(cpu, "loongson2e"); set_elf_platform(cpu, "loongson2e");
break; break;
case PRID_REV_LOONGSON2F: case PRID_REV_LOONGSON2F:
c->cputype = CPU_LOONGSON2;
__cpu_name[cpu] = "ICT Loongson-2";
set_elf_platform(cpu, "loongson2f"); set_elf_platform(cpu, "loongson2f");
break; break;
case PRID_REV_LOONGSON3A:
c->cputype = CPU_LOONGSON3;
__cpu_name[cpu] = "ICT Loongson-3";
set_elf_platform(cpu, "loongson3a");
break;
} }
set_isa(c, MIPS_CPU_ISA_III); set_isa(c, MIPS_CPU_ISA_III);

View file

@ -398,6 +398,7 @@ static inline void local_r4k___flush_cache_all(void * args)
{ {
switch (current_cpu_type()) { switch (current_cpu_type()) {
case CPU_LOONGSON2: case CPU_LOONGSON2:
case CPU_LOONGSON3:
case CPU_R4000SC: case CPU_R4000SC:
case CPU_R4000MC: case CPU_R4000MC:
case CPU_R4400SC: case CPU_R4400SC:
@ -1066,6 +1067,33 @@ static void probe_pcache(void)
c->dcache.waybit = 0; c->dcache.waybit = 0;
break; break;
case CPU_LOONGSON3:
config1 = read_c0_config1();
lsize = (config1 >> 19) & 7;
if (lsize)
c->icache.linesz = 2 << lsize;
else
c->icache.linesz = 0;
c->icache.sets = 64 << ((config1 >> 22) & 7);
c->icache.ways = 1 + ((config1 >> 16) & 7);
icache_size = c->icache.sets *
c->icache.ways *
c->icache.linesz;
c->icache.waybit = 0;
lsize = (config1 >> 10) & 7;
if (lsize)
c->dcache.linesz = 2 << lsize;
else
c->dcache.linesz = 0;
c->dcache.sets = 64 << ((config1 >> 13) & 7);
c->dcache.ways = 1 + ((config1 >> 7) & 7);
dcache_size = c->dcache.sets *
c->dcache.ways *
c->dcache.linesz;
c->dcache.waybit = 0;
break;
default: default:
if (!(config & MIPS_CONF_M)) if (!(config & MIPS_CONF_M))
panic("Don't know how to probe P-caches on this cpu."); panic("Don't know how to probe P-caches on this cpu.");
@ -1303,6 +1331,33 @@ static void __init loongson2_sc_init(void)
c->options |= MIPS_CPU_INCLUSIVE_CACHES; c->options |= MIPS_CPU_INCLUSIVE_CACHES;
} }
static void __init loongson3_sc_init(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
unsigned int config2, lsize;
config2 = read_c0_config2();
lsize = (config2 >> 4) & 15;
if (lsize)
c->scache.linesz = 2 << lsize;
else
c->scache.linesz = 0;
c->scache.sets = 64 << ((config2 >> 8) & 15);
c->scache.ways = 1 + (config2 & 15);
scache_size = c->scache.sets *
c->scache.ways *
c->scache.linesz;
/* Loongson-3 has 4 cores, 1MB scache for each. scaches are shared */
scache_size *= 4;
c->scache.waybit = 0;
pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
if (scache_size)
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
return;
}
extern int r5k_sc_init(void); extern int r5k_sc_init(void);
extern int rm7k_sc_init(void); extern int rm7k_sc_init(void);
extern int mips_sc_init(void); extern int mips_sc_init(void);
@ -1355,6 +1410,10 @@ static void setup_scache(void)
loongson2_sc_init(); loongson2_sc_init();
return; return;
case CPU_LOONGSON3:
loongson3_sc_init();
return;
case CPU_XLP: case CPU_XLP:
/* don't need to worry about L2, fully coherent */ /* don't need to worry about L2, fully coherent */
return; return;

View file

@ -48,13 +48,14 @@ extern void build_tlb_refill_handler(void);
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
/* /*
* LOONGSON2 has a 4 entry itlb which is a subset of dtlb, * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb,
* unfortrunately, itlb is not totally transparent to software. * unfortunately, itlb is not totally transparent to software.
*/ */
static inline void flush_itlb(void) static inline void flush_itlb(void)
{ {
switch (current_cpu_type()) { switch (current_cpu_type()) {
case CPU_LOONGSON2: case CPU_LOONGSON2:
case CPU_LOONGSON3:
write_c0_diag(4); write_c0_diag(4);
break; break;
default: default:

View file

@ -582,6 +582,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
case CPU_BMIPS4380: case CPU_BMIPS4380:
case CPU_BMIPS5000: case CPU_BMIPS5000:
case CPU_LOONGSON2: case CPU_LOONGSON2:
case CPU_LOONGSON3:
case CPU_R5500: case CPU_R5500:
if (m4kc_tlbp_war()) if (m4kc_tlbp_war())
uasm_i_nop(p); uasm_i_nop(p);