Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/sunxi Add Allwinner A83T SMP support.



details:   https://anonhg.NetBSD.org/src/rev/f08caf73efe0
branches:  trunk
changeset: 838103:f08caf73efe0
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Thu Jan 03 11:01:59 2019 +0000

description:
Add Allwinner A83T SMP support.

diffstat:

 sys/arch/arm/sunxi/files.sunxi        |    9 +-
 sys/arch/arm/sunxi/sunxi_mc_mpstart.S |   82 +++++++++++++
 sys/arch/arm/sunxi/sunxi_mc_smp.c     |  209 ++++++++++++++++++++++++++++++++++
 sys/arch/arm/sunxi/sunxi_mc_smp.h     |   35 +++++
 sys/arch/arm/sunxi/sunxi_platform.c   |   91 ++++++++++++++-
 5 files changed, 421 insertions(+), 5 deletions(-)

diffs (truncated from 510 to 300 lines):

diff -r 35798133f4fa -r f08caf73efe0 sys/arch/arm/sunxi/files.sunxi
--- a/sys/arch/arm/sunxi/files.sunxi    Thu Jan 03 10:44:04 2019 +0000
+++ b/sys/arch/arm/sunxi/files.sunxi    Thu Jan 03 11:01:59 2019 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.sunxi,v 1.57 2018/06/01 22:11:54 jmcneill Exp $
+#      $NetBSD: files.sunxi,v 1.58 2019/01/03 11:01:59 jmcneill Exp $
 #
 # Configuration info for Allwinner sunxi family SoCs
 #
@@ -6,6 +6,9 @@
 
 file   arch/arm/sunxi/sunxi_platform.c         soc_sunxi
 
+file   arch/arm/sunxi/sunxi_mc_smp.c           soc_sunxi_mc
+file   arch/arm/sunxi/sunxi_mc_mpstart.S       soc_sunxi_mc
+
 # CCU
 define sunxi_ccu
 file   arch/arm/sunxi/sunxi_ccu.c              sunxi_ccu
@@ -293,8 +296,10 @@
 device sunxilradc
 attach sunxilradc at fdt with sunxi_lradc
 file   arch/arm/sunxi/sunxi_lradc.c            sunxi_lradc
+
 # SOC parameters
 defflag        opt_soc.h                       SOC_SUNXI
+defflag        opt_soc.h                       SOC_SUNXI_MC
 defflag        opt_soc.h                       SOC_SUN4I: SOC_SUNXI
 defflag        opt_soc.h                       SOC_SUN4I_A10: SOC_SUN4I
 defflag        opt_soc.h                       SOC_SUN5I: SOC_SUNXI
@@ -304,7 +309,7 @@
 defflag        opt_soc.h                       SOC_SUN7I: SOC_SUNXI
 defflag        opt_soc.h                       SOC_SUN7I_A20: SOC_SUN7I
 defflag        opt_soc.h                       SOC_SUN8I: SOC_SUNXI
-defflag        opt_soc.h                       SOC_SUN8I_A83T: SOC_SUN8I
+defflag        opt_soc.h                       SOC_SUN8I_A83T: SOC_SUN8I, SOC_SUNXI_MC
 defflag        opt_soc.h                       SOC_SUN8I_H3: SOC_SUN8I
 defflag        opt_soc.h                       SOC_SUN9I: SOC_SUNXI
 defflag        opt_soc.h                       SOC_SUN9I_A80: SOC_SUN9I
diff -r 35798133f4fa -r f08caf73efe0 sys/arch/arm/sunxi/sunxi_mc_mpstart.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/sunxi/sunxi_mc_mpstart.S     Thu Jan 03 11:01:59 2019 +0000
@@ -0,0 +1,82 @@
+/* $NetBSD: sunxi_mc_mpstart.S,v 1.1 2019/01/03 11:01:59 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2018 Jared McNeill <jmcneill%invisible.ca@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <arm/asm.h>
+#include <arm/armreg.h>
+#include "assym.h"
+
+#define        CCI_SNOOP_CTRL          0x000
+#define         CCI_SNOOP_CTRL_DVM     __BIT(1)
+#define         CCI_SNOOP_CTRL_SNOOP   __BIT(0)
+
+       R_TMP1          .req r8
+       R_VTOPDIFF      .req r10
+
+       .global _C_LABEL(sunxi_mc_mpstart)
+_C_LABEL(sunxi_mc_mpstart):
+
+       adr     R_TMP1, sunxi_mc_mpstart 
+       ldr     R_VTOPDIFF, =sunxi_mc_mpstart
+       sub     R_VTOPDIFF, R_VTOPDIFF, R_TMP1
+
+       mrc     p15, 0, r4, c0, c0, 5           // MPIDR get
+       and     r4, #(MPIDR_AFF2|MPIDR_AFF1|MPIDR_AFF0)
+
+       mov     r0, #0
+       ldr     r1, =cpu_mpidr
+       sub     r1, R_VTOPDIFF
+1:
+
+       ldr     r2, [r1, r0, lsl #2]            // r2 = cpu_mpidr[r0]
+       cmp     r2, r4
+       beq     2f                              // found our mpidr
+
+       add     r0, #1
+       cmp     r0, #MAXCPUS
+       bne     1b
+
+       // Not found our mpidr in the list - use Aff0 for cpuindex
+       and     r0, r4, #7
+2:
+
+       // Find our CCI-400 interface's base address by cpuindex
+       ldr     r1, =sunxi_mc_cci_port
+       sub     r1, R_VTOPDIFF
+       ldr     r2, [r1, r0, lsl #2]            // r2 = sunxi_mc_cci_port[r0]
+
+       cmp     r2, #0
+       beq     3f
+
+       // Enable snooping and DVM broadcast on our CCI-400 interface
+       mov     r3, #(CCI_SNOOP_CTRL_DVM|CCI_SNOOP_CTRL_SNOOP)
+       str     r3, [r2, #CCI_SNOOP_CTRL]
+
+3:
+       b cpu_mpstart
diff -r 35798133f4fa -r f08caf73efe0 sys/arch/arm/sunxi/sunxi_mc_smp.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/sunxi/sunxi_mc_smp.c Thu Jan 03 11:01:59 2019 +0000
@@ -0,0 +1,209 @@
+/* $NetBSD: sunxi_mc_smp.c,v 1.1 2019/01/03 11:01:59 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jared McNeill <jmcneill%invisible.ca@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(0, "$NetBSD: sunxi_mc_smp.c,v 1.1 2019/01/03 11:01:59 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/armreg.h>
+#include <arm/cpu.h>
+#include <arm/cpufunc.h>
+#include <arm/locore.h>
+
+#include <arm/sunxi/sunxi_mc_smp.h>
+
+#define        A83T_SMP_ENABLE_METHOD  "allwinner,sun8i-a83t-smp"
+
+#define        PRCM_BASE               0x01f01400
+#define        PRCM_SIZE               0x800
+
+#define         PRCM_CL_RST_CTRL(cluster)      (0x4 + (cluster) * 0x4)
+#define         PRCM_CL_PWROFF(cluster)        (0x100 + (cluster) * 0x4)
+#define         PRCM_CL_PWR_CLAMP(cluster, cpu) (0x140 + (cluster) * 0x10 + (cpu) * 0x4)
+
+#define        CPUCFG_BASE     0x01f01c00
+#define        CPUCFG_SIZE     0x400
+
+#define         CPUCFG_CL_RST(cluster)         (0x30 + (cluster) * 0x4)
+#define         CPUCFG_P_REG0                  0x1a4
+
+#define        CPUXCFG_BASE    0x01700000
+#define        CPUXCFG_SIZE    0x400
+
+#define         CPUXCFG_CL_RST(cluster)        (0x80 + (cluster) * 0x4)
+#define          CPUXCFG_CL_RST_SOC_DBG_RST    __BIT(24)
+#define          CPUXCFG_CL_RST_ETM_RST(cpu)   __BIT(20 + (cpu))
+#define          CPUXCFG_CL_RST_DBG_RST(cpu)   __BIT(16 + (cpu))
+#define          CPUXCFG_CL_RST_H_RST          __BIT(12)
+#define          CPUXCFG_CL_RST_L2_RST         __BIT(8)
+#define         CPUXCFG_CL_CTRL0(cluster)      (0x0 + (cluster) * 0x10)
+#define         CPUXCFG_CL_CTRL1(cluster)      (0x4 + (cluster) * 0x10)
+#define          CPUXCFG_CL_CTRL1_ACINACTM     __BIT(0)
+
+#define        CCI_BASE                0x01790000
+#define        CCI_SLAVEIF3_BASE       (CCI_BASE + 0x4000)
+#define        CCI_SLAVEIF4_BASE       (CCI_BASE + 0x5000)
+
+extern struct bus_space arm_generic_bs_tag;
+
+uint32_t sunxi_mc_cci_port[MAXCPUS] = {
+       CCI_SLAVEIF3_BASE,
+       CCI_SLAVEIF3_BASE,
+       CCI_SLAVEIF3_BASE,
+       CCI_SLAVEIF3_BASE,
+       CCI_SLAVEIF4_BASE,
+       CCI_SLAVEIF4_BASE,
+       CCI_SLAVEIF4_BASE,
+       CCI_SLAVEIF4_BASE,
+};
+
+static uint32_t
+sunxi_mc_smp_pa(void)
+{
+       extern void sunxi_mc_mpstart(void);
+       bool ok __diagused;
+       paddr_t pa;
+
+       ok = pmap_extract(pmap_kernel(), (vaddr_t)sunxi_mc_mpstart, &pa);
+       KASSERT(ok);
+
+       return pa;
+}
+
+static int
+sunxi_mc_smp_start(bus_space_tag_t bst, bus_space_handle_t prcm, bus_space_handle_t cpucfg,
+    bus_space_handle_t cpuxcfg, u_int cluster, u_int cpu)
+{
+       uint32_t val;
+       int i;
+
+       /* Set start vector */
+       bus_space_write_4(bst, cpucfg, CPUCFG_P_REG0, sunxi_mc_smp_pa());
+
+       /* Assert core reset */
+       val = bus_space_read_4(bst, cpuxcfg, CPUXCFG_CL_RST(cluster));
+       val &= ~__BIT(cpu);
+       bus_space_write_4(bst, cpuxcfg, CPUXCFG_CL_RST(cluster), val);
+
+       /* Assert power-on reset */
+       val = bus_space_read_4(bst, cpucfg, CPUCFG_CL_RST(cluster));
+       val &= ~__BIT(cpu);
+       bus_space_write_4(bst, cpucfg, CPUCFG_CL_RST(cluster), val);
+
+       /* Disable automatic L1 cache invalidate at reset */
+       val = bus_space_read_4(bst, cpuxcfg, CPUXCFG_CL_CTRL0(cluster));
+       val &= ~__BIT(cpu);
+       bus_space_write_4(bst, cpuxcfg, CPUXCFG_CL_CTRL0(cluster), val);
+
+       /* Release power clamp */
+       for (i = 0; i <= 8; i++) {
+               bus_space_write_4(bst, prcm, PRCM_CL_PWR_CLAMP(cluster, cpu), 0xff >> i);
+               delay(10);
+       }
+       for (i = 100000; i > 0; i--) {
+               if (bus_space_read_4(bst, prcm, PRCM_CL_PWR_CLAMP(cluster, cpu)) == 0)
+                       break;
+       }
+       if (i == 0) {
+               printf("CPU %#llx failed to start\n", __SHIFTIN(cluster, MPIDR_AFF1) | __SHIFTIN(cpu, MPIDR_AFF0));
+               return ETIMEDOUT;
+       }
+
+       /* Clear power-off gating */
+       val = bus_space_read_4(bst, prcm, PRCM_CL_PWROFF(cluster));
+       if (cpu == 0)
+               val &= ~__BIT(4);
+       val &= ~__BIT(cpu);
+       bus_space_write_4(bst, prcm, PRCM_CL_PWROFF(cluster), val);
+
+       /* De-assert power-on reset */
+       val = bus_space_read_4(bst, prcm, PRCM_CL_RST_CTRL(cluster));
+       val |= __BIT(cpu);
+       bus_space_write_4(bst, prcm, PRCM_CL_RST_CTRL(cluster), val);
+
+       val = bus_space_read_4(bst, cpucfg, CPUCFG_CL_RST(cluster));
+       val |= __BIT(cpu);
+       bus_space_write_4(bst, cpucfg, CPUCFG_CL_RST(cluster), val);
+       delay(10);
+
+       /* De-assert core reset */
+       val = bus_space_read_4(bst, cpuxcfg, CPUXCFG_CL_RST(cluster));
+       val |= __BIT(cpu);
+       val |= CPUXCFG_CL_RST_SOC_DBG_RST;
+       val |= CPUXCFG_CL_RST_ETM_RST(cpu);
+       val |= CPUXCFG_CL_RST_DBG_RST(cpu);
+       val |= CPUXCFG_CL_RST_L2_RST;
+       val |= CPUXCFG_CL_RST_H_RST;
+       bus_space_write_4(bst, cpuxcfg, CPUXCFG_CL_RST(cluster), val);



Home | Main Index | Thread Index | Old Index