1/*- 2 * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD: releng/11.0/sys/arm/rockchip/rk30xx_mp.c 296100 2016-02-26 16:04:47Z andrew $"); 28#include <sys/param.h> 29#include <sys/systm.h> 30#include <sys/bus.h> 31#include <sys/kernel.h> 32#include <sys/lock.h> 33#include <sys/mutex.h> 34#include <sys/smp.h> 35 36#include <vm/vm.h> 37#include <vm/pmap.h> 38 39#include <machine/cpu.h> 40#include <machine/smp.h> 41#include <machine/fdt.h> 42#include <machine/intr.h> 43 44#define SCU_PHYSBASE 0x1013c000 45#define SCU_SIZE 0x100 46 47#define SCU_CONTROL_REG 0x00 48#define SCU_CONTROL_ENABLE (1 << 0) 49#define SCU_STANDBY_EN (1 << 5) 50#define SCU_CONFIG_REG 0x04 51#define SCU_CONFIG_REG_NCPU_MASK 0x03 52#define SCU_CPUPOWER_REG 0x08 53#define SCU_INV_TAGS_REG 0x0c 54 55#define SCU_FILTER_START_REG 0x10 56#define SCU_FILTER_END_REG 0x14 57#define SCU_SECURE_ACCESS_REG 0x18 58#define SCU_NONSECURE_ACCESS_REG 0x1c 59 60#define IMEM_PHYSBASE 0x10080000 61#define IMEM_SIZE 0x20 62 63#define PMU_PHYSBASE 0x20004000 64#define PMU_SIZE 0x100 65#define PMU_PWRDN_CON 0x08 66#define PMU_PWRDN_SCU (1 << 4) 67 68extern char *mpentry_addr; 69static void rk30xx_boot2(void); 70 71static void 72rk30xx_boot2(void) 73{ 74 75 __asm __volatile( 76 "ldr pc, 1f\n" 77 ".globl mpentry_addr\n" 78 "mpentry_addr:\n" 79 "1: .space 4\n"); 80} 81 82void 83platform_mp_setmaxid(void) 84{ 85 bus_space_handle_t scu; 86 int ncpu; 87 uint32_t val; 88 89 if (mp_ncpus != 0) 90 return; 91 92 if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0) 93 panic("Could not map the SCU"); 94 95 val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONFIG_REG); 96 ncpu = (val & SCU_CONFIG_REG_NCPU_MASK) + 1; 97 bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE); 98 99 mp_ncpus = ncpu; 100 mp_maxid = ncpu - 1; 101} 102 103void 104platform_mp_start_ap(void) 105{ 106 bus_space_handle_t scu; 107 bus_space_handle_t imem; 108 bus_space_handle_t pmu; 109 uint32_t val; 110 int i; 111 112 if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0) 113 panic("Could not map the SCU"); 114 if (bus_space_map(fdtbus_bs_tag, IMEM_PHYSBASE, 115 IMEM_SIZE, 0, &imem) != 0) 116 panic("Could not map the IMEM"); 117 if (bus_space_map(fdtbus_bs_tag, PMU_PHYSBASE, PMU_SIZE, 0, &pmu) != 0) 118 panic("Could not map the PMU"); 119 120 /* 121 * Invalidate SCU cache tags. The 0x0000ffff constant invalidates all 122 * ways on all cores 0-3. Per the ARM docs, it's harmless to write to 123 * the bits for cores that are not present. 124 */ 125 bus_space_write_4(fdtbus_bs_tag, scu, SCU_INV_TAGS_REG, 0x0000ffff); 126 127 /* Make sure all cores except the first are off */ 128 val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); 129 for (i = 1; i < mp_ncpus; i++) 130 val |= 1 << i; 131 bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val); 132 133 /* Enable SCU power domain */ 134 val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); 135 val &= ~PMU_PWRDN_SCU; 136 bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val); 137 138 /* Enable SCU */ 139 val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG); 140 bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG, 141 val | SCU_CONTROL_ENABLE); 142 143 /* 144 * Cores will execute the code which resides at the start of 145 * the on-chip bootram/sram after power-on. This sram region 146 * should be reserved and the trampoline code that directs 147 * the core to the real startup code in ram should be copied 148 * into this sram region. 149 * 150 * First set boot function for the sram code. 151 */ 152 mpentry_addr = (char *)pmap_kextract((vm_offset_t)mpentry); 153 154 /* Copy trampoline to sram, that runs during startup of the core */ 155 bus_space_write_region_4(fdtbus_bs_tag, imem, 0, 156 (uint32_t *)&rk30xx_boot2, 8); 157 158 dcache_wbinv_poc_all(); 159 160 /* Start all cores */ 161 val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); 162 for (i = 1; i < mp_ncpus; i++) 163 val &= ~(1 << i); 164 bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val); 165 166 armv7_sev(); 167 168 bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE); 169 bus_space_unmap(fdtbus_bs_tag, imem, IMEM_SIZE); 170 bus_space_unmap(fdtbus_bs_tag, pmu, PMU_SIZE); 171} 172