Merge tag 'arc-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 25 Nov 2017 18:21:54 +0000 (08:21 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 25 Nov 2017 18:21:54 +0000 (08:21 -1000)
Pull ARC updates from Vineet Gupta:

 - more changes for HS48 cores: supporting MMUv5, detecting new
   micro-arch gizmos

 - axs10x platform wiring up reset driver merged in this cycle

 - ARC perf driver optimizations

* tag 'arc-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc:
  ARC: perf: avoid vmalloc backed mmap
  ARCv2: perf: optimize given that num counters <= 32
  ARCv2: perf: tweak overflow interrupt
  ARC: [plat-axs10x] DTS: Add reset controller node to manage ethernet reset
  ARCv2: boot log: updates for HS48: dual-issue, ECC, Loop Buffer
  ARCv2: Accomodate HS48 MMUv5 by relaxing MMU ver checking
  ARC: [plat-axs10x] auto-select AXS101 or AXS103 given the  ISA config

arch/arc/Kconfig
arch/arc/boot/dts/axs10x_mb.dtsi
arch/arc/include/asm/arcregs.h
arch/arc/kernel/perf_event.c
arch/arc/kernel/setup.c
arch/arc/mm/tlb.c
arch/arc/plat-axs10x/Kconfig
arch/arc/plat-axs10x/axs10x.c

index 5c7adf100a582ba1d1a4c3d2760d1d7103e0eb0d..9d5fd00d9e91bf0caa066bc0597475723a014328 100644 (file)
@@ -39,7 +39,7 @@ config ARC
        select OF
        select OF_EARLY_FLATTREE
        select OF_RESERVED_MEM
-       select PERF_USE_VMALLOC
+       select PERF_USE_VMALLOC if ARC_CACHE_VIPT_ALIASING
        select HAVE_DEBUG_STACKOVERFLOW
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_KERNEL_GZIP
index e114000a84f56c9e07ddd3a2e623c4dfeb3df6a2..74d070cd3c13a723fef1a2b3cd91cd2919392762 100644 (file)
                ranges = <0x00000000 0x0 0xe0000000 0x10000000>;
                interrupt-parent = <&mb_intc>;
 
+               creg_rst: reset-controller@11220 {
+                       compatible = "snps,axs10x-reset";
+                       #reset-cells = <1>;
+                       reg = <0x11220 0x4>;
+               };
+
                i2sclk: i2sclk@100a0 {
                        compatible = "snps,axs10x-i2s-pll-clock";
                        reg = <0x100a0 0x10>;
@@ -73,6 +79,8 @@
                        clocks = <&apbclk>;
                        clock-names = "stmmaceth";
                        max-speed = <100>;
+                       resets = <&creg_rst 5>;
+                       reset-names = "stmmaceth";
                };
 
                ehci@0x40000 {
index b1c56d35f2a938e59c9677454499aeecb1da4f7e..49bfbd879caa6ffa08553e9b0f49b542739bb95b 100644 (file)
 
 /* Build Configuration Registers */
 #define ARC_REG_AUX_DCCM       0x18    /* DCCM Base Addr ARCv2 */
+#define ARC_REG_ERP_CTRL       0x3F    /* ARCv2 Error protection control */
 #define ARC_REG_DCCM_BASE_BUILD        0x61    /* DCCM Base Addr ARCompact */
 #define ARC_REG_CRC_BCR                0x62
 #define ARC_REG_VECBASE_BCR    0x68
 #define ARC_REG_PERIBASE_BCR   0x69
 #define ARC_REG_FP_BCR         0x6B    /* ARCompact: Single-Precision FPU */
 #define ARC_REG_DPFP_BCR       0x6C    /* ARCompact: Dbl Precision FPU */
+#define ARC_REG_ERP_BUILD      0xc7    /* ARCv2 Error protection Build: ECC/Parity */
 #define ARC_REG_FP_V2_BCR      0xc8    /* ARCv2 FPU */
 #define ARC_REG_SLC_BCR                0xce
 #define ARC_REG_DCCM_BUILD     0x74    /* DCCM size (common) */
 #define ARC_REG_D_UNCACH_BCR   0x6A
 #define ARC_REG_BPU_BCR                0xc0
 #define ARC_REG_ISA_CFG_BCR    0xc1
+#define ARC_REG_LPB_BUILD      0xE9    /* ARCv2 Loop Buffer Build */
 #define ARC_REG_RTT_BCR                0xF2
 #define ARC_REG_IRQ_BCR                0xF3
+#define ARC_REG_MICRO_ARCH_BCR 0xF9    /* ARCv2 Product revision */
 #define ARC_REG_SMART_BCR      0xFF
 #define ARC_REG_CLUSTER_BCR    0xcf
 #define ARC_REG_AUX_ICCM       0x208   /* ICCM Base Addr (ARCv2) */
+#define ARC_REG_LPB_CTRL       0x488   /* ARCv2 Loop Buffer control */
 
 /* Common for ARCompact and ARCv2 status register */
 #define ARC_REG_STATUS32       0x0A
@@ -229,6 +234,32 @@ struct bcr_bpu_arcv2 {
 #endif
 };
 
+/* Error Protection Build: ECC/Parity */
+struct bcr_erp {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad3:5, mmu:3, pad2:4, ic:3, dc:3, pad1:6, ver:8;
+#else
+       unsigned int ver:8, pad1:6, dc:3, ic:3, pad2:4, mmu:3, pad3:5;
+#endif
+};
+
+/* Error Protection Control */
+struct ctl_erp {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad2:27, mpd:1, pad1:2, dpd:1, dpi:1;
+#else
+       unsigned int dpi:1, dpd:1, pad1:2, mpd:1, pad2:27;
+#endif
+};
+
+struct bcr_lpb {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad:16, entries:8, ver:8;
+#else
+       unsigned int ver:8, entries:8, pad:16;
+#endif
+};
+
 struct bcr_generic {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int info:24, ver:8;
@@ -270,7 +301,7 @@ struct cpuinfo_arc {
        struct cpuinfo_arc_ccm iccm, dccm;
        struct {
                unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, swape:1, pad1:2,
-                            fpu_sp:1, fpu_dp:1, dual_iss_enb:1, dual_iss_exist:1, pad2:4,
+                            fpu_sp:1, fpu_dp:1, dual:1, dual_enb:1, pad2:4,
                             debug:1, ap:1, smart:1, rtt:1, pad3:4,
                             timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4;
        } extn;
index 2ce24e74f87956af0bba1d9430200196353bdff8..8aec462d90fbe8f0aa88847272d02004a863f2db 100644 (file)
@@ -336,15 +336,12 @@ static int arc_pmu_add(struct perf_event *event, int flags)
        struct hw_perf_event *hwc = &event->hw;
        int idx = hwc->idx;
 
-       if (__test_and_set_bit(idx, pmu_cpu->used_mask)) {
-               idx = find_first_zero_bit(pmu_cpu->used_mask,
-                                         arc_pmu->n_counters);
-               if (idx == arc_pmu->n_counters)
-                       return -EAGAIN;
-
-               __set_bit(idx, pmu_cpu->used_mask);
-               hwc->idx = idx;
-       }
+       idx = ffz(pmu_cpu->used_mask[0]);
+       if (idx == arc_pmu->n_counters)
+               return -EAGAIN;
+
+       __set_bit(idx, pmu_cpu->used_mask);
+       hwc->idx = idx;
 
        write_aux_reg(ARC_REG_PCT_INDEX, idx);
 
@@ -377,21 +374,22 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
        struct perf_sample_data data;
        struct arc_pmu_cpu *pmu_cpu = this_cpu_ptr(&arc_pmu_cpu);
        struct pt_regs *regs;
-       int active_ints;
+       unsigned int active_ints;
        int idx;
 
        arc_pmu_disable(&arc_pmu->pmu);
 
        active_ints = read_aux_reg(ARC_REG_PCT_INT_ACT);
+       if (!active_ints)
+               goto done;
 
        regs = get_irq_regs();
 
-       for (idx = 0; idx < arc_pmu->n_counters; idx++) {
-               struct perf_event *event = pmu_cpu->act_counter[idx];
+       do {
+               struct perf_event *event;
                struct hw_perf_event *hwc;
 
-               if (!(active_ints & (1 << idx)))
-                       continue;
+               idx = __ffs(active_ints);
 
                /* Reset interrupt flag by writing of 1 */
                write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
@@ -404,19 +402,22 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
                write_aux_reg(ARC_REG_PCT_INT_CTRL,
                        read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx));
 
+               event = pmu_cpu->act_counter[idx];
                hwc = &event->hw;
 
                WARN_ON_ONCE(hwc->idx != idx);
 
                arc_perf_event_update(event, &event->hw, event->hw.idx);
                perf_sample_data_init(&data, 0, hwc->last_period);
-               if (!arc_pmu_event_set_period(event))
-                       continue;
+               if (arc_pmu_event_set_period(event)) {
+                       if (perf_event_overflow(event, &data, regs))
+                               arc_pmu_stop(event, 0);
+               }
 
-               if (perf_event_overflow(event, &data, regs))
-                       arc_pmu_stop(event, 0);
-       }
+               active_ints &= ~(1U << idx);
+       } while (active_ints);
 
+done:
        arc_pmu_enable(&arc_pmu->pmu);
 
        return IRQ_HANDLED;
@@ -461,6 +462,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                pr_err("This core does not have performance counters!\n");
                return -ENODEV;
        }
+       BUILD_BUG_ON(ARC_PERF_MAX_COUNTERS > 32);
        BUG_ON(pct_bcr.c > ARC_PERF_MAX_COUNTERS);
 
        READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
index fb83844daeea3550aacd27de2525711a6aa5fddc..7ef7d9a8ff89231811e73a241a3a3c6d248e720b 100644 (file)
@@ -199,8 +199,10 @@ static void read_arc_build_cfg_regs(void)
                        unsigned int exec_ctrl;
 
                        READ_BCR(AUX_EXEC_CTRL, exec_ctrl);
-                       cpu->extn.dual_iss_exist = 1;
-                       cpu->extn.dual_iss_enb = exec_ctrl & 1;
+                       cpu->extn.dual_enb = exec_ctrl & 1;
+
+                       /* dual issue always present for this core */
+                       cpu->extn.dual = 1;
                }
        }
 
@@ -253,7 +255,7 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
                       cpu_id, cpu->name, cpu->details,
                       is_isa_arcompact() ? "ARCompact" : "ARCv2",
                       IS_AVAIL1(cpu->isa.be, "[Big-Endian]"),
-                      IS_AVAIL3(cpu->extn.dual_iss_exist, cpu->extn.dual_iss_enb, " Dual-Issue"));
+                      IS_AVAIL3(cpu->extn.dual, cpu->extn.dual_enb, " Dual-Issue "));
 
        n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s%s%s\nISA Extn\t: ",
                       IS_AVAIL1(cpu->extn.timer0, "Timer0 "),
@@ -293,11 +295,26 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 
        if (cpu->bpu.ver)
                n += scnprintf(buf + n, len - n,
-                             "BPU\t\t: %s%s match, cache:%d, Predict Table:%d\n",
+                             "BPU\t\t: %s%s match, cache:%d, Predict Table:%d",
                              IS_AVAIL1(cpu->bpu.full, "full"),
                              IS_AVAIL1(!cpu->bpu.full, "partial"),
                              cpu->bpu.num_cache, cpu->bpu.num_pred);
 
+       if (is_isa_arcv2()) {
+               struct bcr_lpb lpb;
+
+               READ_BCR(ARC_REG_LPB_BUILD, lpb);
+               if (lpb.ver) {
+                       unsigned int ctl;
+                       ctl = read_aux_reg(ARC_REG_LPB_CTRL);
+
+                       n += scnprintf(buf + n, len - n, " Loop Buffer:%d %s",
+                               lpb.entries,
+                               IS_DISABLED_RUN(!ctl));
+               }
+       }
+
+       n += scnprintf(buf + n, len - n, "\n");
        return buf;
 }
 
@@ -326,6 +343,24 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
                               cpu->dccm.base_addr, TO_KB(cpu->dccm.sz),
                               cpu->iccm.base_addr, TO_KB(cpu->iccm.sz));
 
+       if (is_isa_arcv2()) {
+
+               /* Error Protection: ECC/Parity */
+               struct bcr_erp erp;
+               READ_BCR(ARC_REG_ERP_BUILD, erp);
+
+               if (erp.ver) {
+                       struct  ctl_erp ctl;
+                       READ_BCR(ARC_REG_ERP_CTRL, ctl);
+
+                       /* inverted bits: 0 means enabled */
+                       n += scnprintf(buf + n, len - n, "Extn [ECC]\t: %s%s%s%s%s%s\n",
+                               IS_AVAIL3(erp.ic,  !ctl.dpi, "IC "),
+                               IS_AVAIL3(erp.dc,  !ctl.dpd, "DC "),
+                               IS_AVAIL3(erp.mmu, !ctl.mpd, "MMU "));
+               }
+       }
+
        n += scnprintf(buf + n, len - n, "OS ABI [v%d]\t: %s\n",
                        EF_ARC_OSABI_CURRENT >> 8,
                        EF_ARC_OSABI_CURRENT == EF_ARC_OSABI_V3 ?
index 8ceefbf72fb0f8b0d1ce9ca1516bb7edd487cc9a..4097764fea23499a828a559f70a62a29daba14c8 100644 (file)
@@ -762,21 +762,23 @@ void read_decode_mmu_bcr(void)
        tmp = read_aux_reg(ARC_REG_MMU_BCR);
        mmu->ver = (tmp >> 24);
 
-       if (mmu->ver <= 2) {
-               mmu2 = (struct bcr_mmu_1_2 *)&tmp;
-               mmu->pg_sz_k = TO_KB(0x2000);
-               mmu->sets = 1 << mmu2->sets;
-               mmu->ways = 1 << mmu2->ways;
-               mmu->u_dtlb = mmu2->u_dtlb;
-               mmu->u_itlb = mmu2->u_itlb;
-       } else if (mmu->ver == 3) {
-               mmu3 = (struct bcr_mmu_3 *)&tmp;
-               mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1);
-               mmu->sets = 1 << mmu3->sets;
-               mmu->ways = 1 << mmu3->ways;
-               mmu->u_dtlb = mmu3->u_dtlb;
-               mmu->u_itlb = mmu3->u_itlb;
-               mmu->sasid = mmu3->sasid;
+       if (is_isa_arcompact()) {
+               if (mmu->ver <= 2) {
+                       mmu2 = (struct bcr_mmu_1_2 *)&tmp;
+                       mmu->pg_sz_k = TO_KB(0x2000);
+                       mmu->sets = 1 << mmu2->sets;
+                       mmu->ways = 1 << mmu2->ways;
+                       mmu->u_dtlb = mmu2->u_dtlb;
+                       mmu->u_itlb = mmu2->u_itlb;
+               } else {
+                       mmu3 = (struct bcr_mmu_3 *)&tmp;
+                       mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1);
+                       mmu->sets = 1 << mmu3->sets;
+                       mmu->ways = 1 << mmu3->ways;
+                       mmu->u_dtlb = mmu3->u_dtlb;
+                       mmu->u_itlb = mmu3->u_itlb;
+                       mmu->sasid = mmu3->sasid;
+               }
        } else {
                mmu4 = (struct bcr_mmu_4 *)&tmp;
                mmu->pg_sz_k = 1 << (mmu4->sz0 - 1);
@@ -818,8 +820,9 @@ int pae40_exist_but_not_enab(void)
 
 void arc_mmu_init(void)
 {
-       char str[256];
        struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu;
+       char str[256];
+       int compat = 0;
 
        pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str)));
 
@@ -834,15 +837,21 @@ void arc_mmu_init(void)
         */
        BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE));
 
-       /* For efficiency sake, kernel is compile time built for a MMU ver
-        * This must match the hardware it is running on.
-        * Linux built for MMU V2, if run on MMU V1 will break down because V1
-        *  hardware doesn't understand cmds such as WriteNI, or IVUTLB
-        * On the other hand, Linux built for V1 if run on MMU V2 will do
-        *   un-needed workarounds to prevent memcpy thrashing.
-        * Similarly MMU V3 has new features which won't work on older MMU
+       /*
+        * Ensure that MMU features assumed by kernel exist in hardware.
+        * For older ARC700 cpus, it has to be exact match, since the MMU
+        * revisions were not backwards compatible (MMUv3 TLB layout changed
+        * so even if kernel for v2 didn't use any new cmds of v3, it would
+        * still not work.
+        * For HS cpus, MMUv4 was baseline and v5 is backwards compatible
+        * (will run older software).
         */
-       if (mmu->ver != CONFIG_ARC_MMU_VER) {
+       if (is_isa_arcompact() && mmu->ver == CONFIG_ARC_MMU_VER)
+               compat = 1;
+       else if (is_isa_arcv2() && mmu->ver >= CONFIG_ARC_MMU_VER)
+               compat = 1;
+
+       if (!compat) {
                panic("MMU ver %d doesn't match kernel built for %d...\n",
                      mmu->ver, CONFIG_ARC_MMU_VER);
        }
index c54d1ae57fe0b3feffd4578387f11593c45308e4..4e0df7b7a248147af495948e95488a67e0b78499 100644 (file)
@@ -14,6 +14,8 @@ menuconfig ARC_PLAT_AXS10X
        select MIGHT_HAVE_PCI
        select GENERIC_IRQ_CHIP
        select GPIOLIB
+       select AXS101 if ISA_ARCOMPACT
+       select AXS103 if ISA_ARCV2
        help
          Support for the ARC AXS10x Software Development Platforms.
 
index cf14ebc36916a2a0eca39728c0cc0f315d58bbeb..f1ac6790da5fe64782b59b720bf3ea80d999bff1 100644 (file)
@@ -111,13 +111,6 @@ static void __init axs10x_early_init(void)
 
        axs10x_enable_gpio_intc_wire();
 
-       /*
-        * Reset ethernet IP core.
-        * TODO: get rid of this quirk after axs10x reset driver (or simple
-        * reset driver) will be available in upstream.
-        */
-       iowrite32((1 << 5), (void __iomem *) CREG_MB_SW_RESET);
-
        scnprintf(mb, 32, "MainBoard v%d", mb_rev);
        axs10x_print_board_ver(CREG_MB_VER, mb);
 }