1*8e6b5205Srin /* $NetBSD: meson_platform.c,v 1.17 2021/01/29 13:10:07 rin Exp $ */ 288499cefSjmcneill 388499cefSjmcneill /*- 488499cefSjmcneill * Copyright (c) 2019 Jared McNeill <jmcneill@invisible.ca> 588499cefSjmcneill * All rights reserved. 688499cefSjmcneill * 788499cefSjmcneill * Redistribution and use in source and binary forms, with or without 888499cefSjmcneill * modification, are permitted provided that the following conditions 988499cefSjmcneill * are met: 1088499cefSjmcneill * 1. Redistributions of source code must retain the above copyright 1188499cefSjmcneill * notice, this list of conditions and the following disclaimer. 1288499cefSjmcneill * 2. Redistributions in binary form must reproduce the above copyright 1388499cefSjmcneill * notice, this list of conditions and the following disclaimer in the 1488499cefSjmcneill * documentation and/or other materials provided with the distribution. 1588499cefSjmcneill * 1688499cefSjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1788499cefSjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1888499cefSjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1988499cefSjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2088499cefSjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2188499cefSjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2288499cefSjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2388499cefSjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2488499cefSjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2588499cefSjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2688499cefSjmcneill * SUCH DAMAGE. 2788499cefSjmcneill */ 2888499cefSjmcneill 2988499cefSjmcneill #include "opt_soc.h" 3088499cefSjmcneill #include "opt_multiprocessor.h" 3188499cefSjmcneill #include "opt_console.h" 3288499cefSjmcneill 3388499cefSjmcneill #include "arml2cc.h" 3488499cefSjmcneill 3588499cefSjmcneill #include <sys/cdefs.h> 36*8e6b5205Srin __KERNEL_RCSID(0, "$NetBSD: meson_platform.c,v 1.17 2021/01/29 13:10:07 rin Exp $"); 3788499cefSjmcneill 3888499cefSjmcneill #include <sys/param.h> 3988499cefSjmcneill #include <sys/bus.h> 4088499cefSjmcneill #include <sys/cpu.h> 4188499cefSjmcneill #include <sys/device.h> 4288499cefSjmcneill #include <sys/termios.h> 4388499cefSjmcneill 4488499cefSjmcneill #include <dev/fdt/fdtvar.h> 4588499cefSjmcneill #include <arm/fdt/arm_fdtvar.h> 4688499cefSjmcneill 4788499cefSjmcneill #include <uvm/uvm_extern.h> 4888499cefSjmcneill 4988499cefSjmcneill #include <machine/bootconfig.h> 5088499cefSjmcneill #include <arm/cpufunc.h> 5188499cefSjmcneill 5288499cefSjmcneill #include <arm/cortex/a9tmr_var.h> 5382a9c324Sjmcneill #include <arm/cortex/gtmr_var.h> 5488499cefSjmcneill #include <arm/cortex/pl310_var.h> 5588499cefSjmcneill #include <arm/cortex/scu_reg.h> 5688499cefSjmcneill 5788499cefSjmcneill #include <arm/amlogic/meson_uart.h> 5888499cefSjmcneill 5988499cefSjmcneill #include <evbarm/fdt/platform.h> 6088499cefSjmcneill #include <evbarm/fdt/machdep.h> 6188499cefSjmcneill 62ce2792c5Sjmcneill #include <net/if_ether.h> 63ce2792c5Sjmcneill 6488499cefSjmcneill #include <libfdt.h> 6588499cefSjmcneill 6688499cefSjmcneill #define MESON_CORE_APB3_VBASE KERNEL_IO_VBASE 6788499cefSjmcneill #define MESON_CORE_APB3_PBASE 0xc0000000 6882a9c324Sjmcneill #define MESON_CORE_APB3_SIZE 0x01400000 6988499cefSjmcneill 7088499cefSjmcneill #define MESON_CBUS_OFFSET 0x01100000 7188499cefSjmcneill 72f0949908Sjmcneill #define MESON8B_WATCHDOG_BASE 0xc1109900 73f0949908Sjmcneill #define MESON8B_WATCHDOG_SIZE 0x8 74f0949908Sjmcneill #define MESON8B_WATCHDOG_TC 0x00 75f0949908Sjmcneill #define MESON8B_WATCHDOG_TC_CPUS __BITS(27,24) 76f0949908Sjmcneill #define MESON8B_WATCHDOG_TC_ENABLE __BIT(19) 77f0949908Sjmcneill #define MESON8B_WATCHDOG_TC_TCNT __BITS(15,0) 78f0949908Sjmcneill #define MESON8B_WATCHDOG_RESET 0x04 79f0949908Sjmcneill #define MESON8B_WATCHDOG_RESET_COUNT __BITS(15,0) 80f0949908Sjmcneill 81f0949908Sjmcneill #define MESONGX_WATCHDOG_BASE 0xc11098d0 82f0949908Sjmcneill #define MESONGX_WATCHDOG_SIZE 0x10 83f0949908Sjmcneill #define MESONGX_WATCHDOG_CNTL 0x00 8432461851Sjmcneill #define MESONGX_WATCHDOG_CNTL_CLK_EN __BIT(24) 8532461851Sjmcneill #define MESONGX_WATCHDOG_CNTL_SYS_RESET_N_EN __BIT(21) 86f0949908Sjmcneill #define MESONGX_WATCHDOG_CNTL_WDOG_EN __BIT(18) 87f0949908Sjmcneill #define MESONGX_WATCHDOG_CNTL1 0x04 88f0949908Sjmcneill #define MESONGX_WATCHDOG_TCNT 0x08 89f0949908Sjmcneill #define MESONGX_WATCHDOG_TCNT_COUNT __BITS(15,0) 90f0949908Sjmcneill #define MESONGX_WATCHDOG_RESET 0x0c 9188499cefSjmcneill 9288499cefSjmcneill #define MESON8B_ARM_VBASE (MESON_CORE_APB3_VBASE + MESON_CORE_APB3_SIZE) 9388499cefSjmcneill #define MESON8B_ARM_PBASE 0xc4200000 9488499cefSjmcneill #define MESON8B_ARM_SIZE 0x00200000 9588499cefSjmcneill #define MESON8B_ARM_PL310_BASE 0x00000000 9688499cefSjmcneill #define MESON8B_ARM_SCU_BASE 0x00100000 9788499cefSjmcneill 9888499cefSjmcneill #define MESON8B_AOBUS_VBASE (MESON8B_ARM_VBASE + MESON8B_ARM_SIZE) 9982a9c324Sjmcneill #define MESON8B_AOBUS_PBASE 0xc8000000 10082a9c324Sjmcneill #define MESON8B_AOBUS_SIZE 0x00200000 1011b232e6cSjmcneill #define MESON8B_AOBUS_RTI_OFFSET 0x00100000 10288499cefSjmcneill 10388499cefSjmcneill #define MESON_AOBUS_PWR_CTRL0_REG 0xe0 10488499cefSjmcneill #define MESON_AOBUS_PWR_CTRL1_REG 0xe4 10588499cefSjmcneill #define MESON_AOBUS_PWR_MEM_PD0_REG 0xf4 10688499cefSjmcneill 10788499cefSjmcneill #define MESON_CBUS_CPU_CLK_CNTL_REG 0x419c 10888499cefSjmcneill 10988499cefSjmcneill 11088499cefSjmcneill #define MESON8B_SRAM_VBASE (MESON8B_AOBUS_VBASE + MESON8B_AOBUS_SIZE) 11188499cefSjmcneill #define MESON8B_SRAM_PBASE 0xd9000000 11282a9c324Sjmcneill #define MESON8B_SRAM_SIZE 0x00200000 /* 0x10000 rounded up */ 11388499cefSjmcneill 11488499cefSjmcneill #define MESON8B_SRAM_CPUCONF_OFFSET 0x1ff80 11588499cefSjmcneill #define MESON8B_SRAM_CPUCONF_CTRL_REG 0x00 11688499cefSjmcneill #define MESON8B_SRAM_CPUCONF_CPU_ADDR_REG(n) (0x04 * (n)) 11788499cefSjmcneill 11888499cefSjmcneill 11988499cefSjmcneill extern struct arm32_bus_dma_tag arm_generic_dma_tag; 12088499cefSjmcneill extern struct bus_space arm_generic_bs_tag; 12188499cefSjmcneill 12288499cefSjmcneill #define meson_dma_tag arm_generic_dma_tag 12388499cefSjmcneill #define meson_bs_tag arm_generic_bs_tag 12488499cefSjmcneill 12588499cefSjmcneill static const struct pmap_devmap * 12688499cefSjmcneill meson_platform_devmap(void) 12788499cefSjmcneill { 12888499cefSjmcneill static const struct pmap_devmap devmap[] = { 12988499cefSjmcneill DEVMAP_ENTRY(MESON_CORE_APB3_VBASE, 13088499cefSjmcneill MESON_CORE_APB3_PBASE, 13188499cefSjmcneill MESON_CORE_APB3_SIZE), 13288499cefSjmcneill DEVMAP_ENTRY(MESON8B_ARM_VBASE, 13388499cefSjmcneill MESON8B_ARM_PBASE, 13488499cefSjmcneill MESON8B_ARM_SIZE), 13588499cefSjmcneill DEVMAP_ENTRY(MESON8B_AOBUS_VBASE, 13688499cefSjmcneill MESON8B_AOBUS_PBASE, 13788499cefSjmcneill MESON8B_AOBUS_SIZE), 13888499cefSjmcneill DEVMAP_ENTRY(MESON8B_SRAM_VBASE, 13988499cefSjmcneill MESON8B_SRAM_PBASE, 14088499cefSjmcneill MESON8B_SRAM_SIZE), 14188499cefSjmcneill DEVMAP_ENTRY_END 14288499cefSjmcneill }; 14388499cefSjmcneill 14488499cefSjmcneill return devmap; 14588499cefSjmcneill } 14688499cefSjmcneill 14788499cefSjmcneill static void 14888499cefSjmcneill meson_platform_init_attach_args(struct fdt_attach_args *faa) 14988499cefSjmcneill { 15088499cefSjmcneill faa->faa_bst = &meson_bs_tag; 15188499cefSjmcneill faa->faa_dmat = &meson_dma_tag; 15288499cefSjmcneill } 15388499cefSjmcneill 15488499cefSjmcneill void meson_platform_early_putchar(char); 15588499cefSjmcneill 156078bd70bSskrll void __noasan 15788499cefSjmcneill meson_platform_early_putchar(char c) 15888499cefSjmcneill { 15988499cefSjmcneill #ifdef CONSADDR 16088499cefSjmcneill #define CONSADDR_VA ((CONSADDR - MESON8B_AOBUS_PBASE) + MESON8B_AOBUS_VBASE) 16188499cefSjmcneill volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ? 16288499cefSjmcneill (volatile uint32_t *)CONSADDR_VA : 16388499cefSjmcneill (volatile uint32_t *)CONSADDR; 16488499cefSjmcneill int timo = 150000; 16588499cefSjmcneill 16688499cefSjmcneill while ((uartaddr[UART_STATUS_REG/4] & UART_STATUS_TX_EMPTY) == 0) { 16788499cefSjmcneill if (--timo == 0) 16888499cefSjmcneill break; 16988499cefSjmcneill } 17088499cefSjmcneill 17188499cefSjmcneill uartaddr[UART_WFIFO_REG/4] = c; 17288499cefSjmcneill 17388499cefSjmcneill while ((uartaddr[UART_STATUS_REG/4] & UART_STATUS_TX_EMPTY) == 0) { 17488499cefSjmcneill if (--timo == 0) 17588499cefSjmcneill break; 17688499cefSjmcneill } 17788499cefSjmcneill #endif 17888499cefSjmcneill } 17988499cefSjmcneill 18088499cefSjmcneill static void 18188499cefSjmcneill meson_platform_device_register(device_t self, void *aux) 18288499cefSjmcneill { 183ce2792c5Sjmcneill prop_dictionary_t dict = device_properties(self); 184ce2792c5Sjmcneill 185ce2792c5Sjmcneill if (device_is_a(self, "awge") && device_unit(self) == 0) { 186ce2792c5Sjmcneill uint8_t enaddr[ETHER_ADDR_LEN]; 187ce2792c5Sjmcneill if (get_bootconf_option(boot_args, "awge0.mac-address", 188ce2792c5Sjmcneill BOOTOPT_TYPE_MACADDR, enaddr)) { 189280931ccSskrll prop_dictionary_set_data(dict, "mac-address", enaddr, 190ce2792c5Sjmcneill sizeof(enaddr)); 191ce2792c5Sjmcneill } 192ce2792c5Sjmcneill } 193ce2792c5Sjmcneill 19482a9c324Sjmcneill if (device_is_a(self, "mesonfb")) { 195ce2792c5Sjmcneill int scale, depth; 196ce2792c5Sjmcneill 197ce2792c5Sjmcneill if (get_bootconf_option(boot_args, "fb.scale", 198ce2792c5Sjmcneill BOOTOPT_TYPE_INT, &scale) && scale > 0) { 199ce2792c5Sjmcneill prop_dictionary_set_uint32(dict, "scale", scale); 200ce2792c5Sjmcneill } 201ce2792c5Sjmcneill if (get_bootconf_option(boot_args, "fb.depth", 202ce2792c5Sjmcneill BOOTOPT_TYPE_INT, &depth)) { 203ce2792c5Sjmcneill prop_dictionary_set_uint32(dict, "depth", depth); 204ce2792c5Sjmcneill } 205ce2792c5Sjmcneill } 20688499cefSjmcneill } 20788499cefSjmcneill 208d52edb14Sjmcneill #if defined(SOC_MESON8B) 209d52edb14Sjmcneill #define MESON8B_BOOTINFO_REG 0xd901ff04 210d52edb14Sjmcneill static int 211d52edb14Sjmcneill meson8b_get_boot_id(void) 212d52edb14Sjmcneill { 213d52edb14Sjmcneill static int boot_id = -1; 214d52edb14Sjmcneill bus_space_tag_t bst = &arm_generic_bs_tag; 215d52edb14Sjmcneill bus_space_handle_t bsh; 216d52edb14Sjmcneill 217d52edb14Sjmcneill if (boot_id == -1) { 218d52edb14Sjmcneill if (bus_space_map(bst, MESON8B_BOOTINFO_REG, 4, 0, &bsh) != 0) 219d52edb14Sjmcneill return -1; 220d52edb14Sjmcneill 221d52edb14Sjmcneill boot_id = (int)bus_space_read_4(bst, bsh, 0); 222d52edb14Sjmcneill 223d52edb14Sjmcneill bus_space_unmap(bst, bsh, 4); 224d52edb14Sjmcneill } 225d52edb14Sjmcneill 226d52edb14Sjmcneill return boot_id; 227d52edb14Sjmcneill } 228d52edb14Sjmcneill 229d52edb14Sjmcneill static void 230d52edb14Sjmcneill meson8b_platform_device_register(device_t self, void *aux) 231d52edb14Sjmcneill { 232d52edb14Sjmcneill device_t parent = device_parent(self); 233d52edb14Sjmcneill char *ptr; 234d52edb14Sjmcneill 235d52edb14Sjmcneill if (device_is_a(self, "ld") && 236d52edb14Sjmcneill device_is_a(parent, "sdmmc") && 237d52edb14Sjmcneill (device_is_a(device_parent(parent), "mesonsdhc") || 238d52edb14Sjmcneill device_is_a(device_parent(parent), "mesonsdio"))) { 239d52edb14Sjmcneill 240d52edb14Sjmcneill const int boot_id = meson8b_get_boot_id(); 241d52edb14Sjmcneill const bool has_rootdev = get_bootconf_option(boot_args, "root", BOOTOPT_TYPE_STRING, &ptr) != 0; 242d52edb14Sjmcneill 243d52edb14Sjmcneill if (!has_rootdev) { 244d52edb14Sjmcneill char rootarg[64]; 245d52edb14Sjmcneill snprintf(rootarg, sizeof(rootarg), " root=%sa", device_xname(self)); 246d52edb14Sjmcneill 247d52edb14Sjmcneill /* Assume that SDIO is used for SD cards and SDHC is used for eMMC */ 248d52edb14Sjmcneill if (device_is_a(device_parent(parent), "mesonsdhc") && boot_id == 0) 249d52edb14Sjmcneill strcat(boot_args, rootarg); 250d52edb14Sjmcneill else if (device_is_a(device_parent(parent), "mesonsdio") && boot_id != 0) 251d52edb14Sjmcneill strcat(boot_args, rootarg); 252d52edb14Sjmcneill } 253d52edb14Sjmcneill } 254d52edb14Sjmcneill 255d52edb14Sjmcneill meson_platform_device_register(self, aux); 256d52edb14Sjmcneill } 257d52edb14Sjmcneill #endif 258d52edb14Sjmcneill 25988499cefSjmcneill static u_int 26088499cefSjmcneill meson_platform_uart_freq(void) 26188499cefSjmcneill { 26288499cefSjmcneill return 0; 26388499cefSjmcneill } 26488499cefSjmcneill 26588499cefSjmcneill static void 26688499cefSjmcneill meson_platform_bootstrap(void) 26788499cefSjmcneill { 26888499cefSjmcneill arm_fdt_cpu_bootstrap(); 26988499cefSjmcneill 27088499cefSjmcneill void *fdt_data = __UNCONST(fdtbus_get_data()); 27188499cefSjmcneill const int chosen_off = fdt_path_offset(fdt_data, "/chosen"); 27288499cefSjmcneill if (chosen_off < 0) 27388499cefSjmcneill return; 27488499cefSjmcneill 27588499cefSjmcneill if (match_bootconf_option(boot_args, "console", "fb")) { 27688499cefSjmcneill const int framebuffer_off = 27788499cefSjmcneill fdt_path_offset(fdt_data, "/chosen/framebuffer"); 27888499cefSjmcneill if (framebuffer_off >= 0) { 27988499cefSjmcneill const char *status = fdt_getprop(fdt_data, 28088499cefSjmcneill framebuffer_off, "status", NULL); 28188499cefSjmcneill if (status == NULL || strncmp(status, "ok", 2) == 0) { 28288499cefSjmcneill fdt_setprop_string(fdt_data, chosen_off, 28388499cefSjmcneill "stdout-path", "/chosen/framebuffer"); 28488499cefSjmcneill } 28588499cefSjmcneill } 28688499cefSjmcneill } else if (match_bootconf_option(boot_args, "console", "serial")) { 28788499cefSjmcneill fdt_setprop_string(fdt_data, chosen_off, 28888499cefSjmcneill "stdout-path", "serial0:115200n8"); 28988499cefSjmcneill } 29088499cefSjmcneill } 29188499cefSjmcneill 29288499cefSjmcneill #if defined(SOC_MESON8B) 29388499cefSjmcneill static void 29488499cefSjmcneill meson8b_platform_bootstrap(void) 29588499cefSjmcneill { 29688499cefSjmcneill 29788499cefSjmcneill #if NARML2CC > 0 29888499cefSjmcneill const bus_space_handle_t pl310_bh = MESON8B_ARM_VBASE + MESON8B_ARM_PL310_BASE; 29988499cefSjmcneill arml2cc_init(&arm_generic_bs_tag, pl310_bh, 0); 30088499cefSjmcneill #endif 30188499cefSjmcneill 30288499cefSjmcneill meson_platform_bootstrap(); 30388499cefSjmcneill } 30488499cefSjmcneill 30588499cefSjmcneill static void 306f0949908Sjmcneill meson8b_platform_reset(void) 30788499cefSjmcneill { 30888499cefSjmcneill bus_space_tag_t bst = &meson_bs_tag; 30988499cefSjmcneill bus_space_handle_t bsh; 31088499cefSjmcneill 311f0949908Sjmcneill bus_space_map(bst, MESON8B_WATCHDOG_BASE, MESON8B_WATCHDOG_SIZE, 0, &bsh); 31288499cefSjmcneill 313f0949908Sjmcneill bus_space_write_4(bst, bsh, MESON8B_WATCHDOG_TC, 314f0949908Sjmcneill MESON8B_WATCHDOG_TC_CPUS | MESON8B_WATCHDOG_TC_ENABLE | __SHIFTIN(0xfff, MESON8B_WATCHDOG_TC_TCNT)); 315f0949908Sjmcneill bus_space_write_4(bst, bsh, MESON8B_WATCHDOG_RESET, 0); 31688499cefSjmcneill 31788499cefSjmcneill for (;;) { 31888499cefSjmcneill __asm("wfi"); 31988499cefSjmcneill } 32088499cefSjmcneill } 32188499cefSjmcneill 322*8e6b5205Srin #ifdef MULTIPROCESSOR 32388499cefSjmcneill static void 32488499cefSjmcneill meson8b_mpinit_delay(u_int n) 32588499cefSjmcneill { 32688499cefSjmcneill for (volatile int i = 0; i < n; i++) 32788499cefSjmcneill ; 32888499cefSjmcneill } 329*8e6b5205Srin #endif 33088499cefSjmcneill 33188499cefSjmcneill static int 33288499cefSjmcneill cpu_enable_meson8b(int phandle) 33388499cefSjmcneill { 334*8e6b5205Srin #ifdef MULTIPROCESSOR 33588499cefSjmcneill const bus_addr_t cbar = armreg_cbar_read(); 33688499cefSjmcneill bus_space_tag_t bst = &arm_generic_bs_tag; 33788499cefSjmcneill 33888499cefSjmcneill const bus_space_handle_t scu_bsh = 33988499cefSjmcneill cbar - MESON8B_ARM_PBASE + MESON8B_ARM_VBASE; 34088499cefSjmcneill const bus_space_handle_t cpuconf_bsh = 34188499cefSjmcneill MESON8B_SRAM_VBASE + MESON8B_SRAM_CPUCONF_OFFSET; 34288499cefSjmcneill const bus_space_handle_t ao_bsh = 3431b232e6cSjmcneill MESON8B_AOBUS_VBASE + MESON8B_AOBUS_RTI_OFFSET; 34488499cefSjmcneill const bus_space_handle_t cbus_bsh = 34588499cefSjmcneill MESON_CORE_APB3_VBASE + MESON_CBUS_OFFSET; 34688499cefSjmcneill uint32_t pwr_sts, pwr_cntl0, pwr_cntl1, cpuclk, mempd0; 34788499cefSjmcneill uint64_t mpidr; 34888499cefSjmcneill 34988499cefSjmcneill fdtbus_get_reg64(phandle, 0, &mpidr, NULL); 35088499cefSjmcneill 35188499cefSjmcneill const u_int cpuno = __SHIFTOUT(mpidr, MPIDR_AFF0); 35288499cefSjmcneill 35388499cefSjmcneill bus_space_write_4(bst, cpuconf_bsh, MESON8B_SRAM_CPUCONF_CPU_ADDR_REG(cpuno), 35488499cefSjmcneill KERN_VTOPHYS((vaddr_t)cpu_mpstart)); 35588499cefSjmcneill 35688499cefSjmcneill pwr_sts = bus_space_read_4(bst, scu_bsh, SCU_CPU_PWR_STS); 35788499cefSjmcneill pwr_sts &= ~(3 << (8 * cpuno)); 35888499cefSjmcneill bus_space_write_4(bst, scu_bsh, SCU_CPU_PWR_STS, pwr_sts); 35988499cefSjmcneill 36088499cefSjmcneill pwr_cntl0 = bus_space_read_4(bst, ao_bsh, MESON_AOBUS_PWR_CTRL0_REG); 36188499cefSjmcneill pwr_cntl0 &= ~((3 << 18) << ((cpuno - 1) * 2)); 36288499cefSjmcneill bus_space_write_4(bst, ao_bsh, MESON_AOBUS_PWR_CTRL0_REG, pwr_cntl0); 36388499cefSjmcneill 36488499cefSjmcneill meson8b_mpinit_delay(5000); 36588499cefSjmcneill 36688499cefSjmcneill cpuclk = bus_space_read_4(bst, cbus_bsh, MESON_CBUS_CPU_CLK_CNTL_REG); 36788499cefSjmcneill cpuclk |= (1 << (24 + cpuno)); 36888499cefSjmcneill bus_space_write_4(bst, cbus_bsh, MESON_CBUS_CPU_CLK_CNTL_REG, cpuclk); 36988499cefSjmcneill 37088499cefSjmcneill mempd0 = bus_space_read_4(bst, ao_bsh, MESON_AOBUS_PWR_MEM_PD0_REG); 37188499cefSjmcneill mempd0 &= ~((uint32_t)(0xf << 28) >> ((cpuno - 1) * 4)); 37288499cefSjmcneill bus_space_write_4(bst, ao_bsh, MESON_AOBUS_PWR_MEM_PD0_REG, mempd0); 37388499cefSjmcneill 37488499cefSjmcneill pwr_cntl1 = bus_space_read_4(bst, ao_bsh, MESON_AOBUS_PWR_CTRL1_REG); 37588499cefSjmcneill pwr_cntl1 &= ~((3 << 4) << ((cpuno - 1) * 2)); 37688499cefSjmcneill bus_space_write_4(bst, ao_bsh, MESON_AOBUS_PWR_CTRL1_REG, pwr_cntl1); 37788499cefSjmcneill 37888499cefSjmcneill meson8b_mpinit_delay(10000); 37988499cefSjmcneill 38088499cefSjmcneill for (;;) { 38188499cefSjmcneill pwr_cntl1 = bus_space_read_4(bst, ao_bsh, 38288499cefSjmcneill MESON_AOBUS_PWR_CTRL1_REG) & ((1 << 17) << (cpuno - 1)); 38388499cefSjmcneill if (pwr_cntl1) 38488499cefSjmcneill break; 38588499cefSjmcneill meson8b_mpinit_delay(10000); 38688499cefSjmcneill } 38788499cefSjmcneill 38888499cefSjmcneill pwr_cntl0 = bus_space_read_4(bst, ao_bsh, MESON_AOBUS_PWR_CTRL0_REG); 38988499cefSjmcneill pwr_cntl0 &= ~(1 << cpuno); 39088499cefSjmcneill bus_space_write_4(bst, ao_bsh, MESON_AOBUS_PWR_CTRL0_REG, pwr_cntl0); 39188499cefSjmcneill 39288499cefSjmcneill cpuclk = bus_space_read_4(bst, cbus_bsh, MESON_CBUS_CPU_CLK_CNTL_REG); 39388499cefSjmcneill cpuclk &= ~(1 << (24 + cpuno)); 39488499cefSjmcneill bus_space_write_4(bst, cbus_bsh, MESON_CBUS_CPU_CLK_CNTL_REG, cpuclk); 39588499cefSjmcneill 39688499cefSjmcneill bus_space_write_4(bst, cpuconf_bsh, MESON8B_SRAM_CPUCONF_CPU_ADDR_REG(cpuno), 39788499cefSjmcneill KERN_VTOPHYS((vaddr_t)cpu_mpstart)); 39888499cefSjmcneill 39988499cefSjmcneill uint32_t ctrl = bus_space_read_4(bst, cpuconf_bsh, MESON8B_SRAM_CPUCONF_CTRL_REG); 40088499cefSjmcneill ctrl |= __BITS(cpuno,0); 40188499cefSjmcneill bus_space_write_4(bst, cpuconf_bsh, MESON8B_SRAM_CPUCONF_CTRL_REG, ctrl); 402*8e6b5205Srin #endif 40388499cefSjmcneill 40488499cefSjmcneill return 0; 40588499cefSjmcneill } 40688499cefSjmcneill 40788499cefSjmcneill ARM_CPU_METHOD(meson8b, "amlogic,meson8b-smp", cpu_enable_meson8b); 40888499cefSjmcneill 409679fad90Sskrll static int 41082a9c324Sjmcneill meson8b_mpstart(void) 41188499cefSjmcneill { 412679fad90Sskrll int ret = 0; 41388499cefSjmcneill const bus_addr_t cbar = armreg_cbar_read(); 41488499cefSjmcneill bus_space_tag_t bst = &arm_generic_bs_tag; 41588499cefSjmcneill 41688499cefSjmcneill if (cbar == 0) 417679fad90Sskrll return ret; 41888499cefSjmcneill 41988499cefSjmcneill const bus_space_handle_t scu_bsh = 42088499cefSjmcneill cbar - MESON8B_ARM_PBASE + MESON8B_ARM_VBASE; 42188499cefSjmcneill 42288499cefSjmcneill const uint32_t scu_cfg = bus_space_read_4(bst, scu_bsh, SCU_CFG); 42388499cefSjmcneill const u_int ncpus = (scu_cfg & SCU_CFG_CPUMAX) + 1; 42488499cefSjmcneill 42588499cefSjmcneill if (ncpus < 2) 426679fad90Sskrll return ret; 42788499cefSjmcneill 42888499cefSjmcneill /* 42988499cefSjmcneill * Invalidate all SCU cache tags. That is, for all cores (0-3) 43088499cefSjmcneill */ 43188499cefSjmcneill bus_space_write_4(bst, scu_bsh, SCU_INV_ALL_REG, 0xffff); 43288499cefSjmcneill 43388499cefSjmcneill uint32_t scu_ctl = bus_space_read_4(bst, scu_bsh, SCU_CTL); 43488499cefSjmcneill scu_ctl |= SCU_CTL_SCU_ENA; 43588499cefSjmcneill bus_space_write_4(bst, scu_bsh, SCU_CTL, scu_ctl); 43688499cefSjmcneill 43788499cefSjmcneill armv7_dcache_wbinv_all(); 43888499cefSjmcneill 439679fad90Sskrll ret = arm_fdt_cpu_mpstart(); 440679fad90Sskrll return ret; 44188499cefSjmcneill } 44288499cefSjmcneill 44388499cefSjmcneill static const struct arm_platform meson8b_platform = { 4440eec6d7cSjmcneill .ap_devmap = meson_platform_devmap, 44588499cefSjmcneill .ap_bootstrap = meson8b_platform_bootstrap, 44688499cefSjmcneill .ap_init_attach_args = meson_platform_init_attach_args, 447d52edb14Sjmcneill .ap_device_register = meson8b_platform_device_register, 4480eec6d7cSjmcneill .ap_reset = meson8b_platform_reset, 449f0d94fb3Sskrll .ap_delay = a9ptmr_delay, 45088499cefSjmcneill .ap_uart_freq = meson_platform_uart_freq, 45182a9c324Sjmcneill .ap_mpstart = meson8b_mpstart, 45288499cefSjmcneill }; 45388499cefSjmcneill 45488499cefSjmcneill ARM_PLATFORM(meson8b, "amlogic,meson8b", &meson8b_platform); 45582a9c324Sjmcneill #endif /* SOC_MESON8B */ 45682a9c324Sjmcneill 457838e36f6Sjmcneill #if defined(SOC_MESONGX) 458f0949908Sjmcneill static void 459f0949908Sjmcneill mesongx_platform_reset(void) 460f0949908Sjmcneill { 461f0949908Sjmcneill bus_space_tag_t bst = &meson_bs_tag; 462f0949908Sjmcneill bus_space_handle_t bsh; 463f0949908Sjmcneill uint32_t val; 464f0949908Sjmcneill 465f0949908Sjmcneill bus_space_map(bst, MESONGX_WATCHDOG_BASE, MESONGX_WATCHDOG_SIZE, 0, &bsh); 466f0949908Sjmcneill 46732461851Sjmcneill val = MESONGX_WATCHDOG_CNTL_SYS_RESET_N_EN | 46832461851Sjmcneill MESONGX_WATCHDOG_CNTL_WDOG_EN | 46932461851Sjmcneill MESONGX_WATCHDOG_CNTL_CLK_EN; 470f0949908Sjmcneill bus_space_write_4(bst, bsh, MESONGX_WATCHDOG_CNTL, val); 471f0949908Sjmcneill 472f0949908Sjmcneill bus_space_write_4(bst, bsh, MESONGX_WATCHDOG_TCNT, 1); 473f0949908Sjmcneill 474f0949908Sjmcneill bus_space_write_4(bst, bsh, MESONGX_WATCHDOG_RESET, 0); 475f0949908Sjmcneill 476f0949908Sjmcneill for (;;) { 477f0949908Sjmcneill __asm("wfi"); 478f0949908Sjmcneill } 479f0949908Sjmcneill } 480f0949908Sjmcneill 481838e36f6Sjmcneill static const struct arm_platform mesongx_platform = { 48282a9c324Sjmcneill .ap_devmap = meson_platform_devmap, 48382a9c324Sjmcneill .ap_bootstrap = meson_platform_bootstrap, 48482a9c324Sjmcneill .ap_init_attach_args = meson_platform_init_attach_args, 48582a9c324Sjmcneill .ap_device_register = meson_platform_device_register, 486f0949908Sjmcneill .ap_reset = mesongx_platform_reset, 48782a9c324Sjmcneill .ap_delay = gtmr_delay, 48882a9c324Sjmcneill .ap_uart_freq = meson_platform_uart_freq, 48982a9c324Sjmcneill .ap_mpstart = arm_fdt_cpu_mpstart, 49082a9c324Sjmcneill }; 49182a9c324Sjmcneill 492838e36f6Sjmcneill #if defined(SOC_MESONGXBB) 493838e36f6Sjmcneill ARM_PLATFORM(mesongxbb, "amlogic,meson-gxbb", &mesongx_platform); 494838e36f6Sjmcneill #endif /* SOC_MESONGXBB */ 495838e36f6Sjmcneill #if defined(SOC_MESONGXL) 496838e36f6Sjmcneill ARM_PLATFORM(mesongxl, "amlogic,meson-gxl", &mesongx_platform); 497838e36f6Sjmcneill #endif /* SOC_MESONGXL */ 498838e36f6Sjmcneill #endif /* SOC_MESONGX */ 499