#define CPU_FEATURE_LBT_MIPS           12      /* CPU has MIPS Binary Translation */
 #define CPU_FEATURE_TLB                        13      /* CPU has TLB */
 #define CPU_FEATURE_CSR                        14      /* CPU has CSR */
-#define CPU_FEATURE_WATCH              15      /* CPU has watchpoint registers */
-#define CPU_FEATURE_VINT               16      /* CPU has vectored interrupts */
-#define CPU_FEATURE_CSRIPI             17      /* CPU has CSR-IPI */
-#define CPU_FEATURE_EXTIOI             18      /* CPU has EXT-IOI */
-#define CPU_FEATURE_PREFETCH           19      /* CPU has prefetch instructions */
-#define CPU_FEATURE_PMP                        20      /* CPU has perfermance counter */
-#define CPU_FEATURE_SCALEFREQ          21      /* CPU supports cpufreq scaling */
-#define CPU_FEATURE_FLATMODE           22      /* CPU has flat mode */
-#define CPU_FEATURE_EIODECODE          23      /* CPU has EXTIOI interrupt pin decode mode */
-#define CPU_FEATURE_GUESTID            24      /* CPU has GuestID feature */
-#define CPU_FEATURE_HYPERVISOR         25      /* CPU has hypervisor (running in VM) */
-#define CPU_FEATURE_PTW                        26      /* CPU has hardware page table walker */
-#define CPU_FEATURE_AVECINT            27      /* CPU has avec interrupt */
+#define CPU_FEATURE_IOCSR              15      /* CPU has IOCSR */
+#define CPU_FEATURE_WATCH              16      /* CPU has watchpoint registers */
+#define CPU_FEATURE_VINT               17      /* CPU has vectored interrupts */
+#define CPU_FEATURE_CSRIPI             18      /* CPU has CSR-IPI */
+#define CPU_FEATURE_EXTIOI             19      /* CPU has EXT-IOI */
+#define CPU_FEATURE_PREFETCH           20      /* CPU has prefetch instructions */
+#define CPU_FEATURE_PMP                        21      /* CPU has perfermance counter */
+#define CPU_FEATURE_SCALEFREQ          22      /* CPU supports cpufreq scaling */
+#define CPU_FEATURE_FLATMODE           23      /* CPU has flat mode */
+#define CPU_FEATURE_EIODECODE          24      /* CPU has EXTIOI interrupt pin decode mode */
+#define CPU_FEATURE_GUESTID            25      /* CPU has GuestID feature */
+#define CPU_FEATURE_HYPERVISOR         26      /* CPU has hypervisor (running in VM) */
+#define CPU_FEATURE_PTW                        27      /* CPU has hardware page table walker */
+#define CPU_FEATURE_LSPW               28      /* CPU has LSPW (lddir/ldpte instructions) */
+#define CPU_FEATURE_AVECINT            29      /* CPU has AVEC interrupt */
 
 #define LOONGARCH_CPU_CPUCFG           BIT_ULL(CPU_FEATURE_CPUCFG)
 #define LOONGARCH_CPU_LAM              BIT_ULL(CPU_FEATURE_LAM)
 #define LOONGARCH_CPU_LBT_ARM          BIT_ULL(CPU_FEATURE_LBT_ARM)
 #define LOONGARCH_CPU_LBT_MIPS         BIT_ULL(CPU_FEATURE_LBT_MIPS)
 #define LOONGARCH_CPU_TLB              BIT_ULL(CPU_FEATURE_TLB)
+#define LOONGARCH_CPU_IOCSR            BIT_ULL(CPU_FEATURE_IOCSR)
 #define LOONGARCH_CPU_CSR              BIT_ULL(CPU_FEATURE_CSR)
 #define LOONGARCH_CPU_WATCH            BIT_ULL(CPU_FEATURE_WATCH)
 #define LOONGARCH_CPU_VINT             BIT_ULL(CPU_FEATURE_VINT)
 #define LOONGARCH_CPU_GUESTID          BIT_ULL(CPU_FEATURE_GUESTID)
 #define LOONGARCH_CPU_HYPERVISOR       BIT_ULL(CPU_FEATURE_HYPERVISOR)
 #define LOONGARCH_CPU_PTW              BIT_ULL(CPU_FEATURE_PTW)
+#define LOONGARCH_CPU_LSPW             BIT_ULL(CPU_FEATURE_LSPW)
 #define LOONGARCH_CPU_AVECINT          BIT_ULL(CPU_FEATURE_AVECINT)
 
 #endif /* _ASM_CPU_H */
 
        unsigned int config;
        unsigned long asid_mask;
 
-       c->options = LOONGARCH_CPU_CPUCFG | LOONGARCH_CPU_CSR |
-                    LOONGARCH_CPU_TLB | LOONGARCH_CPU_VINT | LOONGARCH_CPU_WATCH;
+       c->options = LOONGARCH_CPU_CPUCFG | LOONGARCH_CPU_CSR | LOONGARCH_CPU_VINT;
 
        elf_hwcap = HWCAP_LOONGARCH_CPUCFG;
 
        config = read_cpucfg(LOONGARCH_CPUCFG1);
+
+       switch (config & CPUCFG1_ISA) {
+       case 0:
+               set_isa(c, LOONGARCH_CPU_ISA_LA32R);
+               break;
+       case 1:
+               set_isa(c, LOONGARCH_CPU_ISA_LA32S);
+               break;
+       case 2:
+               set_isa(c, LOONGARCH_CPU_ISA_LA64);
+               break;
+       default:
+               pr_warn("Warning: unknown ISA level\n");
+       }
+
+       if (config & CPUCFG1_PAGING)
+               c->options |= LOONGARCH_CPU_TLB;
+       if (config & CPUCFG1_IOCSR)
+               c->options |= LOONGARCH_CPU_IOCSR;
        if (config & CPUCFG1_UAL) {
                c->options |= LOONGARCH_CPU_UAL;
                elf_hwcap |= HWCAP_LOONGARCH_UAL;
                c->options |= LOONGARCH_CPU_PTW;
                elf_hwcap |= HWCAP_LOONGARCH_PTW;
        }
+       if (config & CPUCFG2_LSPW) {
+               c->options |= LOONGARCH_CPU_LSPW;
+               elf_hwcap |= HWCAP_LOONGARCH_LSPW;
+       }
        if (config & CPUCFG2_LVZP) {
                c->options |= LOONGARCH_CPU_LVZ;
                elf_hwcap |= HWCAP_LOONGARCH_LVZ;
        if (config & CPUCFG6_PMP)
                c->options |= LOONGARCH_CPU_PMP;
 
-       config = iocsr_read32(LOONGARCH_IOCSR_FEATURES);
-       if (config & IOCSRF_CSRIPI)
-               c->options |= LOONGARCH_CPU_CSRIPI;
-       if (config & IOCSRF_EXTIOI)
-               c->options |= LOONGARCH_CPU_EXTIOI;
-       if (config & IOCSRF_FREQSCALE)
-               c->options |= LOONGARCH_CPU_SCALEFREQ;
-       if (config & IOCSRF_FLATMODE)
-               c->options |= LOONGARCH_CPU_FLATMODE;
-       if (config & IOCSRF_EIODECODE)
-               c->options |= LOONGARCH_CPU_EIODECODE;
-       if (config & IOCSRF_AVEC)
-               c->options |= LOONGARCH_CPU_AVECINT;
-       if (config & IOCSRF_VM)
-               c->options |= LOONGARCH_CPU_HYPERVISOR;
-
        config = csr_read32(LOONGARCH_CSR_ASID);
        config = (config & CSR_ASID_BIT) >> CSR_ASID_BIT_SHIFT;
        asid_mask = GENMASK(config - 1, 0);
        default:
                pr_warn("Warning: unknown TLB type\n");
        }
+
+       if (get_num_brps() + get_num_wrps())
+               c->options |= LOONGARCH_CPU_WATCH;
 }
 
 #define MAX_NAME_LEN   32
 
 static inline void cpu_probe_loongson(struct cpuinfo_loongarch *c, unsigned int cpu)
 {
+       uint32_t config;
        uint64_t *vendor = (void *)(&cpu_full_name[VENDOR_OFFSET]);
        uint64_t *cpuname = (void *)(&cpu_full_name[CPUNAME_OFFSET]);
+       const char *core_name = "Unknown";
 
-       if (!__cpu_full_name[cpu])
-               __cpu_full_name[cpu] = cpu_full_name;
-
-       *vendor = iocsr_read64(LOONGARCH_IOCSR_VENDOR);
-       *cpuname = iocsr_read64(LOONGARCH_IOCSR_CPUNAME);
-
-       switch (c->processor_id & PRID_SERIES_MASK) {
-       case PRID_SERIES_LA132:
+       switch (BIT(fls(c->isa_level) - 1)) {
+       case LOONGARCH_CPU_ISA_LA32R:
+       case LOONGARCH_CPU_ISA_LA32S:
                c->cputype = CPU_LOONGSON32;
-               set_isa(c, LOONGARCH_CPU_ISA_LA32S);
                __cpu_family[cpu] = "Loongson-32bit";
-               pr_info("32-bit Loongson Processor probed (LA132 Core)\n");
                break;
-       case PRID_SERIES_LA264:
+       case LOONGARCH_CPU_ISA_LA64:
                c->cputype = CPU_LOONGSON64;
-               set_isa(c, LOONGARCH_CPU_ISA_LA64);
                __cpu_family[cpu] = "Loongson-64bit";
-               pr_info("64-bit Loongson Processor probed (LA264 Core)\n");
+               break;
+       }
+
+       switch (c->processor_id & PRID_SERIES_MASK) {
+       case PRID_SERIES_LA132:
+               core_name = "LA132";
+               break;
+       case PRID_SERIES_LA264:
+               core_name = "LA264";
                break;
        case PRID_SERIES_LA364:
-               c->cputype = CPU_LOONGSON64;
-               set_isa(c, LOONGARCH_CPU_ISA_LA64);
-               __cpu_family[cpu] = "Loongson-64bit";
-               pr_info("64-bit Loongson Processor probed (LA364 Core)\n");
+               core_name = "LA364";
                break;
        case PRID_SERIES_LA464:
-               c->cputype = CPU_LOONGSON64;
-               set_isa(c, LOONGARCH_CPU_ISA_LA64);
-               __cpu_family[cpu] = "Loongson-64bit";
-               pr_info("64-bit Loongson Processor probed (LA464 Core)\n");
+               core_name = "LA464";
                break;
        case PRID_SERIES_LA664:
-               c->cputype = CPU_LOONGSON64;
-               set_isa(c, LOONGARCH_CPU_ISA_LA64);
-               __cpu_family[cpu] = "Loongson-64bit";
-               pr_info("64-bit Loongson Processor probed (LA664 Core)\n");
+               core_name = "LA664";
                break;
-       default: /* Default to 64 bit */
-               c->cputype = CPU_LOONGSON64;
-               set_isa(c, LOONGARCH_CPU_ISA_LA64);
-               __cpu_family[cpu] = "Loongson-64bit";
-               pr_info("64-bit Loongson Processor probed (Unknown Core)\n");
        }
+
+       pr_info("%s Processor probed (%s Core)\n", __cpu_family[cpu], core_name);
+
+       if (!cpu_has_iocsr)
+               return;
+
+       if (!__cpu_full_name[cpu])
+               __cpu_full_name[cpu] = cpu_full_name;
+
+       *vendor = iocsr_read64(LOONGARCH_IOCSR_VENDOR);
+       *cpuname = iocsr_read64(LOONGARCH_IOCSR_CPUNAME);
+
+       config = iocsr_read32(LOONGARCH_IOCSR_FEATURES);
+       if (config & IOCSRF_CSRIPI)
+               c->options |= LOONGARCH_CPU_CSRIPI;
+       if (config & IOCSRF_EXTIOI)
+               c->options |= LOONGARCH_CPU_EXTIOI;
+       if (config & IOCSRF_FREQSCALE)
+               c->options |= LOONGARCH_CPU_SCALEFREQ;
+       if (config & IOCSRF_FLATMODE)
+               c->options |= LOONGARCH_CPU_FLATMODE;
+       if (config & IOCSRF_EIODECODE)
+               c->options |= LOONGARCH_CPU_EIODECODE;
+       if (config & IOCSRF_AVEC)
+               c->options |= LOONGARCH_CPU_AVECINT;
+       if (config & IOCSRF_VM)
+               c->options |= LOONGARCH_CPU_HYPERVISOR;
 }
 
 #ifdef CONFIG_64BIT
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
        unsigned long n = (unsigned long) v - 1;
+       unsigned int isa = cpu_data[n].isa_level;
        unsigned int version = cpu_data[n].processor_id & 0xff;
        unsigned int fp_version = cpu_data[n].fpu_vers;
        struct proc_cpuinfo_notifier_args proc_cpuinfo_notifier_args;
                      cpu_pabits + 1, cpu_vabits + 1);
 
        seq_printf(m, "ISA\t\t\t:");
-       if (cpu_has_loongarch32)
-               seq_printf(m, " loongarch32");
-       if (cpu_has_loongarch64)
+       if (isa & LOONGARCH_CPU_ISA_LA32R)
+               seq_printf(m, " loongarch32r");
+       if (isa & LOONGARCH_CPU_ISA_LA32S)
+               seq_printf(m, " loongarch32s");
+       if (isa & LOONGARCH_CPU_ISA_LA64)
                seq_printf(m, " loongarch64");
        seq_printf(m, "\n");
 
        if (cpu_has_complex)    seq_printf(m, " complex");
        if (cpu_has_crypto)     seq_printf(m, " crypto");
        if (cpu_has_ptw)        seq_printf(m, " ptw");
+       if (cpu_has_lspw)       seq_printf(m, " lspw");
        if (cpu_has_lvz)        seq_printf(m, " lvz");
        if (cpu_has_lbt_x86)    seq_printf(m, " lbt_x86");
        if (cpu_has_lbt_arm)    seq_printf(m, " lbt_arm");