aw_mp.c revision 292426
1/*- 2 * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD: head/sys/arm/allwinner/a20/a20_mp.c 292426 2015-12-18 05:43:59Z adrian $"); 28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/bus.h> 32#include <sys/kernel.h> 33#include <sys/lock.h> 34#include <sys/mutex.h> 35#include <sys/smp.h> 36 37#include <vm/vm.h> 38#include <vm/pmap.h> 39 40#include <machine/smp.h> 41#include <machine/fdt.h> 42#include <machine/intr.h> 43 44#define CPUCFG_BASE 0x01c25c00 45#define CPUCFG_SIZE 0x400 46 47#define CPU0_RST_CTL 0x40 48#define CPU0_CTL 0x44 49#define CPU0_STATUS 0x48 50#define CPU1_RST_CTL 0x80 51#define CPU1_CTL 0x84 52#define CPU1_STATUS 0x88 53#define CPUCFG_GENCTL 0x184 54#define CPUCFG_P_REG0 0x1a4 55#define CPU1_PWR_CLAMP 0x1b0 56#define CPU1_PWROFF_REG 0x1b4 57#define CPUCFG_DBGCTL0 0x1e0 58#define CPUCFG_DBGCTL1 0x1e4 59 60void 61platform_mp_init_secondary(void) 62{ 63 64 intr_pic_init_secondary(); 65} 66 67void 68platform_mp_setmaxid(void) 69{ 70 int ncpu; 71 72 if (mp_ncpus != 0) 73 return; 74 75 /* Read the number of cores from the CP15 L2 Control Register. */ 76 __asm __volatile("mrc p15, 1, %0, c9, c0, 2" : "=r" (ncpu)); 77 ncpu = ((ncpu >> 24) & 0x3) + 1; 78 79 mp_ncpus = ncpu; 80 mp_maxid = ncpu - 1; 81} 82 83int 84platform_mp_probe(void) 85{ 86 87 if (mp_ncpus == 0) 88 platform_mp_setmaxid(); 89 90 return (mp_ncpus > 1); 91} 92 93void 94platform_mp_start_ap(void) 95{ 96 bus_space_handle_t cpucfg; 97 98 uint32_t val; 99 100 if (bus_space_map(fdtbus_bs_tag, CPUCFG_BASE, CPUCFG_SIZE, 0, 101 &cpucfg) != 0) 102 panic("Couldn't map the CPUCFG\n"); 103 104 cpu_idcache_wbinv_all(); 105 cpu_l2cache_wbinv_all(); 106 107 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_P_REG0, 108 pmap_kextract((vm_offset_t)mpentry)); 109 110 /* 111 * Assert nCOREPORESET low and set L1RSTDISABLE low. 112 * Ensure DBGPWRDUP is set to LOW to prevent any external 113 * debug access to the processor. 114 */ 115 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_RST_CTL, 0); 116 117 /* Set L1RSTDISABLE low */ 118 val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_GENCTL); 119 val &= ~(1 << 1); 120 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_GENCTL, val); 121 122 /* Set DBGPWRDUP low */ 123 val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1); 124 val &= ~(1 << 1); 125 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1, val); 126 127 /* Release power clamp */ 128 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0xff); 129 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x7f); 130 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x3f); 131 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x1f); 132 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x0f); 133 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x07); 134 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x03); 135 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x01); 136 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x00); 137 DELAY(10000); 138 139 /* Clear power-off gating */ 140 val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPU1_PWROFF_REG); 141 val &= ~(1 << 0); 142 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWROFF_REG, val); 143 DELAY(1000); 144 145 /* De-assert cpu core reset */ 146 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_RST_CTL, 3); 147 148 /* Assert DBGPWRDUP signal */ 149 val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1); 150 val |= (1 << 1); 151 bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1, val); 152 153 armv7_sev(); 154 bus_space_unmap(fdtbus_bs_tag, cpucfg, CPUCFG_SIZE); 155} 156 157void 158platform_ipi_send(cpuset_t cpus, u_int ipi) 159{ 160 161 pic_ipi_send(cpus, ipi); 162} 163