1*e7fbe403Sjmcneill /* $NetBSD: tegra_platform.c,v 1.20 2019/01/03 12:52:40 jmcneill Exp $ */ 2a7aa900aSjmcneill 3a7aa900aSjmcneill /*- 4a7aa900aSjmcneill * Copyright (c) 2017 Jared D. McNeill <jmcneill@invisible.ca> 5a7aa900aSjmcneill * All rights reserved. 6a7aa900aSjmcneill * 7a7aa900aSjmcneill * Redistribution and use in source and binary forms, with or without 8a7aa900aSjmcneill * modification, are permitted provided that the following conditions 9a7aa900aSjmcneill * are met: 10a7aa900aSjmcneill * 1. Redistributions of source code must retain the above copyright 11a7aa900aSjmcneill * notice, this list of conditions and the following disclaimer. 12a7aa900aSjmcneill * 2. Redistributions in binary form must reproduce the above copyright 13a7aa900aSjmcneill * notice, this list of conditions and the following disclaimer in the 14a7aa900aSjmcneill * documentation and/or other materials provided with the distribution. 15a7aa900aSjmcneill * 16a7aa900aSjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17a7aa900aSjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18a7aa900aSjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19a7aa900aSjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20a7aa900aSjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21a7aa900aSjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22a7aa900aSjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23a7aa900aSjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24a7aa900aSjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25a7aa900aSjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26a7aa900aSjmcneill * SUCH DAMAGE. 27a7aa900aSjmcneill */ 28a7aa900aSjmcneill 29e4a950e6Sskrll #include "opt_arm_debug.h" 3059508e8aSskrll #include "opt_console.h" 31e4a950e6Sskrll #include "opt_multiprocessor.h" 32e4a950e6Sskrll #include "opt_tegra.h" 33a7aa900aSjmcneill 34a7aa900aSjmcneill #include "ukbd.h" 35a7aa900aSjmcneill 36a7aa900aSjmcneill #include <sys/cdefs.h> 37*e7fbe403Sjmcneill __KERNEL_RCSID(0, "$NetBSD: tegra_platform.c,v 1.20 2019/01/03 12:52:40 jmcneill Exp $"); 38a7aa900aSjmcneill 39a7aa900aSjmcneill #include <sys/param.h> 40a7aa900aSjmcneill #include <sys/bus.h> 41a7aa900aSjmcneill #include <sys/cpu.h> 42a7aa900aSjmcneill #include <sys/device.h> 43a7aa900aSjmcneill #include <sys/termios.h> 44a7aa900aSjmcneill 45a7aa900aSjmcneill #include <dev/fdt/fdtvar.h> 46a7aa900aSjmcneill 47a7aa900aSjmcneill #include <uvm/uvm_extern.h> 48a7aa900aSjmcneill 49a7aa900aSjmcneill #include <machine/bootconfig.h> 50a7aa900aSjmcneill #include <arm/cpufunc.h> 51a7aa900aSjmcneill 52a7aa900aSjmcneill #include <arm/nvidia/tegra_reg.h> 53a7aa900aSjmcneill #include <arm/nvidia/tegra_var.h> 548694f07cSryo #include <arm/nvidia/tegra_platform.h> 55a7aa900aSjmcneill 5679b9098aSjmcneill #include <arm/fdt/arm_fdtvar.h> 57a7aa900aSjmcneill 5856ba9c3dSjmcneill #include <arm/arm/psci.h> 590102a965Sryo #include <arm/fdt/psci_fdtvar.h> 6056ba9c3dSjmcneill 61a7aa900aSjmcneill #if NUKBD > 0 62a7aa900aSjmcneill #include <dev/usb/ukbdvar.h> 63a7aa900aSjmcneill #endif 64a7aa900aSjmcneill 6513d8fe7bSjmcneill #include <dev/ic/ns16550reg.h> 6613d8fe7bSjmcneill #include <dev/ic/comreg.h> 6713d8fe7bSjmcneill 6845b0a61fSjmcneill #define PLLP_OUT0_FREQ 408000000 6945b0a61fSjmcneill 708694f07cSryo void tegra_platform_early_putchar(char); 718694f07cSryo 72763b86b6Sskrll void 73763b86b6Sskrll tegra_platform_early_putchar(char c) 74763b86b6Sskrll { 75763b86b6Sskrll #ifdef CONSADDR 76763b86b6Sskrll #define CONSADDR_VA (CONSADDR - TEGRA_APB_BASE + TEGRA_APB_VBASE) 77763b86b6Sskrll 78763b86b6Sskrll volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ? 79763b86b6Sskrll (volatile uint32_t *)CONSADDR_VA : 80763b86b6Sskrll (volatile uint32_t *)CONSADDR; 81763b86b6Sskrll 82763b86b6Sskrll while ((uartaddr[com_lsr] & LSR_TXRDY) == 0) 83763b86b6Sskrll ; 84763b86b6Sskrll 85763b86b6Sskrll uartaddr[com_data] = c; 86763b86b6Sskrll #endif 87763b86b6Sskrll } 88763b86b6Sskrll 89a7aa900aSjmcneill static const struct pmap_devmap * 90a7aa900aSjmcneill tegra_platform_devmap(void) 91a7aa900aSjmcneill { 92a7aa900aSjmcneill static const struct pmap_devmap devmap[] = { 93a7aa900aSjmcneill DEVMAP_ENTRY(TEGRA_HOST1X_VBASE, 94a7aa900aSjmcneill TEGRA_HOST1X_BASE, 95a7aa900aSjmcneill TEGRA_HOST1X_SIZE), 96a7aa900aSjmcneill DEVMAP_ENTRY(TEGRA_PPSB_VBASE, 97a7aa900aSjmcneill TEGRA_PPSB_BASE, 98a7aa900aSjmcneill TEGRA_PPSB_SIZE), 99a7aa900aSjmcneill DEVMAP_ENTRY(TEGRA_APB_VBASE, 100a7aa900aSjmcneill TEGRA_APB_BASE, 101a7aa900aSjmcneill TEGRA_APB_SIZE), 102a7aa900aSjmcneill DEVMAP_ENTRY(TEGRA_AHB_A2_VBASE, 103a7aa900aSjmcneill TEGRA_AHB_A2_BASE, 104a7aa900aSjmcneill TEGRA_AHB_A2_SIZE), 105a7aa900aSjmcneill DEVMAP_ENTRY_END 106a7aa900aSjmcneill }; 107a7aa900aSjmcneill 108a7aa900aSjmcneill return devmap; 109a7aa900aSjmcneill } 110a7aa900aSjmcneill 111e4a950e6Sskrll #if defined(SOC_TEGRA124) 112a7aa900aSjmcneill static void 1132f0a559aSjmcneill tegra124_platform_bootstrap(void) 114a7aa900aSjmcneill { 1158694f07cSryo #ifdef MULTIPROCESSOR 116e4a950e6Sskrll arm_cpu_max = 1 + __SHIFTOUT(armreg_l2ctrl_read(), L2CTRL_NUMCPU); 1178694f07cSryo #endif 118e4a950e6Sskrll 119e4a950e6Sskrll tegra_bootstrap(); 1202f0a559aSjmcneill } 12156ba9c3dSjmcneill #endif 1222f0a559aSjmcneill 123e4a950e6Sskrll #if defined(SOC_TEGRA210) 1242f0a559aSjmcneill static void 1252f0a559aSjmcneill tegra210_platform_bootstrap(void) 1262f0a559aSjmcneill { 127e4a950e6Sskrll 1282f0a559aSjmcneill tegra_bootstrap(); 1296ae27e98Sjmcneill 1306ae27e98Sjmcneill #if defined(MULTIPROCESSOR) && defined(__aarch64__) 1316ae27e98Sjmcneill arm_fdt_cpu_bootstrap(); 1326ae27e98Sjmcneill #endif 133e4a950e6Sskrll } 13456ba9c3dSjmcneill #endif 135a7aa900aSjmcneill 136a7aa900aSjmcneill static void 1375c283536Sjmcneill tegra_platform_init_attach_args(struct fdt_attach_args *faa) 1385c283536Sjmcneill { 1398694f07cSryo extern struct bus_space arm_generic_bs_tag; 1408694f07cSryo extern struct bus_space arm_generic_a4x_bs_tag; 1412e1981a2Sryo extern struct arm32_bus_dma_tag arm_generic_dma_tag; 1425c283536Sjmcneill 1438694f07cSryo faa->faa_bst = &arm_generic_bs_tag; 1448694f07cSryo faa->faa_a4x_bst = &arm_generic_a4x_bs_tag; 1452e1981a2Sryo faa->faa_dmat = &arm_generic_dma_tag; 1465c283536Sjmcneill } 1475c283536Sjmcneill 148a7aa900aSjmcneill static void 149a7aa900aSjmcneill tegra_platform_device_register(device_t self, void *aux) 150a7aa900aSjmcneill { 151a7aa900aSjmcneill prop_dictionary_t dict = device_properties(self); 152a7aa900aSjmcneill 153a7aa900aSjmcneill if (device_is_a(self, "tegrafb") && 154a7aa900aSjmcneill match_bootconf_option(boot_args, "console", "fb")) { 155a7aa900aSjmcneill prop_dictionary_set_bool(dict, "is_console", true); 156a7aa900aSjmcneill #if NUKBD > 0 157a7aa900aSjmcneill ukbd_cnattach(); 158a7aa900aSjmcneill #endif 159a7aa900aSjmcneill } 160a7aa900aSjmcneill 161a7aa900aSjmcneill if (device_is_a(self, "tegradrm")) { 162a7aa900aSjmcneill const char *video = get_bootconf_string(boot_args, "video"); 163a7aa900aSjmcneill if (video) 164a7aa900aSjmcneill prop_dictionary_set_cstring(dict, "HDMI-A-1", video); 165a7aa900aSjmcneill if (match_bootconf_option(boot_args, "hdmi.forcemode", "dvi")) 166a7aa900aSjmcneill prop_dictionary_set_bool(dict, "force-dvi", true); 167a7aa900aSjmcneill } 168a7aa900aSjmcneill 169a7aa900aSjmcneill if (device_is_a(self, "tegracec")) 170a7aa900aSjmcneill prop_dictionary_set_cstring(dict, "hdmi-device", "tegradrm0"); 171a7aa900aSjmcneill 172a7aa900aSjmcneill if (device_is_a(self, "nouveau")) { 173a7aa900aSjmcneill const char *config = get_bootconf_string(boot_args, 174a7aa900aSjmcneill "nouveau.config"); 175a7aa900aSjmcneill if (config) 176a7aa900aSjmcneill prop_dictionary_set_cstring(dict, "config", config); 177a7aa900aSjmcneill const char *debug = get_bootconf_string(boot_args, 178a7aa900aSjmcneill "nouveau.debug"); 179a7aa900aSjmcneill if (debug) 180a7aa900aSjmcneill prop_dictionary_set_cstring(dict, "debug", debug); 181a7aa900aSjmcneill } 182a7aa900aSjmcneill 183a7aa900aSjmcneill if (device_is_a(self, "tegrapcie")) { 184a7aa900aSjmcneill const char * const jetsontk1_compat[] = { 185a7aa900aSjmcneill "nvidia,jetson-tk1", NULL 186a7aa900aSjmcneill }; 187a7aa900aSjmcneill const int phandle = OF_peer(0); 188a7aa900aSjmcneill if (of_match_compatible(phandle, jetsontk1_compat)) { 189a7aa900aSjmcneill /* rfkill GPIO at GPIO X7 */ 190a7aa900aSjmcneill struct tegra_gpio_pin *pin = 191a7aa900aSjmcneill tegra_gpio_acquire("X7", GPIO_PIN_OUTPUT); 192a7aa900aSjmcneill if (pin) 193a7aa900aSjmcneill tegra_gpio_write(pin, 1); 194a7aa900aSjmcneill } 195a7aa900aSjmcneill } 196a7aa900aSjmcneill } 197a7aa900aSjmcneill 198a7aa900aSjmcneill static void 199a7aa900aSjmcneill tegra_platform_reset(void) 200a7aa900aSjmcneill { 201a7aa900aSjmcneill tegra_pmc_reset(); 202a7aa900aSjmcneill } 203a7aa900aSjmcneill 2048702feb1Sjmcneill static void 2058702feb1Sjmcneill tegra_platform_delay(u_int us) 2068702feb1Sjmcneill { 2078702feb1Sjmcneill tegra_timer_delay(us); 2088702feb1Sjmcneill } 2098702feb1Sjmcneill 21045b0a61fSjmcneill static u_int 21145b0a61fSjmcneill tegra_platform_uart_freq(void) 21245b0a61fSjmcneill { 21345b0a61fSjmcneill return PLLP_OUT0_FREQ; 21445b0a61fSjmcneill } 21545b0a61fSjmcneill 216e4a950e6Sskrll #if defined(SOC_TEGRA124) 2172f0a559aSjmcneill static const struct arm_platform tegra124_platform = { 218107aadd0Sskrll .ap_devmap = tegra_platform_devmap, 219107aadd0Sskrll .ap_bootstrap = tegra124_platform_bootstrap, 220107aadd0Sskrll .ap_init_attach_args = tegra_platform_init_attach_args, 221107aadd0Sskrll .ap_device_register = tegra_platform_device_register, 222107aadd0Sskrll .ap_reset = tegra_platform_reset, 223107aadd0Sskrll .ap_delay = tegra_platform_delay, 224107aadd0Sskrll .ap_uart_freq = tegra_platform_uart_freq, 225e4a950e6Sskrll .ap_mpstart = tegra124_mpstart, 226a7aa900aSjmcneill }; 227a7aa900aSjmcneill 2282f0a559aSjmcneill ARM_PLATFORM(tegra124, "nvidia,tegra124", &tegra124_platform); 22956ba9c3dSjmcneill #endif 2302f0a559aSjmcneill 231e4a950e6Sskrll #if defined(SOC_TEGRA210) 2322f0a559aSjmcneill static const struct arm_platform tegra210_platform = { 233107aadd0Sskrll .ap_devmap = tegra_platform_devmap, 234107aadd0Sskrll .ap_bootstrap = tegra210_platform_bootstrap, 235107aadd0Sskrll .ap_init_attach_args = tegra_platform_init_attach_args, 236107aadd0Sskrll .ap_device_register = tegra_platform_device_register, 237107aadd0Sskrll .ap_reset = tegra_platform_reset, 238107aadd0Sskrll .ap_delay = tegra_platform_delay, 239107aadd0Sskrll .ap_uart_freq = tegra_platform_uart_freq, 240*e7fbe403Sjmcneill .ap_mpstart = arm_fdt_cpu_mpstart, 2412f0a559aSjmcneill }; 2422f0a559aSjmcneill 2432f0a559aSjmcneill ARM_PLATFORM(tegra210, "nvidia,tegra210", &tegra210_platform); 24456ba9c3dSjmcneill #endif 245