1/* $NetBSD: rk3066_smp.c,v 1.2 2021/11/13 15:17:22 jmcneill Exp $ */ 2 3/*- 4 * Copyright (c) 2021 Jared McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include "opt_soc.h" 30#include "opt_multiprocessor.h" 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: rk3066_smp.c,v 1.2 2021/11/13 15:17:22 jmcneill Exp $"); 34 35#include <sys/param.h> 36#include <sys/bus.h> 37#include <sys/cpu.h> 38#include <sys/device.h> 39 40#include <dev/fdt/fdtvar.h> 41#include <arm/fdt/arm_fdtvar.h> 42 43#include <uvm/uvm_extern.h> 44 45#define PMU_PWRDN_CON 0x0008 46#define PMU_PWRDN_ST 0x000c 47 48#define SRAM_ENTRY_PA 0x0008 49#define SRAM_DOORBELL 0x0004 50#define SRAM_DOORBELL_MAGIC 0xdeadbeaf 51 52extern struct bus_space arm_generic_bs_tag; 53 54static uint32_t 55rk3066_mpstart_pa(void) 56{ 57 bool ok __diagused; 58 paddr_t pa; 59 60 ok = pmap_extract(pmap_kernel(), (vaddr_t)cpu_mpstart, &pa); 61 KASSERT(ok); 62 63 return (uint32_t)pa; 64} 65 66static int 67rk3066_map(int phandle, bus_space_tag_t bst, bus_space_handle_t *pbsh, 68 bus_size_t *psize) 69{ 70 bus_addr_t addr; 71 int error; 72 73 error = fdtbus_get_reg(phandle, 0, &addr, psize); 74 if (error != 0) { 75 return error; 76 } 77 78 return bus_space_map(bst, addr, *psize, 0, pbsh); 79} 80 81static int 82rk3066_smp_enable(int cpus_phandle, u_int cpuno) 83{ 84 bus_space_tag_t bst = &arm_generic_bs_tag; 85 bus_space_handle_t bsh_sram, bsh_pmu; 86 bus_size_t sz_sram, sz_pmu; 87 uint32_t val; 88 int error; 89 90 const int sram_phandle = 91 of_find_bycompat(OF_peer(0), "rockchip,rk3066-smp-sram"); 92 if (sram_phandle == -1) { 93 printf("%s: missing rockchip,rk3066-smp-sram node\n", 94 __func__); 95 return ENXIO; 96 } 97 98 const int pmu_phandle = fdtbus_get_phandle(cpus_phandle, 99 "rockchip,pmu"); 100 if (pmu_phandle == -1) { 101 printf("%s: missing rockchip,pmu xref\n", __func__); 102 return ENXIO; 103 } 104 105 error = rk3066_map(sram_phandle, bst, &bsh_sram, &sz_sram); 106 if (error != 0) { 107 return error; 108 } 109 110 error = rk3066_map(pmu_phandle, bst, &bsh_pmu, &sz_pmu); 111 if (error != 0) { 112 bus_space_unmap(bst, bsh_pmu, sz_pmu); 113 return error; 114 } 115 116 /* Enable the A17 core's power domain */ 117 val = bus_space_read_4(bst, bsh_pmu, PMU_PWRDN_CON); 118 val &= ~__BIT(cpuno); 119 bus_space_write_4(bst, bsh_pmu, PMU_PWRDN_CON, val); 120 121 /* Wait for the A17 core to power on */ 122 do { 123 val = bus_space_read_4(bst, bsh_pmu, PMU_PWRDN_ST); 124 } while ((val & __BIT(cpuno)) != 0); 125 126 delay(2000); 127 128 /* Set wake vector */ 129 bus_space_write_4(bst, bsh_sram, SRAM_ENTRY_PA, rk3066_mpstart_pa()); 130 /* Notify boot rom that we are ready to start */ 131 bus_space_write_4(bst, bsh_sram, SRAM_DOORBELL, SRAM_DOORBELL_MAGIC); 132 dsb(); 133 sev(); 134 135 bus_space_unmap(bst, bsh_pmu, sz_pmu); 136 bus_space_unmap(bst, bsh_sram, sz_sram); 137 138 return 0; 139} 140 141static int 142cpu_enable_rk3066(int phandle) 143{ 144 uint64_t mpidr; 145 146 fdtbus_get_reg64(phandle, 0, &mpidr, NULL); 147 148 const u_int cpuno = __SHIFTOUT(mpidr, MPIDR_AFF0); 149 150 cpu_dcache_wbinv_all(); 151 152 return rk3066_smp_enable(OF_parent(phandle), cpuno); 153} 154 155ARM_CPU_METHOD(rk3066, "rockchip,rk3066-smp", cpu_enable_rk3066); 156