119304Speter/*- 219304Speter * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org> 319304Speter * All rights reserved. 419304Speter * 519304Speter * Redistribution and use in source and binary forms, with or without 619304Speter * modification, are permitted provided that the following conditions 719304Speter * are met: 819304Speter * 1. Redistributions of source code must retain the above copyright 919304Speter * notice, this list of conditions and the following disclaimer. 1019304Speter * 2. Redistributions in binary form must reproduce the above copyright 11254225Speter * notice, this list of conditions and the following disclaimer in the 1219304Speter * documentation and/or other materials provided with the distribution. 1319304Speter * 1419304Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1519304Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1619304Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1719304Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1819304Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19254225Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2019304Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21254225Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22254225Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23254225Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24254225Speter */ 2519304Speter 2619304Speter#include <sys/cdefs.h> 2719304Speter__FBSDID("$FreeBSD: stable/11/sys/arm/nvidia/tegra124/tegra124_mp.c 307344 2016-10-15 08:27:54Z mmel $"); 2819304Speter 2919304Speter#include <sys/param.h> 3019304Speter#include <sys/systm.h> 3119304Speter#include <sys/bus.h> 3219304Speter#include <sys/kernel.h> 3319304Speter#include <sys/lock.h> 3419304Speter#include <sys/mutex.h> 3519304Speter#include <sys/smp.h> 3619304Speter 3719304Speter#include <vm/vm.h> 3819304Speter#include <vm/pmap.h> 3919304Speter 4019304Speter#include <machine/cpu.h> 4119304Speter#include <machine/intr.h> 4219304Speter#include <machine/fdt.h> 4319304Speter#include <machine/smp.h> 4419304Speter#include <machine/platformvar.h> 4519304Speter#include <machine/pmap.h> 4619304Speter 4719304Speter#include <arm/nvidia/tegra124/tegra124_mp.h> 4819304Speter 4919304Speter#define PMC_PHYSBASE 0x7000e400 5019304Speter#define PMC_SIZE 0x400 5119304Speter#define PMC_CONTROL_REG 0x0 5219304Speter#define PMC_PWRGATE_TOGGLE 0x30 5319304Speter#define PCM_PWRGATE_TOGGLE_START (1 << 8) 5419304Speter#define PMC_PWRGATE_STATUS 0x38 5519304Speter 5619304Speter#define TEGRA_EXCEPTION_VECTORS_BASE 0x6000F000 /* exception vectors */ 5719304Speter#define TEGRA_EXCEPTION_VECTORS_SIZE 1024 5819304Speter#define TEGRA_EXCEPTION_VECTOR_ENTRY 0x100 5919304Speter 6019304Spetervoid 6119304Spetertegra124_mp_setmaxid(platform_t plat) 6219304Speter{ 6319304Speter int ncpu; 6419304Speter 6519304Speter /* If we've already set the global vars don't bother to do it again. */ 6619304Speter if (mp_ncpus != 0) 6719304Speter return; 6819304Speter 6919304Speter /* Read current CP15 Cache Size ID Register */ 7019304Speter ncpu = cp15_l2ctlr_get(); 7119304Speter ncpu = CPUV7_L2CTLR_NPROC(ncpu); 7219304Speter 7319304Speter mp_ncpus = ncpu; 7419304Speter mp_maxid = ncpu - 1; 7519304Speter} 7619304Speter 77254225Spetervoid 7819304Spetertegra124_mp_start_ap(platform_t plat) 7919304Speter{ 8019304Speter bus_space_handle_t pmc; 8119304Speter bus_space_handle_t exvec; 8219304Speter int i; 8319304Speter uint32_t val; 8419304Speter uint32_t mask; 8519304Speter 8619304Speter if (bus_space_map(fdtbus_bs_tag, PMC_PHYSBASE, PMC_SIZE, 0, &pmc) != 0) 87254225Speter panic("Couldn't map the PMC\n"); 8819304Speter if (bus_space_map(fdtbus_bs_tag, TEGRA_EXCEPTION_VECTORS_BASE, 89254225Speter TEGRA_EXCEPTION_VECTORS_SIZE, 0, &exvec) != 0) 90254225Speter panic("Couldn't map the exception vectors\n"); 9119304Speter 92254225Speter bus_space_write_4(fdtbus_bs_tag, exvec , TEGRA_EXCEPTION_VECTOR_ENTRY, 9319304Speter pmap_kextract((vm_offset_t)mpentry)); 9419304Speter bus_space_read_4(fdtbus_bs_tag, exvec , TEGRA_EXCEPTION_VECTOR_ENTRY); 9519304Speter 96254225Speter 9719304Speter /* Wait until POWERGATE is ready (max 20 APB cycles). */ 98254225Speter do { 9919304Speter val = bus_space_read_4(fdtbus_bs_tag, pmc, 10019304Speter PMC_PWRGATE_TOGGLE); 10119304Speter } while ((val & PCM_PWRGATE_TOGGLE_START) != 0); 10219304Speter 10319304Speter for (i = 1; i < mp_ncpus; i++) { 10419304Speter val = bus_space_read_4(fdtbus_bs_tag, pmc, PMC_PWRGATE_STATUS); 10519304Speter mask = 1 << (i + 8); /* cpu mask */ 10619304Speter if ((val & mask) == 0) { 10719304Speter /* Wait until POWERGATE is ready (max 20 APB cycles). */ 10819304Speter do { 10919304Speter val = bus_space_read_4(fdtbus_bs_tag, pmc, 110 PMC_PWRGATE_TOGGLE); 111 } while ((val & PCM_PWRGATE_TOGGLE_START) != 0); 112 bus_space_write_4(fdtbus_bs_tag, pmc, 113 PMC_PWRGATE_TOGGLE, 114 PCM_PWRGATE_TOGGLE_START | (8 + i)); 115 116 /* Wait until CPU is powered */ 117 do { 118 val = bus_space_read_4(fdtbus_bs_tag, pmc, 119 PMC_PWRGATE_STATUS); 120 } while ((val & mask) == 0); 121 } 122 123 } 124 dsb(); 125 sev(); 126 bus_space_unmap(fdtbus_bs_tag, pmc, PMC_SIZE); 127 bus_space_unmap(fdtbus_bs_tag, exvec, TEGRA_EXCEPTION_VECTORS_SIZE); 128} 129