MIPS: Loongson: Add Loongson-3A R2 basic support
authorHuacai Chen <chenhc@lemote.com>
Thu, 3 Mar 2016 01:45:09 +0000 (09:45 +0800)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 13 May 2016 12:02:14 +0000 (14:02 +0200)
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>
15 files changed:
arch/mips/Kconfig
arch/mips/include/asm/cacheops.h
arch/mips/include/asm/cpu-info.h
arch/mips/include/asm/cpu.h
arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/pgtable.h
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/idle.c
arch/mips/kernel/traps.c
arch/mips/loongson64/common/env.c
arch/mips/loongson64/loongson-3/smp.c
arch/mips/mm/c-r4k.c
drivers/platform/mips/cpu_hwmon.c

index fbd63ff8eba49861acbe8dc4498dd4de898b3ef9..adcc97ea4392d2cb8c348976b98bc6cb7ef759a0 100644 (file)
@@ -1354,6 +1354,7 @@ config CPU_LOONGSON3
        select CPU_SUPPORTS_HUGEPAGES
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
+       select MIPS_PGD_C0_CONTEXT
        select ARCH_REQUIRE_GPIOLIB
        help
                The Loongson 3 processor implements the MIPS64R2 instruction
@@ -1823,6 +1824,7 @@ config CPU_BMIPS5000
 config SYS_HAS_CPU_LOONGSON3
        bool
        select CPU_SUPPORTS_CPUFREQ
+       select CPU_HAS_RIXI
 
 config SYS_HAS_CPU_LOONGSON2E
        bool
index c3212ff2672343fcb52315403c73d16759be77b1..8031fbc6b69a2867a043ff4e1655497548631e72 100644 (file)
@@ -21,6 +21,7 @@
 #define Cache_I                                0x00
 #define Cache_D                                0x01
 #define Cache_T                                0x02
+#define Cache_V                                0x02 /* Loongson-3 */
 #define Cache_S                                0x03
 
 #define Index_Writeback_Inv            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 */
index 9ec81684b1b8b95c9e7ca3bcc1a714e2a7e0c0d6..b090aa51d644f5fc93dedc7b46824d6bc1239660 100644 (file)
@@ -60,6 +60,7 @@ struct cpuinfo_mips {
        int                     tlbsizeftlbways;
        struct cache_desc       icache; /* Primary I-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       tcache; /* Tertiary/split secondary cache */
        int                     srsets; /* Shadow register sets */
index 9127a583d1f1348d804ba1960f372ab93adb369b..810536b6900cf5337ac55509988d4f3e9f8e7f27 100644 (file)
@@ -42,6 +42,7 @@
 #define PRID_COMP_LEXRA                0x0b0000
 #define PRID_COMP_NETLOGIC     0x0c0000
 #define PRID_COMP_CAVIUM       0x0d0000
+#define PRID_COMP_LOONGSON     0x140000
 #define PRID_COMP_INGENIC_D0   0xd00000        /* JZ4740, JZ4750 */
 #define PRID_COMP_INGENIC_D1   0xd10000        /* JZ4770, JZ4775 */
 #define PRID_COMP_INGENIC_E1   0xe10000        /* JZ4780 */
 #define PRID_REV_LOONGSON1B    0x0020
 #define PRID_REV_LOONGSON2E    0x0002
 #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_R2 0x0007
+#define PRID_REV_LOONGSON3A_R2 0x0008
 
 /*
  * Older processors used to encode processor version and revision in two
index 98963c2c7be48abf311915cd99fea93f73141cd4..89328a3d44d8556c5ac340dd6c5e22507ecfd66a 100644 (file)
 #ifndef __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_3k_cache       0
 #define cpu_has_4k_cache       1
 #define cpu_has_counter                1
 #define cpu_has_dc_aliases     (PAGE_SIZE < 0x4000)
 #define cpu_has_divec          0
-#define cpu_has_dsp            0
-#define cpu_has_dsp2           0
 #define cpu_has_ejtag          0
-#define cpu_has_ic_fills_f_dc  0
 #define cpu_has_inclusive_pcaches      1
 #define cpu_has_llsc           1
 #define cpu_has_mcheck         0
 #define cpu_has_mdmx           0
 #define cpu_has_mips16         0
-#define cpu_has_mips32r2       0
 #define cpu_has_mips3d         0
-#define cpu_has_mips64r2       0
 #define cpu_has_mipsmt         0
-#define cpu_has_prefetch       0
 #define cpu_has_smartmips      0
 #define cpu_has_tlb            1
 #define cpu_has_tx39_cache     0
-#define cpu_has_userlocal      0
 #define cpu_has_vce            0
 #define cpu_has_veic           0
 #define cpu_has_vint           0
 #define cpu_has_watch          1
 #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 */
index 3f2f84f6c401f5637b5952477abdea47ab9e657d..da83482ff0b97cfa6c80fcbc12e7bc04aed7dfba 100644 (file)
@@ -23,7 +23,8 @@
        or      t0, (0x1 << 7)
        mtc0    t0, $16, 3
        /* Set ELPA on LOONGSON3 pagegrain */
-       li      t0, (0x1 << 29)
+       mfc0    t0, $5, 1
+       or      t0, (0x1 << 29)
        mtc0    t0, $5, 1
        _ehb
        .set    pop
@@ -42,7 +43,8 @@
        or      t0, (0x1 << 7)
        mtc0    t0, $16, 3
        /* Set ELPA on LOONGSON3 pagegrain */
-       li      t0, (0x1 << 29)
+       mfc0    t0, $5, 1
+       or      t0, (0x1 << 29)
        mtc0    t0, $5, 1
        _ehb
        .set    pop
index aea90631a301218ba3c19510aaa2483645c71abc..28ded49d25c64df540db15d8a7c4246fb079d243 100644 (file)
 #define MIPS_CONF6_SYND                (_ULCAST_(1) << 13)
 /* proAptiv FTLB on/off bit */
 #define MIPS_CONF6_FTLBEN      (_ULCAST_(1) << 15)
+/* Loongson-3 FTLB on/off bit */
+#define MIPS_CONF6_FTLBDIS     (_ULCAST_(1) << 22)
 /* FTLB probability bits */
 #define MIPS_CONF6_FTLBP_SHIFT (16)
 
index 45de5765161907ec52a20f02a3b47fc7c0ffb016..7f422500b65d26f3fdc7de725ca2e394fb933ecf 100644 (file)
@@ -384,7 +384,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
 static inline pte_t pte_mkyoung(pte_t pte)
 {
        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))
                pte_val(pte) |= _PAGE_SILENT_READ;
        else
@@ -570,7 +570,7 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd)
 {
        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))
                pmd_val(pmd) |= _PAGE_SILENT_READ;
        else
index d72bd7eb8bce64eef3939bac4bd72c1ecae2385c..2bfd48375b46065643ccdcb610c18fb05eb76fcb 100644 (file)
@@ -562,6 +562,16 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
                write_c0_config7(config | (calculate_ftlb_probability(c)
                                           << MIPS_CONF7_FTLBP_SHIFT));
                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:
                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);
                        c->fpu_msk31 |= FPU_CSR_CONDX;
                        break;
-               case PRID_REV_LOONGSON3A:
+               case PRID_REV_LOONGSON3A_R1:
                        c->cputype = CPU_LOONGSON3;
                        __cpu_name[cpu] = "ICT Loongson-3";
                        set_elf_platform(cpu, "loongson3a");
@@ -1512,6 +1522,29 @@ platform:
        }
 }
 
+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)
 {
        decode_configs(c);
@@ -1659,6 +1692,9 @@ void cpu_probe(void)
        case PRID_COMP_CAVIUM:
                cpu_probe_cavium(c, cpu);
                break;
+       case PRID_COMP_LOONGSON:
+               cpu_probe_loongson(c, cpu);
+               break;
        case PRID_COMP_INGENIC_D0:
        case PRID_COMP_INGENIC_D1:
        case PRID_COMP_INGENIC_E1:
index 46794d64c0bfe3f9779cc43714cc7c3fbb6a10bc..60ab4c44d30557b285a90cc28e7b8ae1dd2ca21a 100644 (file)
@@ -181,6 +181,11 @@ void __init check_wait(void)
        case CPU_XLP:
                cpu_wait = r4k_wait;
                break;
+       case CPU_LOONGSON3:
+               if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2)
+                       cpu_wait = r4k_wait;
+               break;
+
        case CPU_BMIPS5000:
                cpu_wait = r4k_wait_irqoff;
                break;
index dcda63e65854dcf0f1d8f4ca212c2d5bb32540c4..38864dc179ffe74cece1c5ad5ac7d6c06644e93d 100644 (file)
@@ -1772,7 +1772,8 @@ asmlinkage void do_ftlb(void)
 
        /* For the moment, report the problem and hang. */
        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",
                       read_c0_ecc());
                pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc());
index d6d07ad56180fa7438595994833aef5e60628350..57d590ac80045b9bf9848a6e216d22d72cff33d9 100644 (file)
@@ -105,6 +105,10 @@ void __init prom_init_env(void)
                loongson_chiptemp[1] = 0x900010001fe0019c;
                loongson_chiptemp[2] = 0x900020001fe0019c;
                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.workarounds = WORKAROUND_CPUFREQ;
        } else if (ecpu->cputype == Loongson_3B) {
@@ -187,7 +191,8 @@ void __init prom_init_env(void)
                case PRID_REV_LOONGSON2F:
                        cpu_clock_freq = 797000000;
                        break;
-               case PRID_REV_LOONGSON3A:
+               case PRID_REV_LOONGSON3A_R1:
+               case PRID_REV_LOONGSON3A_R2:
                        cpu_clock_freq = 900000000;
                        break;
                case PRID_REV_LOONGSON3B_R1:
index b913cd240d77f2c9d6d1ca41838c0a61829064a6..e59759af63d9f0c929e4635e5e3993e299254e89 100644 (file)
@@ -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
  * safely disable the clock of the target core. loongson3_play_dead() is
  * 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 long cpuid, core, node, count;
@@ -501,6 +501,89 @@ static void loongson3a_play_dead(int *state_addr)
                : "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)
 {
        register int val;
@@ -572,13 +655,18 @@ void play_dead(void)
        void (*play_dead_at_ckseg1)(int *);
 
        idle_task_exit();
-       switch (loongson_sysconf.cputype) {
-       case Loongson_3A:
+       switch (read_c0_prid() & PRID_REV_MASK) {
+       case PRID_REV_LOONGSON3A_R1:
        default:
                play_dead_at_ckseg1 =
-                       (void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead);
+                       (void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
+               break;
+       case PRID_REV_LOONGSON3A_R2:
+               play_dead_at_ckseg1 =
+                       (void *)CKSEG1ADDR((unsigned long)loongson3a_r2_play_dead);
                break;
-       case Loongson_3B:
+       case PRID_REV_LOONGSON3B_R1:
+       case PRID_REV_LOONGSON3B_R2:
                play_dead_at_ckseg1 =
                        (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
                break;
@@ -593,9 +681,9 @@ void loongson3_disable_clock(int cpu)
        uint64_t core_id = cpu_data[cpu].core;
        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));
-       } else if (loongson_sysconf.cputype == Loongson_3B) {
+       } else {
                if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
                        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 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);
-       } else if (loongson_sysconf.cputype == Loongson_3B) {
+       } else {
                if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
                        LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
        }
index 6f43bdf9a67963fb97f24faa978537d656f94ce2..77fbaf1cdfd635d6848b81e0f31d507ef4554342 100644 (file)
@@ -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 dcache_size __read_mostly;
+static unsigned long vcache_size __read_mostly;
 static unsigned long scache_size __read_mostly;
 
 /*
@@ -1349,6 +1350,31 @@ static void probe_pcache(void)
               c->dcache.linesz);
 }
 
+static void probe_vcache(void)
+{
+       struct cpuinfo_mips *c = &current_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
  * 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 = &current_cpu_data;
 
        probe_pcache();
+       probe_vcache();
        setup_scache();
 
        r4k_blast_dcache_page_setup();
index 0f6c63e17049e9eebed64bef0dcd2cdceff7facd..8c5072b7ad4f2c65464e244d6f01cb33e78809e3 100644 (file)
@@ -20,9 +20,9 @@ int loongson3_cpu_temp(int cpu)
        u32 reg;
 
        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;
-       else if (loongson_sysconf.cputype == Loongson_3B)
+       else
                reg = ((reg >> 8) & 0xff) - 100;
 
        return (int)reg * 1000;