1*8d564c5dSskrll /* $NetBSD: tegra_platform.c,v 1.28 2023/04/07 08:55:30 skrll Exp $ */
281bc83c1Sjmcneill
381bc83c1Sjmcneill /*-
481bc83c1Sjmcneill * Copyright (c) 2017 Jared D. McNeill <jmcneill@invisible.ca>
581bc83c1Sjmcneill * All rights reserved.
681bc83c1Sjmcneill *
781bc83c1Sjmcneill * Redistribution and use in source and binary forms, with or without
881bc83c1Sjmcneill * modification, are permitted provided that the following conditions
981bc83c1Sjmcneill * are met:
1081bc83c1Sjmcneill * 1. Redistributions of source code must retain the above copyright
1181bc83c1Sjmcneill * notice, this list of conditions and the following disclaimer.
1281bc83c1Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright
1381bc83c1Sjmcneill * notice, this list of conditions and the following disclaimer in the
1481bc83c1Sjmcneill * documentation and/or other materials provided with the distribution.
1581bc83c1Sjmcneill *
1681bc83c1Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1781bc83c1Sjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1881bc83c1Sjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1981bc83c1Sjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2081bc83c1Sjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2181bc83c1Sjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2281bc83c1Sjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2381bc83c1Sjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2481bc83c1Sjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2581bc83c1Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2681bc83c1Sjmcneill * SUCH DAMAGE.
2781bc83c1Sjmcneill */
2881bc83c1Sjmcneill
29e6c2e807Sskrll #include "opt_arm_debug.h"
305a821b2cSskrll #include "opt_console.h"
31e6c2e807Sskrll #include "opt_multiprocessor.h"
32e6c2e807Sskrll #include "opt_tegra.h"
3381bc83c1Sjmcneill
3481bc83c1Sjmcneill #include "ukbd.h"
3581bc83c1Sjmcneill
3681bc83c1Sjmcneill #include <sys/cdefs.h>
37*8d564c5dSskrll __KERNEL_RCSID(0, "$NetBSD: tegra_platform.c,v 1.28 2023/04/07 08:55:30 skrll Exp $");
3881bc83c1Sjmcneill
3981bc83c1Sjmcneill #include <sys/param.h>
4081bc83c1Sjmcneill #include <sys/bus.h>
4181bc83c1Sjmcneill #include <sys/cpu.h>
4281bc83c1Sjmcneill #include <sys/device.h>
4381bc83c1Sjmcneill #include <sys/termios.h>
4481bc83c1Sjmcneill
4581bc83c1Sjmcneill #include <dev/fdt/fdtvar.h>
4681bc83c1Sjmcneill
4781bc83c1Sjmcneill #include <uvm/uvm_extern.h>
4881bc83c1Sjmcneill
4981bc83c1Sjmcneill #include <machine/bootconfig.h>
5081bc83c1Sjmcneill #include <arm/cpufunc.h>
5181bc83c1Sjmcneill
5281bc83c1Sjmcneill #include <arm/nvidia/tegra_reg.h>
5381bc83c1Sjmcneill #include <arm/nvidia/tegra_var.h>
54fe33aa27Sryo #include <arm/nvidia/tegra_platform.h>
5581bc83c1Sjmcneill
568f0ac464Sjmcneill #include <arm/fdt/arm_fdtvar.h>
5781bc83c1Sjmcneill
58341b0570Sjmcneill #include <arm/arm/psci.h>
5966d31a2dSryo #include <arm/fdt/psci_fdtvar.h>
60341b0570Sjmcneill
6181bc83c1Sjmcneill #if NUKBD > 0
6281bc83c1Sjmcneill #include <dev/usb/ukbdvar.h>
6381bc83c1Sjmcneill #endif
6481bc83c1Sjmcneill
65309390f0Sjmcneill #include <dev/ic/ns16550reg.h>
66309390f0Sjmcneill #include <dev/ic/comreg.h>
67309390f0Sjmcneill
68faf8273eSjmcneill #define PLLP_OUT0_FREQ 408000000
69faf8273eSjmcneill
70fe33aa27Sryo void tegra_platform_early_putchar(char);
71fe33aa27Sryo
72d329adb0Sskrll void __noasan
tegra_platform_early_putchar(char c)73d9031769Sskrll tegra_platform_early_putchar(char c)
74d9031769Sskrll {
75d9031769Sskrll #ifdef CONSADDR
76d9031769Sskrll #define CONSADDR_VA (CONSADDR - TEGRA_APB_BASE + TEGRA_APB_VBASE)
77d9031769Sskrll
78d9031769Sskrll volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ?
79d9031769Sskrll (volatile uint32_t *)CONSADDR_VA :
80d9031769Sskrll (volatile uint32_t *)CONSADDR;
81d9031769Sskrll
82d9031769Sskrll while ((uartaddr[com_lsr] & LSR_TXRDY) == 0)
83d9031769Sskrll ;
84d9031769Sskrll
85d9031769Sskrll uartaddr[com_data] = c;
86d9031769Sskrll #endif
87d9031769Sskrll }
88d9031769Sskrll
8914c88e89Suwe #if defined(SOC_TEGRA124) || defined(SOC_TEGRA210)
9081bc83c1Sjmcneill static const struct pmap_devmap *
tegra_platform_devmap(void)9181bc83c1Sjmcneill tegra_platform_devmap(void)
9281bc83c1Sjmcneill {
9381bc83c1Sjmcneill static const struct pmap_devmap devmap[] = {
9481bc83c1Sjmcneill DEVMAP_ENTRY(TEGRA_HOST1X_VBASE,
9581bc83c1Sjmcneill TEGRA_HOST1X_BASE,
9681bc83c1Sjmcneill TEGRA_HOST1X_SIZE),
9781bc83c1Sjmcneill DEVMAP_ENTRY(TEGRA_PPSB_VBASE,
9881bc83c1Sjmcneill TEGRA_PPSB_BASE,
9981bc83c1Sjmcneill TEGRA_PPSB_SIZE),
10081bc83c1Sjmcneill DEVMAP_ENTRY(TEGRA_APB_VBASE,
10181bc83c1Sjmcneill TEGRA_APB_BASE,
10281bc83c1Sjmcneill TEGRA_APB_SIZE),
10381bc83c1Sjmcneill DEVMAP_ENTRY(TEGRA_AHB_A2_VBASE,
10481bc83c1Sjmcneill TEGRA_AHB_A2_BASE,
10581bc83c1Sjmcneill TEGRA_AHB_A2_SIZE),
10681bc83c1Sjmcneill DEVMAP_ENTRY_END
10781bc83c1Sjmcneill };
10881bc83c1Sjmcneill
10981bc83c1Sjmcneill return devmap;
11081bc83c1Sjmcneill }
11114c88e89Suwe #endif /* SOC_TEGRA124 || SOC_TEGRA210 */
11281bc83c1Sjmcneill
113e6c2e807Sskrll #if defined(SOC_TEGRA124)
11481bc83c1Sjmcneill static void
tegra124_platform_bootstrap(void)11597edf79bSjmcneill tegra124_platform_bootstrap(void)
11681bc83c1Sjmcneill {
117fe33aa27Sryo #ifdef MULTIPROCESSOR
118e6c2e807Sskrll arm_cpu_max = 1 + __SHIFTOUT(armreg_l2ctrl_read(), L2CTRL_NUMCPU);
119fe33aa27Sryo #endif
120e6c2e807Sskrll
121e6c2e807Sskrll tegra_bootstrap();
12297edf79bSjmcneill }
123341b0570Sjmcneill #endif
12497edf79bSjmcneill
125e6c2e807Sskrll #if defined(SOC_TEGRA210)
12697edf79bSjmcneill static void
tegra210_platform_bootstrap(void)12797edf79bSjmcneill tegra210_platform_bootstrap(void)
12897edf79bSjmcneill {
129e6c2e807Sskrll
13097edf79bSjmcneill tegra_bootstrap();
131d48bf867Sjmcneill
132d48bf867Sjmcneill #if defined(MULTIPROCESSOR) && defined(__aarch64__)
133d48bf867Sjmcneill arm_fdt_cpu_bootstrap();
134d48bf867Sjmcneill #endif
135e6c2e807Sskrll }
136341b0570Sjmcneill #endif
13781bc83c1Sjmcneill
13814c88e89Suwe #if defined(SOC_TEGRA124) || defined(SOC_TEGRA210)
13981bc83c1Sjmcneill static void
tegra_platform_init_attach_args(struct fdt_attach_args * faa)14073b64c76Sjmcneill tegra_platform_init_attach_args(struct fdt_attach_args *faa)
14173b64c76Sjmcneill {
142fe33aa27Sryo extern struct bus_space arm_generic_bs_tag;
143eabbe28cSryo extern struct arm32_bus_dma_tag arm_generic_dma_tag;
14473b64c76Sjmcneill
145fe33aa27Sryo faa->faa_bst = &arm_generic_bs_tag;
146eabbe28cSryo faa->faa_dmat = &arm_generic_dma_tag;
14773b64c76Sjmcneill }
14873b64c76Sjmcneill
14981bc83c1Sjmcneill static void
tegra_platform_device_register(device_t self,void * aux)15081bc83c1Sjmcneill tegra_platform_device_register(device_t self, void *aux)
15181bc83c1Sjmcneill {
15281bc83c1Sjmcneill prop_dictionary_t dict = device_properties(self);
15381bc83c1Sjmcneill
15481bc83c1Sjmcneill if (device_is_a(self, "tegrafb") &&
15581bc83c1Sjmcneill match_bootconf_option(boot_args, "console", "fb")) {
15681bc83c1Sjmcneill prop_dictionary_set_bool(dict, "is_console", true);
15781bc83c1Sjmcneill #if NUKBD > 0
15881bc83c1Sjmcneill ukbd_cnattach();
15981bc83c1Sjmcneill #endif
16081bc83c1Sjmcneill }
16181bc83c1Sjmcneill
16281bc83c1Sjmcneill if (device_is_a(self, "tegradrm")) {
16381bc83c1Sjmcneill const char *video = get_bootconf_string(boot_args, "video");
16481bc83c1Sjmcneill if (video)
165d958cb46Sskrll prop_dictionary_set_string(dict, "HDMI-A-1", video);
16681bc83c1Sjmcneill if (match_bootconf_option(boot_args, "hdmi.forcemode", "dvi"))
16781bc83c1Sjmcneill prop_dictionary_set_bool(dict, "force-dvi", true);
16881bc83c1Sjmcneill }
16981bc83c1Sjmcneill
17081bc83c1Sjmcneill if (device_is_a(self, "tegracec"))
171d958cb46Sskrll prop_dictionary_set_string(dict, "hdmi-device", "tegradrm0");
17281bc83c1Sjmcneill
17381bc83c1Sjmcneill if (device_is_a(self, "nouveau")) {
17481bc83c1Sjmcneill const char *config = get_bootconf_string(boot_args,
17581bc83c1Sjmcneill "nouveau.config");
17681bc83c1Sjmcneill if (config)
177d958cb46Sskrll prop_dictionary_set_string(dict, "config", config);
17881bc83c1Sjmcneill const char *debug = get_bootconf_string(boot_args,
17981bc83c1Sjmcneill "nouveau.debug");
18081bc83c1Sjmcneill if (debug)
181d958cb46Sskrll prop_dictionary_set_string(dict, "debug", debug);
18281bc83c1Sjmcneill }
18381bc83c1Sjmcneill
18481bc83c1Sjmcneill if (device_is_a(self, "tegrapcie")) {
1856e54367aSthorpej static const struct device_compatible_entry jetsontk1[] = {
1866e54367aSthorpej { .compat = "nvidia,jetson-tk1" },
1876e54367aSthorpej DEVICE_COMPAT_EOL
18881bc83c1Sjmcneill };
18981bc83c1Sjmcneill const int phandle = OF_peer(0);
1906e54367aSthorpej if (of_compatible_match(phandle, jetsontk1)) {
19181bc83c1Sjmcneill /* rfkill GPIO at GPIO X7 */
19281bc83c1Sjmcneill struct tegra_gpio_pin *pin =
19381bc83c1Sjmcneill tegra_gpio_acquire("X7", GPIO_PIN_OUTPUT);
19481bc83c1Sjmcneill if (pin)
19581bc83c1Sjmcneill tegra_gpio_write(pin, 1);
19681bc83c1Sjmcneill }
19781bc83c1Sjmcneill }
19881bc83c1Sjmcneill }
19981bc83c1Sjmcneill
20081bc83c1Sjmcneill static void
tegra_platform_reset(void)20181bc83c1Sjmcneill tegra_platform_reset(void)
20281bc83c1Sjmcneill {
20381bc83c1Sjmcneill tegra_pmc_reset();
20481bc83c1Sjmcneill }
20581bc83c1Sjmcneill
2062a1124acSjmcneill static void
tegra_platform_delay(u_int us)2072a1124acSjmcneill tegra_platform_delay(u_int us)
2082a1124acSjmcneill {
2092a1124acSjmcneill tegra_timer_delay(us);
2102a1124acSjmcneill }
2112a1124acSjmcneill
212faf8273eSjmcneill static u_int
tegra_platform_uart_freq(void)213faf8273eSjmcneill tegra_platform_uart_freq(void)
214faf8273eSjmcneill {
215faf8273eSjmcneill return PLLP_OUT0_FREQ;
216faf8273eSjmcneill }
21714c88e89Suwe #endif /* SOC_TEGRA124 || SOC_TEGRA210 */
218faf8273eSjmcneill
219e6c2e807Sskrll #if defined(SOC_TEGRA124)
220*8d564c5dSskrll static const struct fdt_platform tegra124_platform = {
221*8d564c5dSskrll .fp_devmap = tegra_platform_devmap,
222*8d564c5dSskrll .fp_bootstrap = tegra124_platform_bootstrap,
223*8d564c5dSskrll .fp_init_attach_args = tegra_platform_init_attach_args,
224*8d564c5dSskrll .fp_device_register = tegra_platform_device_register,
225*8d564c5dSskrll .fp_reset = tegra_platform_reset,
226*8d564c5dSskrll .fp_delay = tegra_platform_delay,
227*8d564c5dSskrll .fp_uart_freq = tegra_platform_uart_freq,
228*8d564c5dSskrll .fp_mpstart = tegra124_mpstart,
22981bc83c1Sjmcneill };
23081bc83c1Sjmcneill
231*8d564c5dSskrll FDT_PLATFORM(tegra124, "nvidia,tegra124", &tegra124_platform);
232341b0570Sjmcneill #endif
23397edf79bSjmcneill
234e6c2e807Sskrll #if defined(SOC_TEGRA210)
235*8d564c5dSskrll static const struct fdt_platform tegra210_platform = {
236*8d564c5dSskrll .fp_devmap = tegra_platform_devmap,
237*8d564c5dSskrll .fp_bootstrap = tegra210_platform_bootstrap,
238*8d564c5dSskrll .fp_init_attach_args = tegra_platform_init_attach_args,
239*8d564c5dSskrll .fp_device_register = tegra_platform_device_register,
240*8d564c5dSskrll .fp_reset = tegra_platform_reset,
241*8d564c5dSskrll .fp_delay = tegra_platform_delay,
242*8d564c5dSskrll .fp_uart_freq = tegra_platform_uart_freq,
243*8d564c5dSskrll .fp_mpstart = arm_fdt_cpu_mpstart,
24497edf79bSjmcneill };
24597edf79bSjmcneill
246*8d564c5dSskrll FDT_PLATFORM(tegra210, "nvidia,tegra210", &tegra210_platform);
247341b0570Sjmcneill #endif
248