1263698Sganbold/*- 2263698Sganbold * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold@freebsd.org> 3263698Sganbold * All rights reserved. 4263698Sganbold * 5263698Sganbold * Redistribution and use in source and binary forms, with or without 6263698Sganbold * modification, are permitted provided that the following conditions 7263698Sganbold * are met: 8263698Sganbold * 1. Redistributions of source code must retain the above copyright 9263698Sganbold * notice, this list of conditions and the following disclaimer. 10263698Sganbold * 2. Redistributions in binary form must reproduce the above copyright 11263698Sganbold * notice, this list of conditions and the following disclaimer in the 12263698Sganbold * documentation and/or other materials provided with the distribution. 13263698Sganbold * 14263698Sganbold * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15263698Sganbold * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16263698Sganbold * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17263698Sganbold * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18263698Sganbold * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19263698Sganbold * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20263698Sganbold * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21263698Sganbold * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22263698Sganbold * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23263698Sganbold * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24263698Sganbold */ 25263698Sganbold 26263698Sganbold#include <sys/cdefs.h> 27263698Sganbold__FBSDID("$FreeBSD: releng/10.2/sys/arm/allwinner/a20/a20_mp.c 266337 2014-05-17 18:53:36Z ian $"); 28263698Sganbold#include <sys/param.h> 29263698Sganbold#include <sys/systm.h> 30263698Sganbold#include <sys/bus.h> 31263698Sganbold#include <sys/kernel.h> 32263698Sganbold#include <sys/lock.h> 33263698Sganbold#include <sys/mutex.h> 34263698Sganbold#include <sys/smp.h> 35263698Sganbold 36263698Sganbold#include <machine/smp.h> 37263698Sganbold#include <machine/fdt.h> 38263698Sganbold#include <machine/intr.h> 39263698Sganbold 40263698Sganbold#define CPUCFG_BASE 0x01c25c00 41263698Sganbold#define CPUCFG_SIZE 0x400 42263698Sganbold 43263698Sganbold#define CPU0_RST_CTL 0x40 44263698Sganbold#define CPU0_CTL 0x44 45263698Sganbold#define CPU0_STATUS 0x48 46263698Sganbold#define CPU1_RST_CTL 0x80 47263698Sganbold#define CPU1_CTL 0x84 48263698Sganbold#define CPU1_STATUS 0x88 49263698Sganbold#define CPUCFG_GENCTL 0x184 50263698Sganbold#define CPUCFG_P_REG0 0x1a4 51263698Sganbold#define CPU1_PWR_CLAMP 0x1b0 52263698Sganbold#define CPU1_PWROFF_REG 0x1b4 53263698Sganbold#define CPUCFG_DBGCTL0 0x1e0 54263698Sganbold#define CPUCFG_DBGCTL1 0x1e4 55263698Sganbold 56263698Sganboldvoid 57263698Sganboldplatform_mp_init_secondary(void) 58263698Sganbold{ 59263698Sganbold 60263698Sganbold gic_init_secondary(); 61263698Sganbold} 62263698Sganbold 63263698Sganboldvoid 64263698Sganboldplatform_mp_setmaxid(void) 65263698Sganbold{ 66263698Sganbold int ncpu; 67263698Sganbold 68263698Sganbold if (mp_ncpus != 0) 69263698Sganbold return; 70263698Sganbold 71263698Sganbold /* Read current CP15 Cache Size ID Register */ 72263698Sganbold __asm __volatile("mrc p15, 1, %0, c9, c0, 2" : "=r" (ncpu)); 73263698Sganbold ncpu = ((ncpu >> 24) & 0x3) + 1; 74263698Sganbold 75263698Sganbold mp_ncpus = ncpu; 76263698Sganbold mp_maxid = ncpu - 1; 77263698Sganbold} 78263698Sganbold 79263698Sganboldint 80263698Sganboldplatform_mp_probe(void) 81263698Sganbold{ 82263698Sganbold 83263698Sganbold if (mp_ncpus == 0) 84263698Sganbold platform_mp_setmaxid(); 85263698Sganbold 86263698Sganbold return (mp_ncpus > 1); 87263698Sganbold} 88263698Sganbold 89263698Sganboldvoid 90263698Sganboldplatform_mp_start_ap(void) 91263698Sganbold{ 92263698Sganbold bus_space_handle_t cpucfg; 93263698Sganbold 94263698Sganbold uint32_t val; 95263698Sganbold 96263698Sganbold if (bus_space_map(fdtbus_bs_tag, CPUCFG_BASE, CPUCFG_SIZE, 0, 97263698Sganbold &cpucfg) != 0) 98263698Sganbold panic("Couldn't map the CPUCFG\n"); 99263698Sganbold 100263698Sganbold cpu_idcache_wbinv_all(); 101263698Sganbold cpu_l2cache_wbinv_all(); 102263698Sganbold 103263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_P_REG0, 104263698Sganbold pmap_kextract((vm_offset_t)mpentry)); 105263698Sganbold 106263698Sganbold /* 107263698Sganbold * Assert nCOREPORESET low and set L1RSTDISABLE low. 108263698Sganbold * Ensure DBGPWRDUP is set to LOW to prevent any external 109263698Sganbold * debug access to the processor. 110263698Sganbold */ 111263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_RST_CTL, 0); 112263698Sganbold 113263698Sganbold /* Set L1RSTDISABLE low */ 114263698Sganbold val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_GENCTL); 115263698Sganbold val &= ~(1 << 1); 116263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_GENCTL, val); 117263698Sganbold 118263698Sganbold /* Set DBGPWRDUP low */ 119263698Sganbold val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1); 120263698Sganbold val &= ~(1 << 1); 121263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1, val); 122263698Sganbold 123263698Sganbold /* Release power clamp */ 124263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0xff); 125263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x7f); 126263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x3f); 127263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x1f); 128263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x0f); 129263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x07); 130263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x03); 131263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x01); 132263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x00); 133263698Sganbold DELAY(10000); 134263698Sganbold 135263698Sganbold /* Clear power-off gating */ 136263698Sganbold val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPU1_PWROFF_REG); 137263698Sganbold val &= ~(1 << 0); 138263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWROFF_REG, val); 139263698Sganbold DELAY(1000); 140263698Sganbold 141263698Sganbold /* De-assert cpu core reset */ 142263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_RST_CTL, 3); 143263698Sganbold 144263698Sganbold /* Assert DBGPWRDUP signal */ 145263698Sganbold val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1); 146263698Sganbold val |= (1 << 1); 147263698Sganbold bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1, val); 148263698Sganbold 149263698Sganbold armv7_sev(); 150263698Sganbold bus_space_unmap(fdtbus_bs_tag, cpucfg, CPUCFG_SIZE); 151263698Sganbold} 152263698Sganbold 153263698Sganboldvoid 154263698Sganboldplatform_ipi_send(cpuset_t cpus, u_int ipi) 155263698Sganbold{ 156263698Sganbold 157263698Sganbold pic_ipi_send(cpus, ipi); 158263698Sganbold} 159