1265739Sganbold/*- 2265739Sganbold * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold@freebsd.org> 3265739Sganbold * All rights reserved. 4265739Sganbold * 5265739Sganbold * Redistribution and use in source and binary forms, with or without 6265739Sganbold * modification, are permitted provided that the following conditions 7265739Sganbold * are met: 8265739Sganbold * 1. Redistributions of source code must retain the above copyright 9265739Sganbold * notice, this list of conditions and the following disclaimer. 10265739Sganbold * 2. Redistributions in binary form must reproduce the above copyright 11265739Sganbold * notice, this list of conditions and the following disclaimer in the 12265739Sganbold * documentation and/or other materials provided with the distribution. 13265739Sganbold * 14265739Sganbold * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15265739Sganbold * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16265739Sganbold * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17265739Sganbold * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18265739Sganbold * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19265739Sganbold * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20265739Sganbold * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21265739Sganbold * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22265739Sganbold * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23265739Sganbold * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24265739Sganbold */ 25265739Sganbold 26265739Sganbold#include <sys/cdefs.h> 27265739Sganbold__FBSDID("$FreeBSD: releng/10.2/sys/arm/rockchip/rk30xx_mp.c 266397 2014-05-18 13:05:07Z ian $"); 28265739Sganbold#include <sys/param.h> 29265739Sganbold#include <sys/systm.h> 30265739Sganbold#include <sys/bus.h> 31265739Sganbold#include <sys/kernel.h> 32265739Sganbold#include <sys/lock.h> 33265739Sganbold#include <sys/mutex.h> 34265739Sganbold#include <sys/smp.h> 35265739Sganbold 36265739Sganbold#include <machine/smp.h> 37265739Sganbold#include <machine/fdt.h> 38265739Sganbold#include <machine/intr.h> 39265739Sganbold 40265739Sganbold#define SCU_PHYSBASE 0x1013c000 41265739Sganbold#define SCU_SIZE 0x100 42265739Sganbold 43265739Sganbold#define SCU_CONTROL_REG 0x00 44265739Sganbold#define SCU_CONTROL_ENABLE (1 << 0) 45265739Sganbold#define SCU_STANDBY_EN (1 << 5) 46265739Sganbold#define SCU_CONFIG_REG 0x04 47265739Sganbold#define SCU_CONFIG_REG_NCPU_MASK 0x03 48265739Sganbold#define SCU_CPUPOWER_REG 0x08 49265739Sganbold#define SCU_INV_TAGS_REG 0x0c 50265739Sganbold 51265739Sganbold#define SCU_FILTER_START_REG 0x10 52265739Sganbold#define SCU_FILTER_END_REG 0x14 53265739Sganbold#define SCU_SECURE_ACCESS_REG 0x18 54265739Sganbold#define SCU_NONSECURE_ACCESS_REG 0x1c 55265739Sganbold 56265739Sganbold#define IMEM_PHYSBASE 0x10080000 57265739Sganbold#define IMEM_SIZE 0x20 58265739Sganbold 59265739Sganbold#define PMU_PHYSBASE 0x20004000 60265739Sganbold#define PMU_SIZE 0x100 61265739Sganbold#define PMU_PWRDN_CON 0x08 62265739Sganbold#define PMU_PWRDN_SCU (1 << 4) 63265739Sganbold 64265739Sganboldextern char *mpentry_addr; 65265739Sganboldstatic void rk30xx_boot2(void); 66265739Sganbold 67265739Sganboldstatic void 68265739Sganboldrk30xx_boot2(void) 69265739Sganbold{ 70265739Sganbold 71265739Sganbold __asm __volatile( 72265739Sganbold "ldr pc, 1f\n" 73265739Sganbold ".globl mpentry_addr\n" 74265739Sganbold "mpentry_addr:\n" 75265739Sganbold "1: .space 4\n"); 76265739Sganbold} 77265739Sganbold 78265739Sganboldvoid 79265739Sganboldplatform_mp_init_secondary(void) 80265739Sganbold{ 81265739Sganbold 82265739Sganbold gic_init_secondary(); 83265739Sganbold} 84265739Sganbold 85265739Sganboldvoid 86265739Sganboldplatform_mp_setmaxid(void) 87265739Sganbold{ 88265739Sganbold bus_space_handle_t scu; 89265739Sganbold int ncpu; 90265739Sganbold uint32_t val; 91265739Sganbold 92265739Sganbold if (mp_ncpus != 0) 93265739Sganbold return; 94265739Sganbold 95265739Sganbold if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0) 96265739Sganbold panic("Could not map the SCU"); 97265739Sganbold 98265739Sganbold val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONFIG_REG); 99265739Sganbold ncpu = (val & SCU_CONFIG_REG_NCPU_MASK) + 1; 100265739Sganbold bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE); 101265739Sganbold 102265739Sganbold mp_ncpus = ncpu; 103265739Sganbold mp_maxid = ncpu - 1; 104265739Sganbold} 105265739Sganbold 106265739Sganboldint 107265739Sganboldplatform_mp_probe(void) 108265739Sganbold{ 109265739Sganbold 110265739Sganbold if (mp_ncpus == 0) 111265739Sganbold platform_mp_setmaxid(); 112265739Sganbold 113265739Sganbold return (mp_ncpus > 1); 114265739Sganbold} 115265739Sganbold 116265739Sganboldvoid 117265739Sganboldplatform_mp_start_ap(void) 118265739Sganbold{ 119265739Sganbold bus_space_handle_t scu; 120265739Sganbold bus_space_handle_t imem; 121265739Sganbold bus_space_handle_t pmu; 122265739Sganbold uint32_t val; 123265739Sganbold int i; 124265739Sganbold 125265739Sganbold if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0) 126265739Sganbold panic("Could not map the SCU"); 127265739Sganbold if (bus_space_map(fdtbus_bs_tag, IMEM_PHYSBASE, 128265739Sganbold IMEM_SIZE, 0, &imem) != 0) 129265739Sganbold panic("Could not map the IMEM"); 130265739Sganbold if (bus_space_map(fdtbus_bs_tag, PMU_PHYSBASE, PMU_SIZE, 0, &pmu) != 0) 131265739Sganbold panic("Could not map the PMU"); 132265739Sganbold 133265739Sganbold /* 134265739Sganbold * Invalidate SCU cache tags. The 0x0000ffff constant invalidates all 135265739Sganbold * ways on all cores 0-3. Per the ARM docs, it's harmless to write to 136265739Sganbold * the bits for cores that are not present. 137265739Sganbold */ 138265739Sganbold bus_space_write_4(fdtbus_bs_tag, scu, SCU_INV_TAGS_REG, 0x0000ffff); 139265739Sganbold 140265739Sganbold /* Make sure all cores except the first are off */ 141265739Sganbold val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); 142265739Sganbold for (i = 1; i < mp_ncpus; i++) 143265739Sganbold val |= 1 << i; 144265739Sganbold bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val); 145265739Sganbold 146265739Sganbold /* Enable SCU power domain */ 147265739Sganbold val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); 148265739Sganbold val &= ~PMU_PWRDN_SCU; 149265739Sganbold bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val); 150265739Sganbold 151265739Sganbold /* Enable SCU */ 152265739Sganbold val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG); 153265739Sganbold bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG, 154265739Sganbold val | SCU_CONTROL_ENABLE); 155265739Sganbold 156265739Sganbold /* 157265739Sganbold * Cores will execute the code which resides at the start of 158265739Sganbold * the on-chip bootram/sram after power-on. This sram region 159265739Sganbold * should be reserved and the trampoline code that directs 160265739Sganbold * the core to the real startup code in ram should be copied 161265739Sganbold * into this sram region. 162265739Sganbold * 163265739Sganbold * First set boot function for the sram code. 164265739Sganbold */ 165265739Sganbold mpentry_addr = (char *)pmap_kextract((vm_offset_t)mpentry); 166265739Sganbold 167265739Sganbold /* Copy trampoline to sram, that runs during startup of the core */ 168265739Sganbold bus_space_write_region_4(fdtbus_bs_tag, imem, 0, 169265739Sganbold (uint32_t *)&rk30xx_boot2, 8); 170265739Sganbold 171265739Sganbold cpu_idcache_wbinv_all(); 172265739Sganbold cpu_l2cache_wbinv_all(); 173265739Sganbold 174265739Sganbold /* Start all cores */ 175265739Sganbold val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); 176265739Sganbold for (i = 1; i < mp_ncpus; i++) 177265739Sganbold val &= ~(1 << i); 178265739Sganbold bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val); 179265739Sganbold 180265739Sganbold armv7_sev(); 181265739Sganbold 182265739Sganbold bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE); 183265739Sganbold bus_space_unmap(fdtbus_bs_tag, imem, IMEM_SIZE); 184265739Sganbold bus_space_unmap(fdtbus_bs_tag, pmu, PMU_SIZE); 185265739Sganbold} 186265739Sganbold 187265739Sganboldvoid 188265739Sganboldplatform_ipi_send(cpuset_t cpus, u_int ipi) 189265739Sganbold{ 190265739Sganbold 191265739Sganbold pic_ipi_send(cpus, ipi); 192265739Sganbold} 193