xref: /netbsd/sys/arch/arm/nvidia/tegra_platform.c (revision 280931cc)
1*280931ccSskrll /* $NetBSD: tegra_platform.c,v 1.21 2020/06/20 15:48:19 skrll 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*280931ccSskrll __KERNEL_RCSID(0, "$NetBSD: tegra_platform.c,v 1.21 2020/06/20 15:48:19 skrll 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)
164*280931ccSskrll 			prop_dictionary_set_string(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"))
170*280931ccSskrll 		prop_dictionary_set_string(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)
176*280931ccSskrll 			prop_dictionary_set_string(dict, "config", config);
177a7aa900aSjmcneill 		const char *debug = get_bootconf_string(boot_args,
178a7aa900aSjmcneill 		    "nouveau.debug");
179a7aa900aSjmcneill 		if (debug)
180*280931ccSskrll 			prop_dictionary_set_string(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,
240e7fbe403Sjmcneill 	.ap_mpstart = arm_fdt_cpu_mpstart,
2412f0a559aSjmcneill };
2422f0a559aSjmcneill 
2432f0a559aSjmcneill ARM_PLATFORM(tegra210, "nvidia,tegra210", &tegra210_platform);
24456ba9c3dSjmcneill #endif
245