xref: /netbsd/sys/arch/arm/nvidia/tegra_platform.c (revision e4a950e6)
1*e4a950e6Sskrll /* $NetBSD: tegra_platform.c,v 1.17 2018/10/18 09:01:53 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 
29*e4a950e6Sskrll #include "opt_arm_debug.h"
3059508e8aSskrll #include "opt_console.h"
31*e4a950e6Sskrll #include "opt_multiprocessor.h"
32*e4a950e6Sskrll #include "opt_tegra.h"
33a7aa900aSjmcneill 
34a7aa900aSjmcneill #include "ukbd.h"
35a7aa900aSjmcneill 
36a7aa900aSjmcneill #include <sys/cdefs.h>
37*e4a950e6Sskrll __KERNEL_RCSID(0, "$NetBSD: tegra_platform.c,v 1.17 2018/10/18 09:01:53 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 
72a7aa900aSjmcneill static const struct pmap_devmap *
73a7aa900aSjmcneill tegra_platform_devmap(void)
74a7aa900aSjmcneill {
75a7aa900aSjmcneill 	static const struct pmap_devmap devmap[] = {
76a7aa900aSjmcneill 		DEVMAP_ENTRY(TEGRA_HOST1X_VBASE,
77a7aa900aSjmcneill 			     TEGRA_HOST1X_BASE,
78a7aa900aSjmcneill 			     TEGRA_HOST1X_SIZE),
79a7aa900aSjmcneill 		DEVMAP_ENTRY(TEGRA_PPSB_VBASE,
80a7aa900aSjmcneill 			     TEGRA_PPSB_BASE,
81a7aa900aSjmcneill 			     TEGRA_PPSB_SIZE),
82a7aa900aSjmcneill 		DEVMAP_ENTRY(TEGRA_APB_VBASE,
83a7aa900aSjmcneill 			     TEGRA_APB_BASE,
84a7aa900aSjmcneill 			     TEGRA_APB_SIZE),
85a7aa900aSjmcneill 		DEVMAP_ENTRY(TEGRA_AHB_A2_VBASE,
86a7aa900aSjmcneill 			     TEGRA_AHB_A2_BASE,
87a7aa900aSjmcneill 			     TEGRA_AHB_A2_SIZE),
88a7aa900aSjmcneill 		DEVMAP_ENTRY_END
89a7aa900aSjmcneill 	};
90a7aa900aSjmcneill 
91a7aa900aSjmcneill 	return devmap;
92a7aa900aSjmcneill }
93a7aa900aSjmcneill 
94*e4a950e6Sskrll #if defined(SOC_TEGRA124)
95a7aa900aSjmcneill static void
962f0a559aSjmcneill tegra124_platform_bootstrap(void)
97a7aa900aSjmcneill {
988694f07cSryo #ifdef MULTIPROCESSOR
99*e4a950e6Sskrll 	arm_cpu_max = 1 + __SHIFTOUT(armreg_l2ctrl_read(), L2CTRL_NUMCPU);
1008694f07cSryo #endif
101*e4a950e6Sskrll 
102*e4a950e6Sskrll 	tegra_bootstrap();
1032f0a559aSjmcneill }
10456ba9c3dSjmcneill #endif
1052f0a559aSjmcneill 
106*e4a950e6Sskrll #if defined(SOC_TEGRA210)
1072f0a559aSjmcneill static void
1082f0a559aSjmcneill tegra210_platform_bootstrap(void)
1092f0a559aSjmcneill {
110*e4a950e6Sskrll 
1112f0a559aSjmcneill 	tegra_bootstrap();
112*e4a950e6Sskrll }
113*e4a950e6Sskrll 
114*e4a950e6Sskrll static void
115*e4a950e6Sskrll tegra210_platform_mpstart(void)
116*e4a950e6Sskrll {
1172f0a559aSjmcneill 
118c6e44b6bSjmcneill #if defined(MULTIPROCESSOR) && defined(__aarch64__)
1190102a965Sryo 	arm_fdt_cpu_bootstrap();
1208694f07cSryo #endif
121a7aa900aSjmcneill }
12256ba9c3dSjmcneill #endif
123a7aa900aSjmcneill 
124a7aa900aSjmcneill static void
1255c283536Sjmcneill tegra_platform_init_attach_args(struct fdt_attach_args *faa)
1265c283536Sjmcneill {
1278694f07cSryo 	extern struct bus_space arm_generic_bs_tag;
1288694f07cSryo 	extern struct bus_space arm_generic_a4x_bs_tag;
1292e1981a2Sryo 	extern struct arm32_bus_dma_tag arm_generic_dma_tag;
1305c283536Sjmcneill 
1318694f07cSryo 	faa->faa_bst = &arm_generic_bs_tag;
1328694f07cSryo 	faa->faa_a4x_bst = &arm_generic_a4x_bs_tag;
1332e1981a2Sryo 	faa->faa_dmat = &arm_generic_dma_tag;
1345c283536Sjmcneill }
1355c283536Sjmcneill 
1368694f07cSryo void
137a7aa900aSjmcneill tegra_platform_early_putchar(char c)
138a7aa900aSjmcneill {
139a7aa900aSjmcneill #ifdef CONSADDR
140a7aa900aSjmcneill #define CONSADDR_VA	(CONSADDR - TEGRA_APB_BASE + TEGRA_APB_VBASE)
1418694f07cSryo 
1428694f07cSryo 	volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ?
1438694f07cSryo 	    (volatile uint32_t *)CONSADDR_VA :
1448694f07cSryo 	    (volatile uint32_t *)CONSADDR;
145a7aa900aSjmcneill 
146a7aa900aSjmcneill 	while ((uartaddr[com_lsr] & LSR_TXRDY) == 0)
147a7aa900aSjmcneill 		;
148a7aa900aSjmcneill 
149a7aa900aSjmcneill 	uartaddr[com_data] = c;
150a7aa900aSjmcneill #endif
151a7aa900aSjmcneill }
152a7aa900aSjmcneill 
153a7aa900aSjmcneill static void
154a7aa900aSjmcneill tegra_platform_device_register(device_t self, void *aux)
155a7aa900aSjmcneill {
156a7aa900aSjmcneill 	prop_dictionary_t dict = device_properties(self);
157a7aa900aSjmcneill 
158a7aa900aSjmcneill 	if (device_is_a(self, "tegrafb") &&
159a7aa900aSjmcneill 	    match_bootconf_option(boot_args, "console", "fb")) {
160a7aa900aSjmcneill 		prop_dictionary_set_bool(dict, "is_console", true);
161a7aa900aSjmcneill #if NUKBD > 0
162a7aa900aSjmcneill 		ukbd_cnattach();
163a7aa900aSjmcneill #endif
164a7aa900aSjmcneill 	}
165a7aa900aSjmcneill 
166a7aa900aSjmcneill 	if (device_is_a(self, "tegradrm")) {
167a7aa900aSjmcneill 		const char *video = get_bootconf_string(boot_args, "video");
168a7aa900aSjmcneill 		if (video)
169a7aa900aSjmcneill 			prop_dictionary_set_cstring(dict, "HDMI-A-1", video);
170a7aa900aSjmcneill 		if (match_bootconf_option(boot_args, "hdmi.forcemode", "dvi"))
171a7aa900aSjmcneill 			prop_dictionary_set_bool(dict, "force-dvi", true);
172a7aa900aSjmcneill 	}
173a7aa900aSjmcneill 
174a7aa900aSjmcneill 	if (device_is_a(self, "tegracec"))
175a7aa900aSjmcneill 		prop_dictionary_set_cstring(dict, "hdmi-device", "tegradrm0");
176a7aa900aSjmcneill 
177a7aa900aSjmcneill 	if (device_is_a(self, "nouveau")) {
178a7aa900aSjmcneill 		const char *config = get_bootconf_string(boot_args,
179a7aa900aSjmcneill 		    "nouveau.config");
180a7aa900aSjmcneill 		if (config)
181a7aa900aSjmcneill 			prop_dictionary_set_cstring(dict, "config", config);
182a7aa900aSjmcneill 		const char *debug = get_bootconf_string(boot_args,
183a7aa900aSjmcneill 		    "nouveau.debug");
184a7aa900aSjmcneill 		if (debug)
185a7aa900aSjmcneill 			prop_dictionary_set_cstring(dict, "debug", debug);
186a7aa900aSjmcneill 	}
187a7aa900aSjmcneill 
188a7aa900aSjmcneill 	if (device_is_a(self, "tegrapcie")) {
189a7aa900aSjmcneill 		const char * const jetsontk1_compat[] = {
190a7aa900aSjmcneill 		    "nvidia,jetson-tk1", NULL
191a7aa900aSjmcneill 		};
192a7aa900aSjmcneill 		const int phandle = OF_peer(0);
193a7aa900aSjmcneill 		if (of_match_compatible(phandle, jetsontk1_compat)) {
194a7aa900aSjmcneill 			/* rfkill GPIO at GPIO X7 */
195a7aa900aSjmcneill 			struct tegra_gpio_pin *pin =
196a7aa900aSjmcneill 			    tegra_gpio_acquire("X7", GPIO_PIN_OUTPUT);
197a7aa900aSjmcneill 			if (pin)
198a7aa900aSjmcneill 				tegra_gpio_write(pin, 1);
199a7aa900aSjmcneill 		}
200a7aa900aSjmcneill 	}
201a7aa900aSjmcneill }
202a7aa900aSjmcneill 
203a7aa900aSjmcneill static void
204a7aa900aSjmcneill tegra_platform_reset(void)
205a7aa900aSjmcneill {
206a7aa900aSjmcneill 	tegra_pmc_reset();
207a7aa900aSjmcneill }
208a7aa900aSjmcneill 
2098702feb1Sjmcneill static void
2108702feb1Sjmcneill tegra_platform_delay(u_int us)
2118702feb1Sjmcneill {
2128702feb1Sjmcneill 	tegra_timer_delay(us);
2138702feb1Sjmcneill }
2148702feb1Sjmcneill 
21545b0a61fSjmcneill static u_int
21645b0a61fSjmcneill tegra_platform_uart_freq(void)
21745b0a61fSjmcneill {
21845b0a61fSjmcneill 	return PLLP_OUT0_FREQ;
21945b0a61fSjmcneill }
22045b0a61fSjmcneill 
221*e4a950e6Sskrll #if defined(SOC_TEGRA124)
2222f0a559aSjmcneill static const struct arm_platform tegra124_platform = {
223107aadd0Sskrll 	.ap_devmap = tegra_platform_devmap,
224107aadd0Sskrll 	.ap_bootstrap = tegra124_platform_bootstrap,
225107aadd0Sskrll 	.ap_init_attach_args = tegra_platform_init_attach_args,
226107aadd0Sskrll 	.ap_early_putchar = tegra_platform_early_putchar,
227107aadd0Sskrll 	.ap_device_register = tegra_platform_device_register,
228107aadd0Sskrll 	.ap_reset = tegra_platform_reset,
229107aadd0Sskrll 	.ap_delay = tegra_platform_delay,
230107aadd0Sskrll 	.ap_uart_freq = tegra_platform_uart_freq,
231*e4a950e6Sskrll 	.ap_mpstart = tegra124_mpstart,
232a7aa900aSjmcneill };
233a7aa900aSjmcneill 
2342f0a559aSjmcneill ARM_PLATFORM(tegra124, "nvidia,tegra124", &tegra124_platform);
23556ba9c3dSjmcneill #endif
2362f0a559aSjmcneill 
237*e4a950e6Sskrll #if defined(SOC_TEGRA210)
2382f0a559aSjmcneill static const struct arm_platform tegra210_platform = {
239107aadd0Sskrll 	.ap_devmap = tegra_platform_devmap,
240107aadd0Sskrll 	.ap_bootstrap = tegra210_platform_bootstrap,
241107aadd0Sskrll 	.ap_init_attach_args = tegra_platform_init_attach_args,
242107aadd0Sskrll 	.ap_early_putchar = tegra_platform_early_putchar,
243107aadd0Sskrll 	.ap_device_register = tegra_platform_device_register,
244107aadd0Sskrll 	.ap_reset = tegra_platform_reset,
245107aadd0Sskrll 	.ap_delay = tegra_platform_delay,
246107aadd0Sskrll 	.ap_uart_freq = tegra_platform_uart_freq,
247*e4a950e6Sskrll 	.ap_mpstart = tegra210_platform_mpstart,
2482f0a559aSjmcneill };
2492f0a559aSjmcneill 
2502f0a559aSjmcneill ARM_PLATFORM(tegra210, "nvidia,tegra210", &tegra210_platform);
25156ba9c3dSjmcneill #endif
252