mirror of
https://github.com/torvalds/linux
synced 2024-07-24 12:11:06 +00:00
MIPS: Loongson: Add Loongson-3A R2 basic support
Loongson-3 CPU family: Code-name Brand-name PRId Loongson-3A R1 Loongson-3A1000 0x6305 Loongson-3A R2 Loongson-3A2000 0x6308 Loongson-3B R1 Loongson-3B1000 0x6306 Loongson-3B R2 Loongson-3B1500 0x6307 Features of R2 revision of Loongson-3A: - Primary cache includes I-Cache, D-Cache and V-Cache (Victim Cache). - I-Cache, D-Cache and V-Cache are 16-way set-associative, linesize is 64 bytes. - 64 entries of VTLB (classic TLB), 1024 entries of FTLB (8-way set-associative). - Supports DSP/DSPv2 instructions, UserLocal register and Read-Inhibit/ Execute-Inhibit. [ralf@linux-mips.org: Resolved merge conflicts.] Signed-off-by: Huacai Chen <chenhc@lemote.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: Steven J . Hill <sjhill@realitydiluted.com> Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12751/ Patchwork: https://patchwork.linux-mips.org/patch/13136/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
24653515e5
commit
b2edcfc814
|
@ -1354,6 +1354,7 @@ config CPU_LOONGSON3
|
||||||
select CPU_SUPPORTS_HUGEPAGES
|
select CPU_SUPPORTS_HUGEPAGES
|
||||||
select WEAK_ORDERING
|
select WEAK_ORDERING
|
||||||
select WEAK_REORDERING_BEYOND_LLSC
|
select WEAK_REORDERING_BEYOND_LLSC
|
||||||
|
select MIPS_PGD_C0_CONTEXT
|
||||||
select ARCH_REQUIRE_GPIOLIB
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
help
|
help
|
||||||
The Loongson 3 processor implements the MIPS64R2 instruction
|
The Loongson 3 processor implements the MIPS64R2 instruction
|
||||||
|
@ -1823,6 +1824,7 @@ config CPU_BMIPS5000
|
||||||
config SYS_HAS_CPU_LOONGSON3
|
config SYS_HAS_CPU_LOONGSON3
|
||||||
bool
|
bool
|
||||||
select CPU_SUPPORTS_CPUFREQ
|
select CPU_SUPPORTS_CPUFREQ
|
||||||
|
select CPU_HAS_RIXI
|
||||||
|
|
||||||
config SYS_HAS_CPU_LOONGSON2E
|
config SYS_HAS_CPU_LOONGSON2E
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define Cache_I 0x00
|
#define Cache_I 0x00
|
||||||
#define Cache_D 0x01
|
#define Cache_D 0x01
|
||||||
#define Cache_T 0x02
|
#define Cache_T 0x02
|
||||||
|
#define Cache_V 0x02 /* Loongson-3 */
|
||||||
#define Cache_S 0x03
|
#define Cache_S 0x03
|
||||||
|
|
||||||
#define Index_Writeback_Inv 0x00
|
#define Index_Writeback_Inv 0x00
|
||||||
|
@ -107,4 +108,9 @@
|
||||||
*/
|
*/
|
||||||
#define Hit_Invalidate_I_Loongson2 (Cache_I | 0x00)
|
#define Hit_Invalidate_I_Loongson2 (Cache_I | 0x00)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loongson3-specific cacheops
|
||||||
|
*/
|
||||||
|
#define Index_Writeback_Inv_V (Cache_V | Index_Writeback_Inv)
|
||||||
|
|
||||||
#endif /* __ASM_CACHEOPS_H */
|
#endif /* __ASM_CACHEOPS_H */
|
||||||
|
|
|
@ -60,6 +60,7 @@ struct cpuinfo_mips {
|
||||||
int tlbsizeftlbways;
|
int tlbsizeftlbways;
|
||||||
struct cache_desc icache; /* Primary I-cache */
|
struct cache_desc icache; /* Primary I-cache */
|
||||||
struct cache_desc dcache; /* Primary D or combined I/D cache */
|
struct cache_desc dcache; /* Primary D or combined I/D cache */
|
||||||
|
struct cache_desc vcache; /* Victim cache, between pcache and scache */
|
||||||
struct cache_desc scache; /* Secondary cache */
|
struct cache_desc scache; /* Secondary cache */
|
||||||
struct cache_desc tcache; /* Tertiary/split secondary cache */
|
struct cache_desc tcache; /* Tertiary/split secondary cache */
|
||||||
int srsets; /* Shadow register sets */
|
int srsets; /* Shadow register sets */
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#define PRID_COMP_LEXRA 0x0b0000
|
#define PRID_COMP_LEXRA 0x0b0000
|
||||||
#define PRID_COMP_NETLOGIC 0x0c0000
|
#define PRID_COMP_NETLOGIC 0x0c0000
|
||||||
#define PRID_COMP_CAVIUM 0x0d0000
|
#define PRID_COMP_CAVIUM 0x0d0000
|
||||||
|
#define PRID_COMP_LOONGSON 0x140000
|
||||||
#define PRID_COMP_INGENIC_D0 0xd00000 /* JZ4740, JZ4750 */
|
#define PRID_COMP_INGENIC_D0 0xd00000 /* JZ4740, JZ4750 */
|
||||||
#define PRID_COMP_INGENIC_D1 0xd10000 /* JZ4770, JZ4775 */
|
#define PRID_COMP_INGENIC_D1 0xd10000 /* JZ4770, JZ4775 */
|
||||||
#define PRID_COMP_INGENIC_E1 0xe10000 /* JZ4780 */
|
#define PRID_COMP_INGENIC_E1 0xe10000 /* JZ4780 */
|
||||||
|
@ -241,9 +242,10 @@
|
||||||
#define PRID_REV_LOONGSON1B 0x0020
|
#define PRID_REV_LOONGSON1B 0x0020
|
||||||
#define PRID_REV_LOONGSON2E 0x0002
|
#define PRID_REV_LOONGSON2E 0x0002
|
||||||
#define PRID_REV_LOONGSON2F 0x0003
|
#define PRID_REV_LOONGSON2F 0x0003
|
||||||
#define PRID_REV_LOONGSON3A 0x0005
|
#define PRID_REV_LOONGSON3A_R1 0x0005
|
||||||
#define PRID_REV_LOONGSON3B_R1 0x0006
|
#define PRID_REV_LOONGSON3B_R1 0x0006
|
||||||
#define PRID_REV_LOONGSON3B_R2 0x0007
|
#define PRID_REV_LOONGSON3B_R2 0x0007
|
||||||
|
#define PRID_REV_LOONGSON3A_R2 0x0008
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Older processors used to encode processor version and revision in two
|
* Older processors used to encode processor version and revision in two
|
||||||
|
|
|
@ -16,11 +16,6 @@
|
||||||
#ifndef __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H
|
#ifndef __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H
|
||||||
#define __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H
|
#define __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H
|
||||||
|
|
||||||
#define cpu_dcache_line_size() 32
|
|
||||||
#define cpu_icache_line_size() 32
|
|
||||||
#define cpu_scache_line_size() 32
|
|
||||||
|
|
||||||
|
|
||||||
#define cpu_has_32fpr 1
|
#define cpu_has_32fpr 1
|
||||||
#define cpu_has_3k_cache 0
|
#define cpu_has_3k_cache 0
|
||||||
#define cpu_has_4k_cache 1
|
#define cpu_has_4k_cache 1
|
||||||
|
@ -31,24 +26,17 @@
|
||||||
#define cpu_has_counter 1
|
#define cpu_has_counter 1
|
||||||
#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
|
#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
|
||||||
#define cpu_has_divec 0
|
#define cpu_has_divec 0
|
||||||
#define cpu_has_dsp 0
|
|
||||||
#define cpu_has_dsp2 0
|
|
||||||
#define cpu_has_ejtag 0
|
#define cpu_has_ejtag 0
|
||||||
#define cpu_has_ic_fills_f_dc 0
|
|
||||||
#define cpu_has_inclusive_pcaches 1
|
#define cpu_has_inclusive_pcaches 1
|
||||||
#define cpu_has_llsc 1
|
#define cpu_has_llsc 1
|
||||||
#define cpu_has_mcheck 0
|
#define cpu_has_mcheck 0
|
||||||
#define cpu_has_mdmx 0
|
#define cpu_has_mdmx 0
|
||||||
#define cpu_has_mips16 0
|
#define cpu_has_mips16 0
|
||||||
#define cpu_has_mips32r2 0
|
|
||||||
#define cpu_has_mips3d 0
|
#define cpu_has_mips3d 0
|
||||||
#define cpu_has_mips64r2 0
|
|
||||||
#define cpu_has_mipsmt 0
|
#define cpu_has_mipsmt 0
|
||||||
#define cpu_has_prefetch 0
|
|
||||||
#define cpu_has_smartmips 0
|
#define cpu_has_smartmips 0
|
||||||
#define cpu_has_tlb 1
|
#define cpu_has_tlb 1
|
||||||
#define cpu_has_tx39_cache 0
|
#define cpu_has_tx39_cache 0
|
||||||
#define cpu_has_userlocal 0
|
|
||||||
#define cpu_has_vce 0
|
#define cpu_has_vce 0
|
||||||
#define cpu_has_veic 0
|
#define cpu_has_veic 0
|
||||||
#define cpu_has_vint 0
|
#define cpu_has_vint 0
|
||||||
|
@ -56,6 +44,10 @@
|
||||||
#define cpu_has_watch 1
|
#define cpu_has_watch 1
|
||||||
#define cpu_has_local_ebase 0
|
#define cpu_has_local_ebase 0
|
||||||
|
|
||||||
#define cpu_has_wsbh IS_ENABLED(CONFIG_CPU_LOONGSON3)
|
#ifdef CONFIG_CPU_LOONGSON3
|
||||||
|
#define cpu_has_wsbh 1
|
||||||
|
#define cpu_has_ic_fills_f_dc 1
|
||||||
|
#define cpu_hwrena_impl_bits 0xc0000000
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H */
|
#endif /* __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H */
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
or t0, (0x1 << 7)
|
or t0, (0x1 << 7)
|
||||||
mtc0 t0, $16, 3
|
mtc0 t0, $16, 3
|
||||||
/* Set ELPA on LOONGSON3 pagegrain */
|
/* Set ELPA on LOONGSON3 pagegrain */
|
||||||
li t0, (0x1 << 29)
|
mfc0 t0, $5, 1
|
||||||
|
or t0, (0x1 << 29)
|
||||||
mtc0 t0, $5, 1
|
mtc0 t0, $5, 1
|
||||||
_ehb
|
_ehb
|
||||||
.set pop
|
.set pop
|
||||||
|
@ -42,7 +43,8 @@
|
||||||
or t0, (0x1 << 7)
|
or t0, (0x1 << 7)
|
||||||
mtc0 t0, $16, 3
|
mtc0 t0, $16, 3
|
||||||
/* Set ELPA on LOONGSON3 pagegrain */
|
/* Set ELPA on LOONGSON3 pagegrain */
|
||||||
li t0, (0x1 << 29)
|
mfc0 t0, $5, 1
|
||||||
|
or t0, (0x1 << 29)
|
||||||
mtc0 t0, $5, 1
|
mtc0 t0, $5, 1
|
||||||
_ehb
|
_ehb
|
||||||
.set pop
|
.set pop
|
||||||
|
|
|
@ -636,6 +636,8 @@
|
||||||
#define MIPS_CONF6_SYND (_ULCAST_(1) << 13)
|
#define MIPS_CONF6_SYND (_ULCAST_(1) << 13)
|
||||||
/* proAptiv FTLB on/off bit */
|
/* proAptiv FTLB on/off bit */
|
||||||
#define MIPS_CONF6_FTLBEN (_ULCAST_(1) << 15)
|
#define MIPS_CONF6_FTLBEN (_ULCAST_(1) << 15)
|
||||||
|
/* Loongson-3 FTLB on/off bit */
|
||||||
|
#define MIPS_CONF6_FTLBDIS (_ULCAST_(1) << 22)
|
||||||
/* FTLB probability bits */
|
/* FTLB probability bits */
|
||||||
#define MIPS_CONF6_FTLBP_SHIFT (16)
|
#define MIPS_CONF6_FTLBP_SHIFT (16)
|
||||||
|
|
||||||
|
|
|
@ -384,7 +384,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
|
||||||
static inline pte_t pte_mkyoung(pte_t pte)
|
static inline pte_t pte_mkyoung(pte_t pte)
|
||||||
{
|
{
|
||||||
pte_val(pte) |= _PAGE_ACCESSED;
|
pte_val(pte) |= _PAGE_ACCESSED;
|
||||||
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_CPU_LOONGSON3)
|
||||||
if (!(pte_val(pte) & _PAGE_NO_READ))
|
if (!(pte_val(pte) & _PAGE_NO_READ))
|
||||||
pte_val(pte) |= _PAGE_SILENT_READ;
|
pte_val(pte) |= _PAGE_SILENT_READ;
|
||||||
else
|
else
|
||||||
|
@ -570,7 +570,7 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd)
|
||||||
{
|
{
|
||||||
pmd_val(pmd) |= _PAGE_ACCESSED;
|
pmd_val(pmd) |= _PAGE_ACCESSED;
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_CPU_LOONGSON3)
|
||||||
if (!(pmd_val(pmd) & _PAGE_NO_READ))
|
if (!(pmd_val(pmd) & _PAGE_NO_READ))
|
||||||
pmd_val(pmd) |= _PAGE_SILENT_READ;
|
pmd_val(pmd) |= _PAGE_SILENT_READ;
|
||||||
else
|
else
|
||||||
|
|
|
@ -562,6 +562,16 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
|
||||||
write_c0_config7(config | (calculate_ftlb_probability(c)
|
write_c0_config7(config | (calculate_ftlb_probability(c)
|
||||||
<< MIPS_CONF7_FTLBP_SHIFT));
|
<< MIPS_CONF7_FTLBP_SHIFT));
|
||||||
break;
|
break;
|
||||||
|
case CPU_LOONGSON3:
|
||||||
|
/* Loongson-3 cores use Config6 to enable the FTLB */
|
||||||
|
config = read_c0_config6();
|
||||||
|
if (enable)
|
||||||
|
/* Enable FTLB */
|
||||||
|
write_c0_config6(config & ~MIPS_CONF6_FTLBDIS);
|
||||||
|
else
|
||||||
|
/* Disable FTLB */
|
||||||
|
write_c0_config6(config | MIPS_CONF6_FTLBDIS);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1178,7 +1188,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
|
||||||
set_isa(c, MIPS_CPU_ISA_III);
|
set_isa(c, MIPS_CPU_ISA_III);
|
||||||
c->fpu_msk31 |= FPU_CSR_CONDX;
|
c->fpu_msk31 |= FPU_CSR_CONDX;
|
||||||
break;
|
break;
|
||||||
case PRID_REV_LOONGSON3A:
|
case PRID_REV_LOONGSON3A_R1:
|
||||||
c->cputype = CPU_LOONGSON3;
|
c->cputype = CPU_LOONGSON3;
|
||||||
__cpu_name[cpu] = "ICT Loongson-3";
|
__cpu_name[cpu] = "ICT Loongson-3";
|
||||||
set_elf_platform(cpu, "loongson3a");
|
set_elf_platform(cpu, "loongson3a");
|
||||||
|
@ -1512,6 +1522,29 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
|
||||||
|
{
|
||||||
|
switch (c->processor_id & PRID_IMP_MASK) {
|
||||||
|
case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */
|
||||||
|
switch (c->processor_id & PRID_REV_MASK) {
|
||||||
|
case PRID_REV_LOONGSON3A_R2:
|
||||||
|
c->cputype = CPU_LOONGSON3;
|
||||||
|
__cpu_name[cpu] = "ICT Loongson-3";
|
||||||
|
set_elf_platform(cpu, "loongson3a");
|
||||||
|
set_isa(c, MIPS_CPU_ISA_M64R2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
decode_configs(c);
|
||||||
|
c->options |= MIPS_CPU_TLBINV;
|
||||||
|
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
panic("Unknown Loongson Processor ID!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
|
static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
|
||||||
{
|
{
|
||||||
decode_configs(c);
|
decode_configs(c);
|
||||||
|
@ -1659,6 +1692,9 @@ void cpu_probe(void)
|
||||||
case PRID_COMP_CAVIUM:
|
case PRID_COMP_CAVIUM:
|
||||||
cpu_probe_cavium(c, cpu);
|
cpu_probe_cavium(c, cpu);
|
||||||
break;
|
break;
|
||||||
|
case PRID_COMP_LOONGSON:
|
||||||
|
cpu_probe_loongson(c, cpu);
|
||||||
|
break;
|
||||||
case PRID_COMP_INGENIC_D0:
|
case PRID_COMP_INGENIC_D0:
|
||||||
case PRID_COMP_INGENIC_D1:
|
case PRID_COMP_INGENIC_D1:
|
||||||
case PRID_COMP_INGENIC_E1:
|
case PRID_COMP_INGENIC_E1:
|
||||||
|
|
|
@ -181,6 +181,11 @@ void __init check_wait(void)
|
||||||
case CPU_XLP:
|
case CPU_XLP:
|
||||||
cpu_wait = r4k_wait;
|
cpu_wait = r4k_wait;
|
||||||
break;
|
break;
|
||||||
|
case CPU_LOONGSON3:
|
||||||
|
if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2)
|
||||||
|
cpu_wait = r4k_wait;
|
||||||
|
break;
|
||||||
|
|
||||||
case CPU_BMIPS5000:
|
case CPU_BMIPS5000:
|
||||||
cpu_wait = r4k_wait_irqoff;
|
cpu_wait = r4k_wait_irqoff;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1772,7 +1772,8 @@ asmlinkage void do_ftlb(void)
|
||||||
|
|
||||||
/* For the moment, report the problem and hang. */
|
/* For the moment, report the problem and hang. */
|
||||||
if ((cpu_has_mips_r2_r6) &&
|
if ((cpu_has_mips_r2_r6) &&
|
||||||
((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
|
(((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS) ||
|
||||||
|
((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_LOONGSON))) {
|
||||||
pr_err("FTLB error exception, cp0_ecc=0x%08x:\n",
|
pr_err("FTLB error exception, cp0_ecc=0x%08x:\n",
|
||||||
read_c0_ecc());
|
read_c0_ecc());
|
||||||
pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc());
|
pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc());
|
||||||
|
|
|
@ -105,6 +105,10 @@ void __init prom_init_env(void)
|
||||||
loongson_chiptemp[1] = 0x900010001fe0019c;
|
loongson_chiptemp[1] = 0x900010001fe0019c;
|
||||||
loongson_chiptemp[2] = 0x900020001fe0019c;
|
loongson_chiptemp[2] = 0x900020001fe0019c;
|
||||||
loongson_chiptemp[3] = 0x900030001fe0019c;
|
loongson_chiptemp[3] = 0x900030001fe0019c;
|
||||||
|
loongson_freqctrl[0] = 0x900000001fe001d0;
|
||||||
|
loongson_freqctrl[1] = 0x900010001fe001d0;
|
||||||
|
loongson_freqctrl[2] = 0x900020001fe001d0;
|
||||||
|
loongson_freqctrl[3] = 0x900030001fe001d0;
|
||||||
loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
|
loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
|
||||||
loongson_sysconf.workarounds = WORKAROUND_CPUFREQ;
|
loongson_sysconf.workarounds = WORKAROUND_CPUFREQ;
|
||||||
} else if (ecpu->cputype == Loongson_3B) {
|
} else if (ecpu->cputype == Loongson_3B) {
|
||||||
|
@ -187,7 +191,8 @@ void __init prom_init_env(void)
|
||||||
case PRID_REV_LOONGSON2F:
|
case PRID_REV_LOONGSON2F:
|
||||||
cpu_clock_freq = 797000000;
|
cpu_clock_freq = 797000000;
|
||||||
break;
|
break;
|
||||||
case PRID_REV_LOONGSON3A:
|
case PRID_REV_LOONGSON3A_R1:
|
||||||
|
case PRID_REV_LOONGSON3A_R2:
|
||||||
cpu_clock_freq = 900000000;
|
cpu_clock_freq = 900000000;
|
||||||
break;
|
break;
|
||||||
case PRID_REV_LOONGSON3B_R1:
|
case PRID_REV_LOONGSON3B_R1:
|
||||||
|
|
|
@ -439,7 +439,7 @@ static void loongson3_cpu_die(unsigned int cpu)
|
||||||
* flush all L1 entries at first. Then, another core (usually Core 0) can
|
* flush all L1 entries at first. Then, another core (usually Core 0) can
|
||||||
* safely disable the clock of the target core. loongson3_play_dead() is
|
* safely disable the clock of the target core. loongson3_play_dead() is
|
||||||
* called via CKSEG1 (uncached and unmmaped) */
|
* called via CKSEG1 (uncached and unmmaped) */
|
||||||
static void loongson3a_play_dead(int *state_addr)
|
static void loongson3a_r1_play_dead(int *state_addr)
|
||||||
{
|
{
|
||||||
register int val;
|
register int val;
|
||||||
register long cpuid, core, node, count;
|
register long cpuid, core, node, count;
|
||||||
|
@ -501,6 +501,89 @@ static void loongson3a_play_dead(int *state_addr)
|
||||||
: "a1");
|
: "a1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void loongson3a_r2_play_dead(int *state_addr)
|
||||||
|
{
|
||||||
|
register int val;
|
||||||
|
register long cpuid, core, node, count;
|
||||||
|
register void *addr, *base, *initfunc;
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
" .set push \n"
|
||||||
|
" .set noreorder \n"
|
||||||
|
" li %[addr], 0x80000000 \n" /* KSEG0 */
|
||||||
|
"1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */
|
||||||
|
" cache 0, 1(%[addr]) \n"
|
||||||
|
" cache 0, 2(%[addr]) \n"
|
||||||
|
" cache 0, 3(%[addr]) \n"
|
||||||
|
" cache 1, 0(%[addr]) \n" /* flush L1 DCache */
|
||||||
|
" cache 1, 1(%[addr]) \n"
|
||||||
|
" cache 1, 2(%[addr]) \n"
|
||||||
|
" cache 1, 3(%[addr]) \n"
|
||||||
|
" addiu %[sets], %[sets], -1 \n"
|
||||||
|
" bnez %[sets], 1b \n"
|
||||||
|
" addiu %[addr], %[addr], 0x40 \n"
|
||||||
|
" li %[addr], 0x80000000 \n" /* KSEG0 */
|
||||||
|
"2: cache 2, 0(%[addr]) \n" /* flush L1 VCache */
|
||||||
|
" cache 2, 1(%[addr]) \n"
|
||||||
|
" cache 2, 2(%[addr]) \n"
|
||||||
|
" cache 2, 3(%[addr]) \n"
|
||||||
|
" cache 2, 4(%[addr]) \n"
|
||||||
|
" cache 2, 5(%[addr]) \n"
|
||||||
|
" cache 2, 6(%[addr]) \n"
|
||||||
|
" cache 2, 7(%[addr]) \n"
|
||||||
|
" cache 2, 8(%[addr]) \n"
|
||||||
|
" cache 2, 9(%[addr]) \n"
|
||||||
|
" cache 2, 10(%[addr]) \n"
|
||||||
|
" cache 2, 11(%[addr]) \n"
|
||||||
|
" cache 2, 12(%[addr]) \n"
|
||||||
|
" cache 2, 13(%[addr]) \n"
|
||||||
|
" cache 2, 14(%[addr]) \n"
|
||||||
|
" cache 2, 15(%[addr]) \n"
|
||||||
|
" addiu %[vsets], %[vsets], -1 \n"
|
||||||
|
" bnez %[vsets], 2b \n"
|
||||||
|
" addiu %[addr], %[addr], 0x40 \n"
|
||||||
|
" li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
|
||||||
|
" sw %[val], (%[state_addr]) \n"
|
||||||
|
" sync \n"
|
||||||
|
" cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */
|
||||||
|
" .set pop \n"
|
||||||
|
: [addr] "=&r" (addr), [val] "=&r" (val)
|
||||||
|
: [state_addr] "r" (state_addr),
|
||||||
|
[sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
|
||||||
|
[vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
" .set push \n"
|
||||||
|
" .set noreorder \n"
|
||||||
|
" .set mips64 \n"
|
||||||
|
" mfc0 %[cpuid], $15, 1 \n"
|
||||||
|
" andi %[cpuid], 0x3ff \n"
|
||||||
|
" dli %[base], 0x900000003ff01000 \n"
|
||||||
|
" andi %[core], %[cpuid], 0x3 \n"
|
||||||
|
" sll %[core], 8 \n" /* get core id */
|
||||||
|
" or %[base], %[base], %[core] \n"
|
||||||
|
" andi %[node], %[cpuid], 0xc \n"
|
||||||
|
" dsll %[node], 42 \n" /* get node id */
|
||||||
|
" or %[base], %[base], %[node] \n"
|
||||||
|
"1: li %[count], 0x100 \n" /* wait for init loop */
|
||||||
|
"2: bnez %[count], 2b \n" /* limit mailbox access */
|
||||||
|
" addiu %[count], -1 \n"
|
||||||
|
" ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */
|
||||||
|
" beqz %[initfunc], 1b \n"
|
||||||
|
" nop \n"
|
||||||
|
" ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */
|
||||||
|
" ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */
|
||||||
|
" ld $a1, 0x38(%[base]) \n"
|
||||||
|
" jr %[initfunc] \n" /* jump to initial PC */
|
||||||
|
" nop \n"
|
||||||
|
" .set pop \n"
|
||||||
|
: [core] "=&r" (core), [node] "=&r" (node),
|
||||||
|
[base] "=&r" (base), [cpuid] "=&r" (cpuid),
|
||||||
|
[count] "=&r" (count), [initfunc] "=&r" (initfunc)
|
||||||
|
: /* No Input */
|
||||||
|
: "a1");
|
||||||
|
}
|
||||||
|
|
||||||
static void loongson3b_play_dead(int *state_addr)
|
static void loongson3b_play_dead(int *state_addr)
|
||||||
{
|
{
|
||||||
register int val;
|
register int val;
|
||||||
|
@ -572,13 +655,18 @@ void play_dead(void)
|
||||||
void (*play_dead_at_ckseg1)(int *);
|
void (*play_dead_at_ckseg1)(int *);
|
||||||
|
|
||||||
idle_task_exit();
|
idle_task_exit();
|
||||||
switch (loongson_sysconf.cputype) {
|
switch (read_c0_prid() & PRID_REV_MASK) {
|
||||||
case Loongson_3A:
|
case PRID_REV_LOONGSON3A_R1:
|
||||||
default:
|
default:
|
||||||
play_dead_at_ckseg1 =
|
play_dead_at_ckseg1 =
|
||||||
(void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead);
|
(void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
|
||||||
break;
|
break;
|
||||||
case Loongson_3B:
|
case PRID_REV_LOONGSON3A_R2:
|
||||||
|
play_dead_at_ckseg1 =
|
||||||
|
(void *)CKSEG1ADDR((unsigned long)loongson3a_r2_play_dead);
|
||||||
|
break;
|
||||||
|
case PRID_REV_LOONGSON3B_R1:
|
||||||
|
case PRID_REV_LOONGSON3B_R2:
|
||||||
play_dead_at_ckseg1 =
|
play_dead_at_ckseg1 =
|
||||||
(void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
|
(void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
|
||||||
break;
|
break;
|
||||||
|
@ -593,9 +681,9 @@ void loongson3_disable_clock(int cpu)
|
||||||
uint64_t core_id = cpu_data[cpu].core;
|
uint64_t core_id = cpu_data[cpu].core;
|
||||||
uint64_t package_id = cpu_data[cpu].package;
|
uint64_t package_id = cpu_data[cpu].package;
|
||||||
|
|
||||||
if (loongson_sysconf.cputype == Loongson_3A) {
|
if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
|
||||||
LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
|
LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
|
||||||
} else if (loongson_sysconf.cputype == Loongson_3B) {
|
} else {
|
||||||
if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
|
if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
|
||||||
LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
|
LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
|
||||||
}
|
}
|
||||||
|
@ -606,9 +694,9 @@ void loongson3_enable_clock(int cpu)
|
||||||
uint64_t core_id = cpu_data[cpu].core;
|
uint64_t core_id = cpu_data[cpu].core;
|
||||||
uint64_t package_id = cpu_data[cpu].package;
|
uint64_t package_id = cpu_data[cpu].package;
|
||||||
|
|
||||||
if (loongson_sysconf.cputype == Loongson_3A) {
|
if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
|
||||||
LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
|
LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
|
||||||
} else if (loongson_sysconf.cputype == Loongson_3B) {
|
} else {
|
||||||
if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
|
if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
|
||||||
LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
|
LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,7 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info)
|
||||||
*/
|
*/
|
||||||
static unsigned long icache_size __read_mostly;
|
static unsigned long icache_size __read_mostly;
|
||||||
static unsigned long dcache_size __read_mostly;
|
static unsigned long dcache_size __read_mostly;
|
||||||
|
static unsigned long vcache_size __read_mostly;
|
||||||
static unsigned long scache_size __read_mostly;
|
static unsigned long scache_size __read_mostly;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1349,6 +1350,31 @@ static void probe_pcache(void)
|
||||||
c->dcache.linesz);
|
c->dcache.linesz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void probe_vcache(void)
|
||||||
|
{
|
||||||
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
||||||
|
unsigned int config2, lsize;
|
||||||
|
|
||||||
|
if (current_cpu_type() != CPU_LOONGSON3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
config2 = read_c0_config2();
|
||||||
|
if ((lsize = ((config2 >> 20) & 15)))
|
||||||
|
c->vcache.linesz = 2 << lsize;
|
||||||
|
else
|
||||||
|
c->vcache.linesz = lsize;
|
||||||
|
|
||||||
|
c->vcache.sets = 64 << ((config2 >> 24) & 15);
|
||||||
|
c->vcache.ways = 1 + ((config2 >> 16) & 15);
|
||||||
|
|
||||||
|
vcache_size = c->vcache.sets * c->vcache.ways * c->vcache.linesz;
|
||||||
|
|
||||||
|
c->vcache.waybit = 0;
|
||||||
|
|
||||||
|
pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n",
|
||||||
|
vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If you even _breathe_ on this function, look at the gcc output and make sure
|
* If you even _breathe_ on this function, look at the gcc output and make sure
|
||||||
* it does not pop things on and off the stack for the cache sizing loop that
|
* it does not pop things on and off the stack for the cache sizing loop that
|
||||||
|
@ -1671,6 +1697,7 @@ void r4k_cache_init(void)
|
||||||
struct cpuinfo_mips *c = ¤t_cpu_data;
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
||||||
|
|
||||||
probe_pcache();
|
probe_pcache();
|
||||||
|
probe_vcache();
|
||||||
setup_scache();
|
setup_scache();
|
||||||
|
|
||||||
r4k_blast_dcache_page_setup();
|
r4k_blast_dcache_page_setup();
|
||||||
|
|
|
@ -20,9 +20,9 @@ int loongson3_cpu_temp(int cpu)
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
reg = LOONGSON_CHIPTEMP(cpu);
|
reg = LOONGSON_CHIPTEMP(cpu);
|
||||||
if (loongson_sysconf.cputype == Loongson_3A)
|
if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1)
|
||||||
reg = (reg >> 8) & 0xff;
|
reg = (reg >> 8) & 0xff;
|
||||||
else if (loongson_sysconf.cputype == Loongson_3B)
|
else
|
||||||
reg = ((reg >> 8) & 0xff) - 100;
|
reg = ((reg >> 8) & 0xff) - 100;
|
||||||
|
|
||||||
return (int)reg * 1000;
|
return (int)reg * 1000;
|
||||||
|
|
Loading…
Reference in a new issue