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:
parent
152ebb44ef
commit
c579d310b9
5 changed files with 76 additions and 5 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 = ¤t_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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue