Module Name: src Committed By: jmcneill Date: Thu Jan 3 11:01:59 UTC 2019
Modified Files: src/sys/arch/arm/sunxi: files.sunxi sunxi_platform.c Added Files: src/sys/arch/arm/sunxi: sunxi_mc_mpstart.S sunxi_mc_smp.c sunxi_mc_smp.h Log Message: Add Allwinner A83T SMP support. To generate a diff of this commit: cvs rdiff -u -r1.57 -r1.58 src/sys/arch/arm/sunxi/files.sunxi cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/sunxi/sunxi_mc_mpstart.S \ src/sys/arch/arm/sunxi/sunxi_mc_smp.c \ src/sys/arch/arm/sunxi/sunxi_mc_smp.h cvs rdiff -u -r1.31 -r1.32 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.57 src/sys/arch/arm/sunxi/files.sunxi:1.58 --- src/sys/arch/arm/sunxi/files.sunxi:1.57 Fri Jun 1 22:11:54 2018 +++ src/sys/arch/arm/sunxi/files.sunxi Thu Jan 3 11:01:59 2019 @@ -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 @@ file arch/arm/sunxi/sunxi_can.c sunxi_c 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_SUN6I_A31: SOC_S 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 Index: src/sys/arch/arm/sunxi/sunxi_platform.c diff -u src/sys/arch/arm/sunxi/sunxi_platform.c:1.31 src/sys/arch/arm/sunxi/sunxi_platform.c:1.32 --- src/sys/arch/arm/sunxi/sunxi_platform.c:1.31 Tue Oct 30 16:41:52 2018 +++ src/sys/arch/arm/sunxi/sunxi_platform.c Thu Jan 3 11:01:59 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_platform.c,v 1.31 2018/10/30 16:41:52 skrll Exp $ */ +/* $NetBSD: sunxi_platform.c,v 1.32 2019/01/03 11:01:59 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.31 2018/10/30 16:41:52 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sunxi_platform.c,v 1.32 2019/01/03 11:01:59 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -58,6 +58,10 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_platfo #include <arm/sunxi/sunxi_platform.h> +#if defined(SOC_SUNXI_MC) +#include <arm/sunxi/sunxi_mc_smp.h> +#endif + #include <libfdt.h> #define SUNXI_REF_FREQ 24000000 @@ -123,6 +127,26 @@ 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 + +static const struct pmap_devmap * +sun8i_a83t_platform_devmap(void) +{ + static const struct pmap_devmap devmap[] = { + 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_END + }; + + return devmap; +} + static void sunxi_platform_init_attach_args(struct fdt_attach_args *faa) { @@ -211,6 +235,55 @@ sunxi_platform_bootstrap(void) } } +static void +sunxi_mc_platform_mpstart(void) +{ + uint32_t started = 0; + +#if defined(MULTIPROCESSOR) && defined(SOC_SUNXI_MC) + const char *method; + uint64_t mpidr, bp_mpidr; + u_int cpuindex; + int child; + + const int cpus = OF_finddevice("/cpus"); + if (cpus == -1) + return; + + /* MPIDR affinity levels of boot processor. */ + bp_mpidr = cpu_mpidr_aff_read(); + + cpuindex = 1; + for (child = OF_child(cpus); child; child = OF_peer(child)) { + if (fdtbus_get_reg64(child, 0, &mpidr, NULL) != 0) + continue; + if (mpidr == bp_mpidr) + continue; + + method = fdtbus_get_string(child, "enable-method"); + if (method == NULL) + method = fdtbus_get_string(cpus, "enable-method"); + if (method == NULL) + continue; + + if (sunxi_mc_smp_match(method) != 0) { + if (sunxi_mc_smp_enable(mpidr) != 0) + continue; + + started |= __BIT(cpuindex); + cpuindex++; + for (u_int i = 0x100000; i > 0; i--) { + membar_consumer(); + if (arm_cpu_hatched & __BIT(cpuindex)) + break; + } + } + } +#endif + + if (started == 0) + arm_fdt_cpu_mpstart(); +} static void sun4i_platform_reset(void) @@ -360,7 +433,19 @@ static const struct arm_platform sun8i_p ARM_PLATFORM(sun8i_h2plus, "allwinner,sun8i-h2-plus", &sun8i_platform); ARM_PLATFORM(sun8i_h3, "allwinner,sun8i-h3", &sun8i_platform); -ARM_PLATFORM(sun8i_a83t, "allwinner,sun8i-a83t", &sun8i_platform); + +static const struct arm_platform sun8i_a83t_platform = { + .ap_devmap = sun8i_a83t_platform_devmap, + .ap_bootstrap = sunxi_platform_bootstrap, + .ap_init_attach_args = sunxi_platform_init_attach_args, + .ap_device_register = sunxi_platform_device_register, + .ap_reset = sun6i_platform_reset, + .ap_delay = gtmr_delay, + .ap_uart_freq = sunxi_platform_uart_freq, + .ap_mpstart = sunxi_mc_platform_mpstart, +}; + +ARM_PLATFORM(sun8i_a83t, "allwinner,sun8i-a83t", &sun8i_a83t_platform); static const struct arm_platform sun9i_platform = { .ap_devmap = sunxi_platform_devmap, Added files: Index: src/sys/arch/arm/sunxi/sunxi_mc_mpstart.S diff -u /dev/null src/sys/arch/arm/sunxi/sunxi_mc_mpstart.S:1.1 --- /dev/null Thu Jan 3 11:01:59 2019 +++ src/sys/arch/arm/sunxi/sunxi_mc_mpstart.S Thu Jan 3 11:01:59 2019 @@ -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 <jmcne...@invisible.ca> + * 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 Index: src/sys/arch/arm/sunxi/sunxi_mc_smp.c diff -u /dev/null src/sys/arch/arm/sunxi/sunxi_mc_smp.c:1.1 --- /dev/null Thu Jan 3 11:01:59 2019 +++ src/sys/arch/arm/sunxi/sunxi_mc_smp.c Thu Jan 3 11:01:59 2019 @@ -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 <jmcne...@invisible.ca> + * 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); + + /* De-assert ACINACTM */ + val = bus_space_read_4(bst, cpuxcfg, CPUXCFG_CL_CTRL1(cluster)); + val &= ~CPUXCFG_CL_CTRL1_ACINACTM; + bus_space_write_4(bst, cpuxcfg, CPUXCFG_CL_CTRL1(cluster), val); + + return 0; +} + +int +sunxi_mc_smp_enable(u_int mpidr) +{ + bus_space_tag_t bst = &arm_generic_bs_tag; + bus_space_handle_t prcm, cpucfg, cpuxcfg; + int error; + + 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 || + 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); + + bus_space_unmap(bst, cpuxcfg, CPUXCFG_SIZE); + bus_space_unmap(bst, cpucfg, CPUCFG_SIZE); + bus_space_unmap(bst, prcm, PRCM_SIZE); + + return error; +} + +int +sunxi_mc_smp_match(const char *enable_method) +{ + return strcmp(enable_method, A83T_SMP_ENABLE_METHOD) == 0; +} Index: src/sys/arch/arm/sunxi/sunxi_mc_smp.h diff -u /dev/null src/sys/arch/arm/sunxi/sunxi_mc_smp.h:1.1 --- /dev/null Thu Jan 3 11:01:59 2019 +++ src/sys/arch/arm/sunxi/sunxi_mc_smp.h Thu Jan 3 11:01:59 2019 @@ -0,0 +1,35 @@ +/* $NetBSD: sunxi_mc_smp.h,v 1.1 2019/01/03 11:01:59 jmcneill Exp $ */ + +/*- + * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca> + * 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. + */ + +#ifndef _SUNXI_MC_SMP_H +#define _SUNXI_MC_SMP_H + +int sunxi_mc_smp_match(const char *); +int sunxi_mc_smp_enable(u_int); + +#endif /* !_SUNXI_MC_SMP_H */