aw_mp.c revision 263698
153541Sshin/*- 253541Sshin * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold@freebsd.org> 353541Sshin * All rights reserved. 453541Sshin * 553541Sshin * Redistribution and use in source and binary forms, with or without 653541Sshin * modification, are permitted provided that the following conditions 753541Sshin * are met: 853541Sshin * 1. Redistributions of source code must retain the above copyright 953541Sshin * notice, this list of conditions and the following disclaimer. 1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright 1153541Sshin * notice, this list of conditions and the following disclaimer in the 1253541Sshin * documentation and/or other materials provided with the distribution. 1353541Sshin * 1453541Sshin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1553541Sshin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1653541Sshin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1753541Sshin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1853541Sshin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1953541Sshin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2053541Sshin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2153541Sshin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2253541Sshin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2353541Sshin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2453541Sshin */ 2553541Sshin 2653541Sshin#include <sys/cdefs.h> 2753541Sshin__FBSDID("$FreeBSD: head/sys/arm/allwinner/a20/a20_mp.c 263698 2014-03-25 01:34:39Z ganbold $"); 2853541Sshin#include <sys/param.h> 2953541Sshin#include <sys/systm.h> 3053541Sshin#include <sys/bus.h> 3153541Sshin#include <sys/kernel.h> 3253541Sshin#include <sys/lock.h> 3353541Sshin#include <sys/mutex.h> 3453541Sshin#include <sys/smp.h> 3553541Sshin 3653541Sshin#include <machine/smp.h> 3753541Sshin#include <machine/fdt.h> 3853541Sshin#include <machine/intr.h> 3953541Sshin 4053541Sshin#define CPUCFG_BASE 0x01c25c00 4153541Sshin#define CPUCFG_SIZE 0x400 4253541Sshin 4353541Sshin#define CPU0_RST_CTL 0x40 4453541Sshin#define CPU0_CTL 0x44 4553541Sshin#define CPU0_STATUS 0x48 4653541Sshin#define CPU1_RST_CTL 0x80 4753541Sshin#define CPU1_CTL 0x84 4853541Sshin#define CPU1_STATUS 0x88 4953541Sshin#define CPUCFG_GENCTL 0x184 5053541Sshin#define CPUCFG_P_REG0 0x1a4 5153541Sshin#define CPU1_PWR_CLAMP 0x1b0 5253541Sshin#define CPU1_PWROFF_REG 0x1b4 5353541Sshin#define CPUCFG_DBGCTL0 0x1e0 5453541Sshin#define CPUCFG_DBGCTL1 0x1e4 5553541Sshin 5653541Sshinvoid 5753541Sshinplatform_mp_init_secondary(void) 5853541Sshin{ 5953541Sshin 6053541Sshin gic_init_secondary(); 6153541Sshin} 6253541Sshin 6353541Sshinvoid 6453541Sshinplatform_mp_setmaxid(void) 6553541Sshin{ 6653541Sshin int ncpu; 6755009Sshin 6855009Sshin if (mp_ncpus != 0) 6953541Sshin return; 7053541Sshin 7153541Sshin /* Read current CP15 Cache Size ID Register */ 7253541Sshin __asm __volatile("mrc p15, 1, %0, c9, c0, 2" : "=r" (ncpu)); 7353541Sshin ncpu = ((ncpu >> 24) & 0x3) + 1; 7453541Sshin 7553541Sshin mp_ncpus = ncpu; 7653541Sshin mp_maxid = ncpu - 1; 7753541Sshin} 7853541Sshin 7953541Sshinint 8053541Sshinplatform_mp_probe(void) 8153541Sshin{ 8253541Sshin 8353541Sshin if (mp_ncpus == 0) 8453541Sshin platform_mp_setmaxid(); 8553541Sshin 8653541Sshin return (mp_ncpus > 1); 8753541Sshin} 8862587Sitojun 8953541Sshinvoid 9056723Sshinplatform_mp_start_ap(void) 9162587Sitojun{ 9253541Sshin bus_space_handle_t cpucfg; 9353541Sshin 9453541Sshin uint32_t val; 9562587Sitojun 9662587Sitojun if (bus_space_map(fdtbus_bs_tag, CPUCFG_BASE, CPUCFG_SIZE, 0, 9762587Sitojun &cpucfg) != 0) 9862587Sitojun panic("Couldn't map the CPUCFG\n"); 9953541Sshin 10053541Sshin cpu_idcache_wbinv_all(); 10153541Sshin cpu_l2cache_wbinv_all(); 10253541Sshin 10353541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_P_REG0, 10453541Sshin pmap_kextract((vm_offset_t)mpentry)); 10553541Sshin 10653541Sshin /* 10754263Sshin * Assert nCOREPORESET low and set L1RSTDISABLE low. 10853541Sshin * Ensure DBGPWRDUP is set to LOW to prevent any external 10953541Sshin * debug access to the processor. 11053541Sshin */ 11153541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_RST_CTL, 0); 11253541Sshin 11353541Sshin /* Set L1RSTDISABLE low */ 11453541Sshin val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_GENCTL); 11553541Sshin val &= ~(1 << 1); 11653541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_GENCTL, val); 11753541Sshin 11853541Sshin /* Set DBGPWRDUP low */ 11953541Sshin val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1); 12053541Sshin val &= ~(1 << 1); 12153541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1, val); 12253541Sshin 12353541Sshin /* Release power clamp */ 12453541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0xff); 12553541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x7f); 12653541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x3f); 12753541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x1f); 12853541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x0f); 12953541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x07); 13053541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x03); 13153541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x01); 13253541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x00); 13353541Sshin DELAY(10000); 13453541Sshin 13553541Sshin /* Clear power-off gating */ 13653541Sshin val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPU1_PWROFF_REG); 13753541Sshin val &= ~(1 << 0); 13853541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWROFF_REG, val); 13953541Sshin DELAY(1000); 14053541Sshin 14153541Sshin /* De-assert cpu core reset */ 14253541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_RST_CTL, 3); 14353541Sshin 14453541Sshin /* Assert DBGPWRDUP signal */ 14553541Sshin val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1); 14653541Sshin val |= (1 << 1); 14753541Sshin bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1, val); 14853541Sshin 14953541Sshin armv7_sev(); 15055009Sshin bus_space_unmap(fdtbus_bs_tag, cpucfg, CPUCFG_SIZE); 15153541Sshin} 15253541Sshin 15353541Sshinvoid 15453541Sshinplatform_ipi_send(cpuset_t cpus, u_int ipi) 15553541Sshin{ 15653541Sshin 15753541Sshin pic_ipi_send(cpus, ipi); 15853541Sshin} 15953541Sshin