xref: /netbsd/sys/arch/arm/nvidia/tegra_platform.c (revision 0102a965)
1*0102a965Sryo /* $NetBSD: tegra_platform.c,v 1.15 2018/09/10 11:05:12 ryo 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 
29a7aa900aSjmcneill #include "opt_tegra.h"
30a7aa900aSjmcneill #include "opt_multiprocessor.h"
3113d8fe7bSjmcneill #include "opt_fdt_arm.h"
32a7aa900aSjmcneill 
33a7aa900aSjmcneill #include "ukbd.h"
34a7aa900aSjmcneill 
35a7aa900aSjmcneill #include <sys/cdefs.h>
36*0102a965Sryo __KERNEL_RCSID(0, "$NetBSD: tegra_platform.c,v 1.15 2018/09/10 11:05:12 ryo Exp $");
37a7aa900aSjmcneill 
38a7aa900aSjmcneill #include <sys/param.h>
39a7aa900aSjmcneill #include <sys/bus.h>
40a7aa900aSjmcneill #include <sys/cpu.h>
41a7aa900aSjmcneill #include <sys/device.h>
42a7aa900aSjmcneill #include <sys/termios.h>
43a7aa900aSjmcneill 
44a7aa900aSjmcneill #include <dev/fdt/fdtvar.h>
45a7aa900aSjmcneill 
46a7aa900aSjmcneill #include <uvm/uvm_extern.h>
47a7aa900aSjmcneill 
48a7aa900aSjmcneill #include <machine/bootconfig.h>
49a7aa900aSjmcneill #include <arm/cpufunc.h>
50a7aa900aSjmcneill 
51a7aa900aSjmcneill #include <arm/nvidia/tegra_reg.h>
52a7aa900aSjmcneill #include <arm/nvidia/tegra_var.h>
538694f07cSryo #include <arm/nvidia/tegra_platform.h>
54a7aa900aSjmcneill 
5579b9098aSjmcneill #include <arm/fdt/arm_fdtvar.h>
56a7aa900aSjmcneill 
5756ba9c3dSjmcneill #include <arm/arm/psci.h>
58*0102a965Sryo #include <arm/fdt/psci_fdtvar.h>
5956ba9c3dSjmcneill 
60a7aa900aSjmcneill #if NUKBD > 0
61a7aa900aSjmcneill #include <dev/usb/ukbdvar.h>
62a7aa900aSjmcneill #endif
63a7aa900aSjmcneill 
6413d8fe7bSjmcneill #include <dev/ic/ns16550reg.h>
6513d8fe7bSjmcneill #include <dev/ic/comreg.h>
6613d8fe7bSjmcneill 
6745b0a61fSjmcneill #define	PLLP_OUT0_FREQ	408000000
6845b0a61fSjmcneill 
698694f07cSryo void tegra_platform_early_putchar(char);
708694f07cSryo 
71a7aa900aSjmcneill static const struct pmap_devmap *
72a7aa900aSjmcneill tegra_platform_devmap(void)
73a7aa900aSjmcneill {
74a7aa900aSjmcneill 	static const struct pmap_devmap devmap[] = {
75a7aa900aSjmcneill 		DEVMAP_ENTRY(TEGRA_HOST1X_VBASE,
76a7aa900aSjmcneill 			     TEGRA_HOST1X_BASE,
77a7aa900aSjmcneill 			     TEGRA_HOST1X_SIZE),
78a7aa900aSjmcneill 		DEVMAP_ENTRY(TEGRA_PPSB_VBASE,
79a7aa900aSjmcneill 			     TEGRA_PPSB_BASE,
80a7aa900aSjmcneill 			     TEGRA_PPSB_SIZE),
81a7aa900aSjmcneill 		DEVMAP_ENTRY(TEGRA_APB_VBASE,
82a7aa900aSjmcneill 			     TEGRA_APB_BASE,
83a7aa900aSjmcneill 			     TEGRA_APB_SIZE),
84a7aa900aSjmcneill 		DEVMAP_ENTRY(TEGRA_AHB_A2_VBASE,
85a7aa900aSjmcneill 			     TEGRA_AHB_A2_BASE,
86a7aa900aSjmcneill 			     TEGRA_AHB_A2_SIZE),
87a7aa900aSjmcneill 		DEVMAP_ENTRY_END
88a7aa900aSjmcneill 	};
89a7aa900aSjmcneill 
90a7aa900aSjmcneill 	return devmap;
91a7aa900aSjmcneill }
92a7aa900aSjmcneill 
9356ba9c3dSjmcneill #ifdef SOC_TEGRA124
94a7aa900aSjmcneill static void
952f0a559aSjmcneill tegra124_platform_bootstrap(void)
96a7aa900aSjmcneill {
97a7aa900aSjmcneill 	tegra_bootstrap();
982f0a559aSjmcneill 
998694f07cSryo #ifdef MULTIPROCESSOR
1002f0a559aSjmcneill 	tegra124_mpinit();
1018694f07cSryo #endif
1022f0a559aSjmcneill }
10356ba9c3dSjmcneill #endif
1042f0a559aSjmcneill 
10556ba9c3dSjmcneill #ifdef SOC_TEGRA210
1062f0a559aSjmcneill static void
1072f0a559aSjmcneill tegra210_platform_bootstrap(void)
1082f0a559aSjmcneill {
1092f0a559aSjmcneill 	tegra_bootstrap();
1102f0a559aSjmcneill 
111c6e44b6bSjmcneill #if defined(MULTIPROCESSOR) && defined(__aarch64__)
112*0102a965Sryo 	arm_fdt_cpu_bootstrap();
1138694f07cSryo #endif
114a7aa900aSjmcneill }
11556ba9c3dSjmcneill #endif
116a7aa900aSjmcneill 
117a7aa900aSjmcneill static void
1185c283536Sjmcneill tegra_platform_init_attach_args(struct fdt_attach_args *faa)
1195c283536Sjmcneill {
1208694f07cSryo 	extern struct bus_space arm_generic_bs_tag;
1218694f07cSryo 	extern struct bus_space arm_generic_a4x_bs_tag;
1222e1981a2Sryo 	extern struct arm32_bus_dma_tag arm_generic_dma_tag;
1235c283536Sjmcneill 
1248694f07cSryo 	faa->faa_bst = &arm_generic_bs_tag;
1258694f07cSryo 	faa->faa_a4x_bst = &arm_generic_a4x_bs_tag;
1262e1981a2Sryo 	faa->faa_dmat = &arm_generic_dma_tag;
1275c283536Sjmcneill }
1285c283536Sjmcneill 
1298694f07cSryo void
130a7aa900aSjmcneill tegra_platform_early_putchar(char c)
131a7aa900aSjmcneill {
132a7aa900aSjmcneill #ifdef CONSADDR
133a7aa900aSjmcneill #define CONSADDR_VA	(CONSADDR - TEGRA_APB_BASE + TEGRA_APB_VBASE)
1348694f07cSryo 
1358694f07cSryo 	volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ?
1368694f07cSryo 	    (volatile uint32_t *)CONSADDR_VA :
1378694f07cSryo 	    (volatile uint32_t *)CONSADDR;
138a7aa900aSjmcneill 
139a7aa900aSjmcneill 	while ((uartaddr[com_lsr] & LSR_TXRDY) == 0)
140a7aa900aSjmcneill 		;
141a7aa900aSjmcneill 
142a7aa900aSjmcneill 	uartaddr[com_data] = c;
143a7aa900aSjmcneill #endif
144a7aa900aSjmcneill }
145a7aa900aSjmcneill 
146a7aa900aSjmcneill static void
147a7aa900aSjmcneill tegra_platform_device_register(device_t self, void *aux)
148a7aa900aSjmcneill {
149a7aa900aSjmcneill 	prop_dictionary_t dict = device_properties(self);
150a7aa900aSjmcneill 
151a7aa900aSjmcneill 	if (device_is_a(self, "tegrafb") &&
152a7aa900aSjmcneill 	    match_bootconf_option(boot_args, "console", "fb")) {
153a7aa900aSjmcneill 		prop_dictionary_set_bool(dict, "is_console", true);
154a7aa900aSjmcneill #if NUKBD > 0
155a7aa900aSjmcneill 		ukbd_cnattach();
156a7aa900aSjmcneill #endif
157a7aa900aSjmcneill 	}
158a7aa900aSjmcneill 
159a7aa900aSjmcneill 	if (device_is_a(self, "tegradrm")) {
160a7aa900aSjmcneill 		const char *video = get_bootconf_string(boot_args, "video");
161a7aa900aSjmcneill 		if (video)
162a7aa900aSjmcneill 			prop_dictionary_set_cstring(dict, "HDMI-A-1", video);
163a7aa900aSjmcneill 		if (match_bootconf_option(boot_args, "hdmi.forcemode", "dvi"))
164a7aa900aSjmcneill 			prop_dictionary_set_bool(dict, "force-dvi", true);
165a7aa900aSjmcneill 	}
166a7aa900aSjmcneill 
167a7aa900aSjmcneill 	if (device_is_a(self, "tegracec"))
168a7aa900aSjmcneill 		prop_dictionary_set_cstring(dict, "hdmi-device", "tegradrm0");
169a7aa900aSjmcneill 
170a7aa900aSjmcneill 	if (device_is_a(self, "nouveau")) {
171a7aa900aSjmcneill 		const char *config = get_bootconf_string(boot_args,
172a7aa900aSjmcneill 		    "nouveau.config");
173a7aa900aSjmcneill 		if (config)
174a7aa900aSjmcneill 			prop_dictionary_set_cstring(dict, "config", config);
175a7aa900aSjmcneill 		const char *debug = get_bootconf_string(boot_args,
176a7aa900aSjmcneill 		    "nouveau.debug");
177a7aa900aSjmcneill 		if (debug)
178a7aa900aSjmcneill 			prop_dictionary_set_cstring(dict, "debug", debug);
179a7aa900aSjmcneill 	}
180a7aa900aSjmcneill 
181a7aa900aSjmcneill 	if (device_is_a(self, "tegrapcie")) {
182a7aa900aSjmcneill 		const char * const jetsontk1_compat[] = {
183a7aa900aSjmcneill 		    "nvidia,jetson-tk1", NULL
184a7aa900aSjmcneill 		};
185a7aa900aSjmcneill 		const int phandle = OF_peer(0);
186a7aa900aSjmcneill 		if (of_match_compatible(phandle, jetsontk1_compat)) {
187a7aa900aSjmcneill 			/* rfkill GPIO at GPIO X7 */
188a7aa900aSjmcneill 			struct tegra_gpio_pin *pin =
189a7aa900aSjmcneill 			    tegra_gpio_acquire("X7", GPIO_PIN_OUTPUT);
190a7aa900aSjmcneill 			if (pin)
191a7aa900aSjmcneill 				tegra_gpio_write(pin, 1);
192a7aa900aSjmcneill 		}
193a7aa900aSjmcneill 	}
194a7aa900aSjmcneill }
195a7aa900aSjmcneill 
196a7aa900aSjmcneill static void
197a7aa900aSjmcneill tegra_platform_reset(void)
198a7aa900aSjmcneill {
199a7aa900aSjmcneill 	tegra_pmc_reset();
200a7aa900aSjmcneill }
201a7aa900aSjmcneill 
2028702feb1Sjmcneill static void
2038702feb1Sjmcneill tegra_platform_delay(u_int us)
2048702feb1Sjmcneill {
2058702feb1Sjmcneill 	tegra_timer_delay(us);
2068702feb1Sjmcneill }
2078702feb1Sjmcneill 
20845b0a61fSjmcneill static u_int
20945b0a61fSjmcneill tegra_platform_uart_freq(void)
21045b0a61fSjmcneill {
21145b0a61fSjmcneill 	return PLLP_OUT0_FREQ;
21245b0a61fSjmcneill }
21345b0a61fSjmcneill 
21456ba9c3dSjmcneill #ifdef SOC_TEGRA124
2152f0a559aSjmcneill static const struct arm_platform tegra124_platform = {
216107aadd0Sskrll 	.ap_devmap = tegra_platform_devmap,
217107aadd0Sskrll 	.ap_bootstrap = tegra124_platform_bootstrap,
218107aadd0Sskrll 	.ap_init_attach_args = tegra_platform_init_attach_args,
219107aadd0Sskrll 	.ap_early_putchar = tegra_platform_early_putchar,
220107aadd0Sskrll 	.ap_device_register = tegra_platform_device_register,
221107aadd0Sskrll 	.ap_reset = tegra_platform_reset,
222107aadd0Sskrll 	.ap_delay = tegra_platform_delay,
223107aadd0Sskrll 	.ap_uart_freq = tegra_platform_uart_freq,
224a7aa900aSjmcneill };
225a7aa900aSjmcneill 
2262f0a559aSjmcneill ARM_PLATFORM(tegra124, "nvidia,tegra124", &tegra124_platform);
22756ba9c3dSjmcneill #endif
2282f0a559aSjmcneill 
22956ba9c3dSjmcneill #ifdef SOC_TEGRA210
2302f0a559aSjmcneill static const struct arm_platform tegra210_platform = {
231107aadd0Sskrll 	.ap_devmap = tegra_platform_devmap,
232107aadd0Sskrll 	.ap_bootstrap = tegra210_platform_bootstrap,
233107aadd0Sskrll 	.ap_init_attach_args = tegra_platform_init_attach_args,
234107aadd0Sskrll 	.ap_early_putchar = tegra_platform_early_putchar,
235107aadd0Sskrll 	.ap_device_register = tegra_platform_device_register,
236107aadd0Sskrll 	.ap_reset = tegra_platform_reset,
237107aadd0Sskrll 	.ap_delay = tegra_platform_delay,
238107aadd0Sskrll 	.ap_uart_freq = tegra_platform_uart_freq,
2392f0a559aSjmcneill };
2402f0a559aSjmcneill 
2412f0a559aSjmcneill ARM_PLATFORM(tegra210, "nvidia,tegra210", &tegra210_platform);
24256ba9c3dSjmcneill #endif
243