Module Name: src Committed By: jmcneill Date: Thu Jan 3 14:44:21 UTC 2019
Modified Files: src/sys/arch/arm/sunxi: files.sunxi sunxi_mc_smp.c sunxi_mc_smp.h sunxi_platform.c Log Message: Add Allwinner A80 SMP support. To generate a diff of this commit: cvs rdiff -u -r1.58 -r1.59 src/sys/arch/arm/sunxi/files.sunxi cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/sunxi/sunxi_mc_smp.c cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/sunxi/sunxi_mc_smp.h cvs rdiff -u -r1.33 -r1.34 src/sys/arch/arm/sunxi/sunxi_platform.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/sunxi/files.sunxi diff -u src/sys/arch/arm/sunxi/files.sunxi:1.58 src/sys/arch/arm/sunxi/files.sunxi:1.59 --- src/sys/arch/arm/sunxi/files.sunxi:1.58 Thu Jan 3 11:01:59 2019 +++ src/sys/arch/arm/sunxi/files.sunxi Thu Jan 3 14:44:21 2019 @@ -1,4 +1,4 @@ -# $NetBSD: files.sunxi,v 1.58 2019/01/03 11:01:59 jmcneill Exp $ +# $NetBSD: files.sunxi,v 1.59 2019/01/03 14:44:21 jmcneill Exp $ # # Configuration info for Allwinner sunxi family SoCs # @@ -312,7 +312,7 @@ defflag opt_soc.h SOC_SUN8I: SOC_SUNXI 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 +defflag opt_soc.h SOC_SUN9I_A80: SOC_SUN9I, SOC_SUNXI_MC defflag opt_soc.h SOC_SUN50I: SOC_SUNXI defflag opt_soc.h SOC_SUN50I_A64: SOC_SUN50I defflag opt_soc.h SOC_SUN50I_H5: SOC_SUN50I, SOC_SUN8I_H3 Index: src/sys/arch/arm/sunxi/sunxi_mc_smp.c diff -u src/sys/arch/arm/sunxi/sunxi_mc_smp.c:1.2 src/sys/arch/arm/sunxi/sunxi_mc_smp.c:1.3 --- src/sys/arch/arm/sunxi/sunxi_mc_smp.c:1.2 Thu Jan 3 12:52:40 2019 +++ src/sys/arch/arm/sunxi/sunxi_mc_smp.c Thu Jan 3 14:44:21 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_mc_smp.c,v 1.2 2019/01/03 12:52:40 jmcneill Exp $ */ +/* $NetBSD: sunxi_mc_smp.c,v 1.3 2019/01/03 14:44:21 jmcneill Exp $ */ /*- * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sunxi_mc_smp.c,v 1.2 2019/01/03 12:52:40 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sunxi_mc_smp.c,v 1.3 2019/01/03 14:44:21 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -46,14 +46,16 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_mc_smp #include <arm/sunxi/sunxi_mc_smp.h> -#define A83T_SMP_ENABLE_METHOD "allwinner,sun8i-a83t-smp" +#define A80_PRCM_BASE 0x08001400 +#define A80_PRCM_SIZE 0x200 -#define PRCM_BASE 0x01f01400 -#define PRCM_SIZE 0x800 +#define A83T_PRCM_BASE 0x01f01400 +#define A83T_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 PRCM_CPU_SOFT_ENTRY 0x164 #define CPUCFG_BASE 0x01f01c00 #define CPUCFG_SIZE 0x400 @@ -70,27 +72,31 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_mc_smp #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_RST_CX_RST(cpu) __BIT(4 + (cpu)) #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) +#define A80_CCI_BASE 0x01c90000 +#define A83T_CCI_BASE 0x01790000 + +#define CCI_SLAVEIF3_OFFSET 0x4000 +#define CCI_SLAVEIF4_OFFSET 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, +enum sunxi_mc_soc { + MC_SOC_A80, + MC_SOC_A83T +}; + +enum sunxi_mc_cpu { + MC_CORE_CA7, + MC_CORE_CA15 }; +uint32_t sunxi_mc_cci_port[MAXCPUS]; + static uint32_t sunxi_mc_smp_pa(void) { @@ -106,28 +112,30 @@ sunxi_mc_smp_pa(void) 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) + bus_space_handle_t cpuxcfg, u_int cluster, u_int cpu, enum sunxi_mc_soc soc, + enum sunxi_mc_cpu core) { 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); + if (soc == MC_SOC_A83T) { + /* 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); + if (core == MC_CORE_CA7) { + /* 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++) { @@ -145,9 +153,14 @@ sunxi_mc_smp_start(bus_space_tag_t bst, /* Clear power-off gating */ val = bus_space_read_4(bst, prcm, PRCM_CL_PWROFF(cluster)); - if (cpu == 0) - val &= ~__BIT(4); - val &= ~__BIT(cpu); + if (soc == MC_SOC_A83T) { + if (cpu == 0) + val &= ~__BIT(4); + val &= ~__BIT(0); /* cluster power gate */ + } else { + val &= ~__BIT(cpu); + val &= ~__BIT(4); /* cluster power gate */ + } bus_space_write_4(bst, prcm, PRCM_CL_PWROFF(cluster), val); /* De-assert power-on reset */ @@ -155,16 +168,21 @@ sunxi_mc_smp_start(bus_space_tag_t bst, 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); + if (soc == MC_SOC_A83T) { + 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); + if (core == MC_CORE_CA7) + val |= CPUXCFG_CL_RST_ETM_RST(cpu); + else + val |= CPUXCFG_CL_RST_CX_RST(cpu); val |= CPUXCFG_CL_RST_DBG_RST(cpu); val |= CPUXCFG_CL_RST_L2_RST; val |= CPUXCFG_CL_RST_H_RST; @@ -179,7 +197,7 @@ sunxi_mc_smp_start(bus_space_tag_t bst, } int -sunxi_mc_smp_enable(u_int mpidr) +sun8i_a83t_smp_enable(u_int mpidr) { bus_space_tag_t bst = &arm_generic_bs_tag; bus_space_handle_t prcm, cpucfg, cpuxcfg; @@ -188,16 +206,58 @@ sunxi_mc_smp_enable(u_int mpidr) const u_int cluster = __SHIFTOUT(mpidr, MPIDR_AFF1); const u_int cpu = __SHIFTOUT(mpidr, MPIDR_AFF0); - if (bus_space_map(bst, PRCM_BASE, PRCM_SIZE, 0, &prcm) != 0 || + if (bus_space_map(bst, A83T_PRCM_BASE, A83T_PRCM_SIZE, 0, &prcm) != 0 || bus_space_map(bst, CPUCFG_BASE, CPUCFG_SIZE, 0, &cpucfg) != 0 || bus_space_map(bst, CPUXCFG_BASE, CPUXCFG_SIZE, 0, &cpuxcfg) != 0) return ENOMEM; - error = sunxi_mc_smp_start(bst, prcm, cpucfg, cpuxcfg, cluster, cpu); + for (int i = 0; i < 4; i++) + sunxi_mc_cci_port[i] = A83T_CCI_BASE + CCI_SLAVEIF3_OFFSET; + for (int i = 4; i < 8; i++) + sunxi_mc_cci_port[i] = A83T_CCI_BASE + CCI_SLAVEIF4_OFFSET; + + /* Set start vector */ + bus_space_write_4(bst, cpucfg, CPUCFG_P_REG0, sunxi_mc_smp_pa()); + cpu_idcache_wbinv_all(); + + error = sunxi_mc_smp_start(bst, prcm, cpucfg, cpuxcfg, cluster, cpu, + MC_SOC_A83T, MC_CORE_CA7); bus_space_unmap(bst, cpuxcfg, CPUXCFG_SIZE); bus_space_unmap(bst, cpucfg, CPUCFG_SIZE); - bus_space_unmap(bst, prcm, PRCM_SIZE); + bus_space_unmap(bst, prcm, A83T_PRCM_SIZE); + + return error; +} + +int +sun9i_a80_smp_enable(u_int mpidr) +{ + bus_space_tag_t bst = &arm_generic_bs_tag; + bus_space_handle_t prcm, cpuxcfg; + int error; + + const u_int cluster = __SHIFTOUT(mpidr, MPIDR_AFF1); + const u_int cpu = __SHIFTOUT(mpidr, MPIDR_AFF0); + + if (bus_space_map(bst, A80_PRCM_BASE, A80_PRCM_SIZE, 0, &prcm) != 0 || + bus_space_map(bst, CPUXCFG_BASE, CPUXCFG_SIZE, 0, &cpuxcfg) != 0) + return ENOMEM; + + for (int i = 0; i < 4; i++) + sunxi_mc_cci_port[i] = A80_CCI_BASE + CCI_SLAVEIF3_OFFSET; + for (int i = 4; i < 8; i++) + sunxi_mc_cci_port[i] = A80_CCI_BASE + CCI_SLAVEIF4_OFFSET; + + /* Set start vector */ + bus_space_write_4(bst, prcm, PRCM_CPU_SOFT_ENTRY, sunxi_mc_smp_pa()); + cpu_idcache_wbinv_all(); + + error = sunxi_mc_smp_start(bst, prcm, 0, cpuxcfg, cluster, cpu, + MC_SOC_A80, cluster == 0 ? MC_CORE_CA7 : MC_CORE_CA15); + + bus_space_unmap(bst, cpuxcfg, CPUXCFG_SIZE); + bus_space_unmap(bst, prcm, A80_PRCM_SIZE); return error; } Index: src/sys/arch/arm/sunxi/sunxi_mc_smp.h diff -u src/sys/arch/arm/sunxi/sunxi_mc_smp.h:1.1 src/sys/arch/arm/sunxi/sunxi_mc_smp.h:1.2 --- src/sys/arch/arm/sunxi/sunxi_mc_smp.h:1.1 Thu Jan 3 11:01:59 2019 +++ src/sys/arch/arm/sunxi/sunxi_mc_smp.h Thu Jan 3 14:44:21 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_mc_smp.h,v 1.1 2019/01/03 11:01:59 jmcneill Exp $ */ +/* $NetBSD: sunxi_mc_smp.h,v 1.2 2019/01/03 14:44:21 jmcneill Exp $ */ /*- * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca> @@ -30,6 +30,7 @@ #define _SUNXI_MC_SMP_H int sunxi_mc_smp_match(const char *); -int sunxi_mc_smp_enable(u_int); +int sun8i_a83t_smp_enable(u_int); +int sun9i_a80_smp_enable(u_int); #endif /* !_SUNXI_MC_SMP_H */ Index: src/sys/arch/arm/sunxi/sunxi_platform.c diff -u src/sys/arch/arm/sunxi/sunxi_platform.c:1.33 src/sys/arch/arm/sunxi/sunxi_platform.c:1.34 --- src/sys/arch/arm/sunxi/sunxi_platform.c:1.33 Thu Jan 3 12:52:40 2019 +++ src/sys/arch/arm/sunxi/sunxi_platform.c Thu Jan 3 14:44:21 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_platform.c,v 1.33 2019/01/03 12:52:40 jmcneill Exp $ */ +/* $NetBSD: sunxi_platform.c,v 1.34 2019/01/03 14:44:21 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -31,7 +31,7 @@ #include "opt_console.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sunxi_platform.c,v 1.33 2019/01/03 12:52:40 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sunxi_platform.c,v 1.34 2019/01/03 14:44:21 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -127,9 +127,9 @@ sunxi_platform_devmap(void) return devmap; } -#define SUN8I_A83T_CPU_VBASE (SUNXI_CORE_VBASE + SUNXI_CORE_SIZE) -#define SUN8I_A83T_CPU_PBASE 0x01700000 -#define SUN8I_A83T_CPU_SIZE 0x00100000 +#define SUNXI_MC_CPU_VBASE (SUNXI_CORE_VBASE + SUNXI_CORE_SIZE) +#define SUNXI_MC_CPU_PBASE 0x01700000 +#define SUNXI_MC_CPU_SIZE 0x00100000 static const struct pmap_devmap * sun8i_a83t_platform_devmap(void) @@ -138,15 +138,39 @@ sun8i_a83t_platform_devmap(void) DEVMAP_ENTRY(SUNXI_CORE_VBASE, SUNXI_CORE_PBASE, SUNXI_CORE_SIZE), - DEVMAP_ENTRY(SUN8I_A83T_CPU_VBASE, - SUN8I_A83T_CPU_PBASE, - SUN8I_A83T_CPU_SIZE), + DEVMAP_ENTRY(SUNXI_MC_CPU_VBASE, + SUNXI_MC_CPU_PBASE, + SUNXI_MC_CPU_SIZE), DEVMAP_ENTRY_END }; return devmap; } +#define SUN9I_A80_PRCM_VBASE (SUNXI_MC_CPU_VBASE + SUNXI_MC_CPU_PBASE) +#define SUN9I_A80_PRCM_PBASE 0x08000000 +#define SUN9I_A80_PRCM_SIZE 0x00100000 + +static const struct pmap_devmap * +sun9i_a80_platform_devmap(void) +{ + static const struct pmap_devmap devmap[] = { + DEVMAP_ENTRY(SUNXI_CORE_VBASE, + SUNXI_CORE_PBASE, + SUNXI_CORE_SIZE), + DEVMAP_ENTRY(SUNXI_MC_CPU_VBASE, + SUNXI_MC_CPU_PBASE, + SUNXI_MC_CPU_SIZE), + DEVMAP_ENTRY(SUN9I_A80_PRCM_VBASE, + SUN9I_A80_PRCM_PBASE, + SUN9I_A80_PRCM_SIZE), + DEVMAP_ENTRY_END + }; + + return devmap; +} + + static void sunxi_platform_init_attach_args(struct fdt_attach_args *faa) { @@ -237,15 +261,26 @@ sunxi_platform_bootstrap(void) #if defined(SOC_SUNXI_MC) static int -cpu_enable_sunxi_mc(int phandle) +cpu_enable_sun8i_a83t(int phandle) { uint64_t mpidr; fdtbus_get_reg64(phandle, 0, &mpidr, NULL); - return sunxi_mc_smp_enable(mpidr); + return sun8i_a83t_smp_enable(mpidr); } -ARM_CPU_METHOD(sun8i_a83t, "allwinner,sun8i-a83t-smp", cpu_enable_sunxi_mc); +ARM_CPU_METHOD(sun8i_a83t, "allwinner,sun8i-a83t-smp", cpu_enable_sun8i_a83t); + +static int +cpu_enable_sun9i_a80(int phandle) +{ + uint64_t mpidr; + + fdtbus_get_reg64(phandle, 0, &mpidr, NULL); + + return sun9i_a80_smp_enable(mpidr); +} +ARM_CPU_METHOD(sun9i_a80, "allwinner,sun9i-a80-smp", cpu_enable_sun9i_a80); #endif static void @@ -411,7 +446,7 @@ static const struct arm_platform sun8i_a ARM_PLATFORM(sun8i_a83t, "allwinner,sun8i-a83t", &sun8i_a83t_platform); static const struct arm_platform sun9i_platform = { - .ap_devmap = sunxi_platform_devmap, + .ap_devmap = sun9i_a80_platform_devmap, .ap_bootstrap = sunxi_platform_bootstrap, .ap_init_attach_args = sunxi_platform_init_attach_args, .ap_device_register = sunxi_platform_device_register,