armadaxp_mp.c revision 266203
11539Srgrimes/*- 21539Srgrimes * Copyright (c) 2011 Semihalf. 31539Srgrimes * All rights reserved. 41539Srgrimes * 51539Srgrimes * Redistribution and use in source and binary forms, with or without 61539Srgrimes * modification, are permitted provided that the following conditions 71539Srgrimes * are met: 81539Srgrimes * 1. Redistributions of source code must retain the above copyright 91539Srgrimes * notice, this list of conditions and the following disclaimer. 101539Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111539Srgrimes * notice, this list of conditions and the following disclaimer in the 121539Srgrimes * documentation and/or other materials provided with the distribution. 131539Srgrimes * 141539Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151539Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161539Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171539Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181539Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191539Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201539Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211539Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221539Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231539Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241539Srgrimes * SUCH DAMAGE. 251539Srgrimes * 261539Srgrimes * $FreeBSD: stable/10/sys/arm/mv/armadaxp/armadaxp_mp.c 266203 2014-05-16 00:14:50Z ian $ 271539Srgrimes */ 281539Srgrimes 291539Srgrimes#include <sys/param.h> 301539Srgrimes#include <sys/systm.h> 311539Srgrimes#include <sys/bus.h> 321539Srgrimes#include <sys/lock.h> 331539Srgrimes#include <sys/mutex.h> 341539Srgrimes#include <sys/smp.h> 351539Srgrimes 361539Srgrimes#include <vm/vm.h> 371539Srgrimes#include <vm/vm_kern.h> 381539Srgrimes#include <vm/vm_extern.h> 391539Srgrimes 401539Srgrimes#include <machine/smp.h> 411539Srgrimes#include <machine/fdt.h> 4254746Sphantom#include <machine/armreg.h> 431539Srgrimes 441539Srgrimes#include <arm/mv/mvwin.h> 457655Sbde 467655Sbde#define MV_AXP_CPU_DIVCLK_BASE (MV_BASE + 0x18700) 471539Srgrimes#define CPU_DIVCLK_CTRL0 0x00 487655Sbde#define CPU_DIVCLK_CTRL2_RATIO_FULL0 0x08 497655Sbde#define CPU_DIVCLK_CTRL2_RATIO_FULL1 0x0c 507655Sbde#define CPU_DIVCLK_MASK(x) (~(0xff << (8 * (x)))) 517655Sbde 521539Srgrimes#define CPU_PMU(x) (MV_BASE + 0x22100 + (0x100 * (x))) 531539Srgrimes#define CPU_PMU_BOOT 0x24 541539Srgrimes 551539Srgrimes#define MP (MV_BASE + 0x20800) 561539Srgrimes#define MP_SW_RESET(x) ((x) * 8) 571539Srgrimes 581539Srgrimes#define CPU_RESUME_CONTROL (0x20988) 591539Srgrimes 601539Srgrimesvoid armadaxp_init_coher_fabric(void); 611539Srgrimesint platform_get_ncpus(void); 621539Srgrimes 631539Srgrimes/* Coherency Fabric registers */ 641539Srgrimesstatic uint32_t 651539Srgrimesread_cpu_clkdiv(uint32_t reg) 661539Srgrimes{ 671539Srgrimes 681539Srgrimes return (bus_space_read_4(fdtbus_bs_tag, MV_AXP_CPU_DIVCLK_BASE, reg)); 697655Sbde} 707655Sbde 717655Sbdestatic void 727655Sbdewrite_cpu_clkdiv(uint32_t reg, uint32_t val) 737655Sbde{ 747655Sbde 757655Sbde bus_space_write_4(fdtbus_bs_tag, MV_AXP_CPU_DIVCLK_BASE, reg, val); 767655Sbde} 777655Sbde 787655Sbdevoid 797655Sbdeplatform_mp_setmaxid(void) 807655Sbde{ 817655Sbde 827655Sbde mp_maxid = 3; 831539Srgrimes} 841539Srgrimes 8554746Sphantomint 867655Sbdeplatform_mp_probe(void) 877655Sbde{ 8854746Sphantom 8954746Sphantom mp_ncpus = platform_get_ncpus(); 9054746Sphantom 9154746Sphantom return (mp_ncpus > 1); 9254746Sphantom} 9354746Sphantom 947655Sbdevoid 957655Sbdeplatform_mp_init_secondary(void) 967655Sbde{ 977655Sbde} 9829884Sache 9929883Sachevoid mptramp(void); 10029883Sache 10129883Sache 10229883Sache 10329883Sachevoid 10429883Sacheplatform_mp_start_ap(void) 10529883Sache{ 10629883Sache uint32_t reg, *src, *dst, cpu_num, div_val, cputype; 10729883Sache vm_offset_t smp_boot; 10829883Sache /* 10929883Sache * Initialization procedure depends on core revision, 11029883Sache * in this step CHIP ID is checked to choose proper procedure 1117655Sbde */ 1127655Sbde cputype = cpufunc_id(); 1137655Sbde cputype &= CPU_ID_CPU_MASK; 1147655Sbde 11554746Sphantom smp_boot = kva_alloc(PAGE_SIZE); 1167655Sbde pmap_kenter_nocache(smp_boot, 0xffff0000); 1177655Sbde dst = (uint32_t *) smp_boot; 1187655Sbde 1191539Srgrimes for (src = (uint32_t *)mptramp; src < (uint32_t *)mpentry; 1207655Sbde src++, dst++) { 12129883Sache *dst = *src; 1227655Sbde } 12329883Sache kva_free(smp_boot, PAGE_SIZE); 12454746Sphantom 1251539Srgrimes if (cputype == CPU_ID_MV88SV584X_V7) { 1261539Srgrimes /* Core rev A0 */ 12715483Sbde div_val = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1); 1281539Srgrimes div_val &= 0x3f; 12915483Sbde 13015483Sbde for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ ) { 13115483Sbde reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1); 1321539Srgrimes reg &= CPU_DIVCLK_MASK(cpu_num); 1331539Srgrimes reg |= div_val << (cpu_num * 8); 1341539Srgrimes write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1, reg); 1357655Sbde } 1367655Sbde } else { 1371539Srgrimes /* Core rev Z1 */ 1387655Sbde div_val = 0x01; 1397655Sbde 1407655Sbde if (mp_ncpus > 1) { 1417655Sbde reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL0); 1421539Srgrimes reg &= CPU_DIVCLK_MASK(3); 1431539Srgrimes reg |= div_val << 24; 1447655Sbde write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL0, reg); 1457655Sbde } 1467655Sbde 1477655Sbde for (cpu_num = 2; cpu_num < mp_ncpus; cpu_num++ ) { 1487655Sbde reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1); 1491539Srgrimes reg &= CPU_DIVCLK_MASK(cpu_num); 15029883Sache reg |= div_val << (cpu_num * 8); 1511539Srgrimes write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1, reg); 15229855Sache } 15329855Sache } 1541539Srgrimes 1551539Srgrimes reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL0); 1561539Srgrimes reg |= ((0x1 << (mp_ncpus - 1)) - 1) << 21; 15715483Sbde write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg); 1581539Srgrimes reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL0); 15912028Sache reg |= 0x01000000; 16029883Sache write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg); 1611539Srgrimes 1621539Srgrimes DELAY(100); 16315483Sbde reg &= ~(0xf << 21); 16415483Sbde write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg); 1651539Srgrimes DELAY(100); 16614813Sache 16712028Sache bus_space_write_4(fdtbus_bs_tag, MV_BASE, CPU_RESUME_CONTROL, 0); 1681539Srgrimes 1691539Srgrimes for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ ) 17015483Sbde bus_space_write_4(fdtbus_bs_tag, CPU_PMU(cpu_num), CPU_PMU_BOOT, 17115483Sbde pmap_kextract((vm_offset_t)mpentry)); 1721539Srgrimes 17314813Sache cpu_idcache_wbinv_all(); 17412028Sache 1751539Srgrimes for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ ) 1761539Srgrimes bus_space_write_4(fdtbus_bs_tag, MP, MP_SW_RESET(cpu_num), 0); 1777655Sbde 1781539Srgrimes /* XXX: Temporary workaround for hangup after releasing AP's */ 1791539Srgrimes wmb(); 18029883Sache DELAY(10); 18115483Sbde 18215483Sbde armadaxp_init_coher_fabric(); 18315483Sbde} 1841539Srgrimes 1857655Sbdevoid 1861539Srgrimesplatform_ipi_send(cpuset_t cpus, u_int ipi) 1871539Srgrimes{ 188 189 pic_ipi_send(cpus, ipi); 190} 191