Module Name:    src
Committed By:   jmcneill
Date:           Sun May 28 23:39:30 UTC 2017

Modified Files:
        src/sys/arch/arm/fdt: armv7_fdt.c
        src/sys/arch/arm/nvidia: files.tegra
        src/sys/arch/evbarm/tegra: platform.h tegra_machdep.c
Added Files:
        src/sys/arch/arm/fdt: armv7_fdtvar.h
        src/sys/arch/arm/nvidia: tegra_platform.c

Log Message:
Add a facility for platform-specific callbacks and use it to remove most
of the Tegra-specific code from tegra_machdep.c.

Platform code matches on the compatible property of the root ("/") DT node
and allows for chip-specific implementations of the following:

 - devmap: Return a 0-terminated list of static device map entries.
 - bootstrap: Early initialization of platform-specific facilities.
 - early_putchar: Provides an implementation of putchar for use in early
     debug messages.
 - device_register: Platform-specific device register callback.
 - reset: Platform-specific CPU reset implementation.
 - consinit: Platform-specific console init implementation.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/fdt/armv7_fdt.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/fdt/armv7_fdtvar.h
cvs rdiff -u -r1.37 -r1.38 src/sys/arch/arm/nvidia/files.tegra
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/nvidia/tegra_platform.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbarm/tegra/platform.h
cvs rdiff -u -r1.45 -r1.46 src/sys/arch/evbarm/tegra/tegra_machdep.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/fdt/armv7_fdt.c
diff -u src/sys/arch/arm/fdt/armv7_fdt.c:1.1 src/sys/arch/arm/fdt/armv7_fdt.c:1.2
--- src/sys/arch/arm/fdt/armv7_fdt.c:1.1	Sun May 28 00:40:20 2017
+++ src/sys/arch/arm/fdt/armv7_fdt.c	Sun May 28 23:39:30 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: armv7_fdt.c,v 1.1 2017/05/28 00:40:20 jmcneill Exp $ */
+/* $NetBSD: armv7_fdt.c,v 1.2 2017/05/28 23:39:30 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared D. McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: armv7_fdt.c,v 1.1 2017/05/28 00:40:20 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: armv7_fdt.c,v 1.2 2017/05/28 23:39:30 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -39,6 +39,8 @@ __KERNEL_RCSID(0, "$NetBSD: armv7_fdt.c,
 #include <dev/fdt/fdtvar.h>
 #include <dev/ofw/openfirm.h>
 
+#include <arm/fdt/armv7_fdtvar.h>
+
 static int	armv7_fdt_match(device_t, cfdata_t, void *);
 static void	armv7_fdt_attach(device_t, device_t, void *);
 
@@ -51,6 +53,9 @@ extern struct bus_space armv7_generic_bs
 extern struct bus_space armv7_generic_a4x_bs_tag;
 extern struct arm32_bus_dma_tag armv7_generic_dma_tag;
 
+static struct armv7_platlist armv7_platform_list =
+    TAILQ_HEAD_INITIALIZER(armv7_platform_list);
+
 int
 armv7_fdt_match(device_t parent, cfdata_t cf, void *aux)
 {
@@ -76,3 +81,30 @@ armv7_fdt_attach(device_t parent, device
 	};
 	config_found(self, &faa, NULL);
 }
+
+const struct armv7_platform *
+armv7_fdt_platform(void)
+{
+	static const struct armv7_platform_info *booted_platform = NULL;
+
+	if (booted_platform == NULL) {
+		__link_set_decl(armv7_platforms, struct armv7_platform_info);
+		struct armv7_platform_info * const *info;
+		const struct armv7_platform_info *best_info = NULL;
+		const int phandle = OF_peer(0);
+		int match, best_match = 0;
+
+		__link_set_foreach(info, armv7_platforms) {
+			const char * const compat[] = { (*info)->compat, NULL };
+			match = of_match_compatible(phandle, compat);
+			if (match > best_match) {
+				best_match = match;
+				best_info = *info;
+			}
+		}
+
+		booted_platform = best_info;
+	}
+
+	return booted_platform == NULL ? NULL : booted_platform->ops;
+}

Index: src/sys/arch/arm/nvidia/files.tegra
diff -u src/sys/arch/arm/nvidia/files.tegra:1.37 src/sys/arch/arm/nvidia/files.tegra:1.38
--- src/sys/arch/arm/nvidia/files.tegra:1.37	Sun May 28 00:40:20 2017
+++ src/sys/arch/arm/nvidia/files.tegra	Sun May 28 23:39:30 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.tegra,v 1.37 2017/05/28 00:40:20 jmcneill Exp $
+#	$NetBSD: files.tegra,v 1.38 2017/05/28 23:39:30 jmcneill Exp $
 #
 # Configuration info for NVIDIA Tegra ARM Peripherals
 #
@@ -14,6 +14,7 @@ file	arch/arm/arm32/armv7_generic_space.
 file	arch/arm/arm32/armv7_generic_dma.c
 file	arch/arm/arm/bus_space_a4x.S
 
+file	arch/arm/nvidia/tegra_platform.c
 file	arch/arm/nvidia/tegra_soc.c
 file	arch/arm/nvidia/tegra_cpufreq.c
 

Index: src/sys/arch/evbarm/tegra/platform.h
diff -u src/sys/arch/evbarm/tegra/platform.h:1.2 src/sys/arch/evbarm/tegra/platform.h:1.3
--- src/sys/arch/evbarm/tegra/platform.h:1.2	Sun May 31 22:15:52 2015
+++ src/sys/arch/evbarm/tegra/platform.h	Sun May 28 23:39:30 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: platform.h,v 1.2 2015/05/31 22:15:52 matt Exp $ */
+/* $NetBSD: platform.h,v 1.3 2017/05/28 23:39:30 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
@@ -39,6 +39,4 @@
 #define KERNEL_VM_SIZE		0x50000000 /* 0x50000000 = 1.25GB */
 #endif
 
-#define CONSADDR_VA     (CONSADDR - TEGRA_APB_BASE + TEGRA_APB_VBASE)
-
 #endif /* _EVBARM_TEGRA_PLATFORM_H */

Index: src/sys/arch/evbarm/tegra/tegra_machdep.c
diff -u src/sys/arch/evbarm/tegra/tegra_machdep.c:1.45 src/sys/arch/evbarm/tegra/tegra_machdep.c:1.46
--- src/sys/arch/evbarm/tegra/tegra_machdep.c:1.45	Sun May 28 15:55:11 2017
+++ src/sys/arch/evbarm/tegra/tegra_machdep.c	Sun May 28 23:39:30 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_machdep.c,v 1.45 2017/05/28 15:55:11 jmcneill Exp $ */
+/* $NetBSD: tegra_machdep.c,v 1.46 2017/05/28 23:39:30 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_machdep.c,v 1.45 2017/05/28 15:55:11 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_machdep.c,v 1.46 2017/05/28 23:39:30 jmcneill Exp $");
 
 #include "opt_tegra.h"
 #include "opt_machdep.h"
@@ -36,11 +36,6 @@ __KERNEL_RCSID(0, "$NetBSD: tegra_machde
 #include "opt_arm_debug.h"
 #include "opt_multiprocessor.h"
 
-#include "com.h"
-#include "ukbd.h"
-#include "genfb.h"
-#include "ether.h"
-
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
@@ -55,13 +50,10 @@ __KERNEL_RCSID(0, "$NetBSD: tegra_machde
 #include <sys/proc.h>
 #include <sys/reboot.h>
 #include <sys/termios.h>
-#include <sys/gpio.h>
 
 #include <uvm/uvm_extern.h>
 
 #include <sys/conf.h>
-#include <dev/cons.h>
-#include <dev/md.h>
 
 #include <machine/db_machdep.h>
 #include <ddb/db_sym.h>
@@ -73,20 +65,10 @@ __KERNEL_RCSID(0, "$NetBSD: tegra_machde
 
 #include <arm/arm32/machdep.h>
 
-#include <arm/nvidia/tegra_reg.h>
-#include <arm/nvidia/tegra_var.h>
-
-#include <arm/cortex/gtmr_var.h>
-
 #include <evbarm/include/autoconf.h>
 #include <evbarm/tegra/platform.h>
 
-#include <dev/ic/ns16550reg.h>
-#include <dev/ic/comreg.h>
-#include <dev/ic/comvar.h>
-
-#include <dev/usb/ukbdvar.h>
-#include <net/if_ether.h>
+#include <arm/fdt/armv7_fdtvar.h>
 
 #ifndef TEGRA_MAX_BOOT_STRING
 #define TEGRA_MAX_BOOT_STRING 1024
@@ -109,46 +91,6 @@ static void tegra_device_register(device
 static void tegra_reset(void);
 static void tegra_powerdown(void);
 
-bs_protos(bs_notimpl);
-
-#define	_A(a)	((a) & ~L1_S_OFFSET)
-#define	_S(s)	(((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
-
-static const struct pmap_devmap devmap[] = {
-	{
-		.pd_va = _A(TEGRA_HOST1X_VBASE),
-		.pd_pa = _A(TEGRA_HOST1X_BASE),
-		.pd_size = _S(TEGRA_HOST1X_SIZE),
-		.pd_prot = VM_PROT_READ|VM_PROT_WRITE,
-		.pd_cache = PTE_NOCACHE
-	},
-	{
-		.pd_va = _A(TEGRA_PPSB_VBASE),
-		.pd_pa = _A(TEGRA_PPSB_BASE),
-		.pd_size = _S(TEGRA_PPSB_SIZE),
-		.pd_prot = VM_PROT_READ|VM_PROT_WRITE,
-		.pd_cache = PTE_NOCACHE
-	},
-	{
-		.pd_va = _A(TEGRA_APB_VBASE),
-		.pd_pa = _A(TEGRA_APB_BASE),
-		.pd_size = _S(TEGRA_APB_SIZE),
-		.pd_prot = VM_PROT_READ|VM_PROT_WRITE,
-		.pd_cache = PTE_NOCACHE
-	},
-	{
-		.pd_va = _A(TEGRA_AHB_A2_VBASE),
-		.pd_pa = _A(TEGRA_AHB_A2_BASE),
-		.pd_size = _S(TEGRA_AHB_A2_SIZE),
-		.pd_prot = VM_PROT_READ|VM_PROT_WRITE,
-		.pd_cache = PTE_NOCACHE
-	},
-	{0}
-};
-
-#undef	_A
-#undef	_S
-
 #ifdef PMAP_NEED_ALLOC_POOLPAGE
 static struct boot_physmem bp_lowgig = {
 	.bp_pages = (KERNEL_VM_BASE - KERNEL_BASE) / NBPG,
@@ -161,15 +103,11 @@ static struct boot_physmem bp_lowgig = {
 static void
 tegra_putchar(char c)
 {
-#ifdef CONSADDR
-	volatile uint32_t *uartaddr = (volatile uint32_t *)CONSADDR_VA;
-
-	while ((uartaddr[com_lsr] & LSR_TXRDY) == 0)
-		;
-
-	uartaddr[com_data] = c;
-#endif
+	const struct armv7_platform *plat = armv7_fdt_platform();
+	if (plat && plat->early_purchar)
+		plat->early_putchar(c);
 }
+
 static void
 tegra_putstr(const char *s)
 {
@@ -201,8 +139,6 @@ tegra_printn(u_int n, int base)
 #define DPRINTN(x,b)
 #endif
 
-extern void cortex_mpstart(void);
-
 /*
  * u_int initarm(...)
  *
@@ -219,24 +155,9 @@ extern void cortex_mpstart(void);
 u_int
 initarm(void *arg)
 {
+	const struct armv7_platform *plat;
 	uint64_t memory_addr, memory_size;
 	psize_t ram_size = 0;
-	DPRINT("initarm:");
-
-	DPRINT(" mpstart<0x");
-	DPRINTN((uint32_t)cortex_mpstart, 16);
-	DPRINT(">");
-
-	DPRINT(" devmap");
-	pmap_devmap_register(devmap);
-
-	DPRINT(" bootstrap");
-	tegra_bootstrap();
-
-	/* Heads up ... Setup the CPU / MMU / TLB functions. */
-	DPRINT(" cpufunc");
-	if (set_cpufuncs())
-		panic("cpu not recognized!");
 
 	/* Load FDT */
 	const uint8_t *fdt_addr_r = (const uint8_t *)uboot_args[2];
@@ -244,15 +165,32 @@ initarm(void *arg)
 	if (error == 0) {
 		error = fdt_move(fdt_addr_r, fdt_data, sizeof(fdt_data));
 		if (error != 0) {
-			DPRINT(" (fdt_move failed!)\n");
 			panic("fdt_move failed: %s", fdt_strerror(error));
 		}
 		fdtbus_set_data(fdt_data);
 	} else {
-		DPRINT(" (fdt_check_header failed!)\n");
 		panic("fdt_check_header failed: %s", fdt_strerror(error));
 	}
 
+	/* Lookup platform specific backend */
+	plat = armv7_fdt_platform();
+	if (plat == NULL)
+		panic("Kernel does not support this device");
+
+	/* Early console may be available, announce ourselves. */
+	DPRINT("NetBSD FDT init");
+
+	DPRINT(" devmap");
+	pmap_devmap_register(plat->devmap());
+
+	DPRINT(" bootstrap");
+	plat->bootstrap();
+
+	/* Heads up ... Setup the CPU / MMU / TLB functions. */
+	DPRINT(" cpufunc");
+	if (set_cpufuncs())
+		panic("cpu not recognized!");
+
 	DPRINT(" consinit");
 	consinit();
 
@@ -265,6 +203,7 @@ initarm(void *arg)
 
 	cpu_reset_address = tegra_reset;
 	cpu_powerdown_address = tegra_powerdown;
+	evbarm_device_register = tegra_device_register;
 
 	/* Talk to the user */
 	DPRINTF("\nNetBSD/evbarm (tegra) booting ...\n");
@@ -326,8 +265,8 @@ initarm(void *arg)
 
 	arm32_bootmem_init(bootconfig.dram[0].address, ram_size,
 	    KERNEL_BASE_PHYS);
-	arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_HIGH, 0, devmap,
-	    mapallmem_p);
+	arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_HIGH, 0,
+	    plat->devmap(), mapallmem_p);
 
 	const int chosen = OF_finddevice("/chosen");
 	if (chosen >= 0) {
@@ -339,8 +278,6 @@ initarm(void *arg)
 	boot_args = bootargs;
 	parse_mi_bootargs(boot_args);
 
-	evbarm_device_register = tegra_device_register;
-
 #ifdef PMAP_NEED_ALLOC_POOLPAGE
 	bp_lowgig.bp_start = memory_addr / NBPG;
 	if (atop(ram_size) > bp_lowgig.bp_pages) {
@@ -354,152 +291,33 @@ initarm(void *arg)
 
 }
 
-#if NCOM > 0
-#ifndef CONMODE
-#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
-#endif
-#endif
-
 void
 consinit(void)
 {
-	static bool consinit_called = false;
+	const struct armv7_platform *plat = armv7_fdt_platform();
 
-	if (consinit_called)
-		return;
-	consinit_called = true;
-
-#if NCOM > 0
-	bus_addr_t addr;
-	int speed;
-
-#ifdef CONSADDR
-	addr = CONSADDR;
-#else
-	const char *stdout_path = fdtbus_get_stdout_path();
-	if (stdout_path == NULL) {
-		DPRINT(" (can't find stdout-path!)\n");
-		panic("Cannot find console device");
-	}
-	DPRINT(" ");
-	DPRINT(stdout_path);
-	fdtbus_get_reg(fdtbus_get_stdout_phandle(), 0, &addr, NULL);
-#endif
-	DPRINT(" 0x");
-	DPRINTN((uint32_t)addr, 16);
-
-#ifdef CONSPEED
-	speed = CONSPEED;
-#else
-	speed = fdtbus_get_stdout_speed();
-	if (speed < 0)
-		speed = 115200;	/* default */
-#endif
-	DPRINT(" ");
-	DPRINTN((uint32_t)speed, 10);
-
-	const bus_space_tag_t bst = &armv7_generic_a4x_bs_tag;
-	const u_int freq = 408000000;	/* 408MHz PLLP_OUT0 */
-	if (comcnattach(bst, addr, speed, freq, COM_TYPE_TEGRA, CONMODE))
-		panic("Serial console cannot be initialized.");
-#else
-#error only COM console is supported
-#endif
-}
-
-static bool
-tegra_bootconf_match(const char *key, const char *val)
-{
-	char *s;
-
-	if (!get_bootconf_option(boot_args, key, BOOTOPT_TYPE_STRING, &s))
-		return false;
-
-	return strncmp(s, val, strlen(val)) == 0;
-}
-
-static char *
-tegra_bootconf_strdup(const char *key)
-{
-	char *s, *ret;
-	int i = 0;
-
-	if (!get_bootconf_option(boot_args, key, BOOTOPT_TYPE_STRING, &s))
-		return NULL;
-
-	for (;;) {
-		if (s[i] == ' ' || s[i] == '\t' || s[i] == '\0')
-			break;
-		++i;
-	}
-
-	ret = kmem_alloc(i + 1, KM_SLEEP);
-	if (ret == NULL)
-		return NULL;
-
-	strlcpy(ret, s, i + 1);
-	return ret;
+	if (plat && plat->consinit)
+		plat->consinit();
 }
 
 void
 tegra_device_register(device_t self, void *aux)
 {
-	prop_dictionary_t dict = device_properties(self);
-
-	if (device_is_a(self, "tegrafb")
-	    && tegra_bootconf_match("console", "fb")) {
-		prop_dictionary_set_bool(dict, "is_console", true);
-#if NUKBD > 0
-		ukbd_cnattach();
-#endif
-	}
-
-	if (device_is_a(self, "tegradrm")) {
-		const char *video = tegra_bootconf_strdup("video");
-
-		if (tegra_bootconf_match("hdmi.forcemode", "dvi")) {
-			prop_dictionary_set_bool(dict, "force-dvi", true);
-		}
-
-		if (video) {
-			prop_dictionary_set_cstring(dict, "HDMI-A-1", video);
-		}
-	}
-
-	if (device_is_a(self, "tegracec")) {
-		prop_dictionary_set_cstring(dict, "hdmi-device", "tegradrm0");
-	}
-
-	if (device_is_a(self, "nouveau")) {
-		const char *config = tegra_bootconf_strdup("nouveau.config");
-		const char *debug = tegra_bootconf_strdup("nouveau.debug");
-		if (config)
-			prop_dictionary_set_cstring(dict, "config", config);
-		if (debug)
-			prop_dictionary_set_cstring(dict, "debug", debug);
-	}
+	const struct armv7_platform *plat = armv7_fdt_platform();
 
-	if (device_is_a(self, "tegrapcie")) {
-		const char * const jetsontk1_compat[] = {
-		    "nvidia,jetson-tk1", NULL
-		};
-		int phandle = OF_peer(0);
-		if (of_match_compatible(phandle, jetsontk1_compat)) {
-			/* rfkill GPIO at GPIO X7 */
-			struct tegra_gpio_pin *pin;
-			pin = tegra_gpio_acquire("X7", GPIO_PIN_OUTPUT);
-			if (pin) {
-				tegra_gpio_write(pin, 1);
-			}
-		}
-	}
+	if (plat && plat->device_register)
+		plat->device_register(self, aux);
 }
 
 static void
 tegra_reset(void)
 {
+	const struct armv7_platform *plat = armv7_fdt_platform();
+
 	fdtbus_power_reset();
-	tegra_pmc_reset();
+
+	if (plat && plat->reset)
+		plat->reset();
 }
 
 static void

Added files:

Index: src/sys/arch/arm/fdt/armv7_fdtvar.h
diff -u /dev/null src/sys/arch/arm/fdt/armv7_fdtvar.h:1.1
--- /dev/null	Sun May 28 23:39:30 2017
+++ src/sys/arch/arm/fdt/armv7_fdtvar.h	Sun May 28 23:39:30 2017
@@ -0,0 +1,60 @@
+/* $NetBSD: armv7_fdtvar.h,v 1.1 2017/05/28 23:39:30 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared D. McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM_ARMV7_FDTVAR_H
+#define _ARM_ARMV7_FDTVAR_H
+
+struct armv7_platform {
+	const struct pmap_devmap *	(*devmap)(void);
+	void				(*bootstrap)(void);
+	void				(*early_putchar)(char);
+	void				(*device_register)(device_t, void *);
+	void				(*reset)(void);
+	void				(*consinit)(void);
+};
+
+struct armv7_platform_info {
+	const char *			compat;
+	const struct armv7_platform *	ops;
+};
+
+#define _ARMV7_PLATFORM_REGISTER(name)	\
+	__link_set_add_rodata(armv7_platforms, __CONCAT(name,_platinfo));
+
+#define ARMV7_PLATFORM(_name, _compat, _ops)				\
+static const struct armv7_platform_info __CONCAT(_name,_platinfo) = {	\
+	.compat = (_compat),						\
+	.ops = (_ops)							\
+};									\
+_ARMV7_PLATFORM_REGISTER(_name)
+
+TAILQ_HEAD(armv7_platlist, armv7_platform_info);
+
+const struct armv7_platform *	armv7_fdt_platform(void);
+
+#endif /* !_ARM_ARMV7_FDTVAR_H */

Index: src/sys/arch/arm/nvidia/tegra_platform.c
diff -u /dev/null src/sys/arch/arm/nvidia/tegra_platform.c:1.1
--- /dev/null	Sun May 28 23:39:30 2017
+++ src/sys/arch/arm/nvidia/tegra_platform.c	Sun May 28 23:39:30 2017
@@ -0,0 +1,223 @@
+/* $NetBSD: tegra_platform.c,v 1.1 2017/05/28 23:39:30 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared D. McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_tegra.h"
+#include "opt_multiprocessor.h"
+
+#include "com.h"
+#include "ukbd.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: tegra_platform.c,v 1.1 2017/05/28 23:39:30 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+#include <sys/termios.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/bootconfig.h>
+#include <arm/cpufunc.h>
+
+#include <arm/nvidia/tegra_reg.h>
+#include <arm/nvidia/tegra_var.h>
+
+#include <arm/fdt/armv7_fdtvar.h>
+
+#if NUKBD > 0
+#include <dev/usb/ukbdvar.h>
+#endif
+
+#if NCOM > 0
+#include <dev/ic/ns16550reg.h>
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+#ifndef CONMODE
+#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
+#endif
+#endif
+
+#define	DEVMAP_ALIGN(a)	((a) & ~L1_S_OFFSET)
+#define	DEVMAP_SIZE(s)	roundup2((s), L1_S_SIZE)
+#define	DEVMAP_ENTRY(va, pa, sz)			\
+	{						\
+		.pd_va = DEVMAP_ALIGN(va),		\
+		.pd_pa = DEVMAP_ALIGN(pa),		\
+		.pd_size = DEVMAP_SIZE(sz),		\
+		.pd_prot = VM_PROT_READ|VM_PROT_WRITE,	\
+		.pd_cache = PTE_NOCACHE			\
+	}
+#define	DEVMAP_ENTRY_END	{ 0 }
+
+static const struct pmap_devmap *
+tegra_platform_devmap(void)
+{
+	static const struct pmap_devmap devmap[] = {
+		DEVMAP_ENTRY(TEGRA_HOST1X_VBASE,
+			     TEGRA_HOST1X_BASE,
+			     TEGRA_HOST1X_SIZE),
+		DEVMAP_ENTRY(TEGRA_PPSB_VBASE,
+			     TEGRA_PPSB_BASE,
+			     TEGRA_PPSB_SIZE),
+		DEVMAP_ENTRY(TEGRA_APB_VBASE,
+			     TEGRA_APB_BASE,
+			     TEGRA_APB_SIZE),
+		DEVMAP_ENTRY(TEGRA_AHB_A2_VBASE,
+			     TEGRA_AHB_A2_BASE,
+			     TEGRA_AHB_A2_SIZE),
+		DEVMAP_ENTRY_END
+	};	
+
+	return devmap;
+}
+
+static void
+tegra_platform_bootstrap(void)
+{
+	tegra_bootstrap();
+}
+
+static void
+tegra_platform_early_putchar(char c)
+{
+#ifdef CONSADDR
+#define CONSADDR_VA	(CONSADDR - TEGRA_APB_BASE + TEGRA_APB_VBASE)
+	volatile uint32_t *uartaddr = (volatile uint32_t *)CONSADDR_VA;
+
+	while ((uartaddr[com_lsr] & LSR_TXRDY) == 0)
+		;
+
+	uartaddr[com_data] = c;
+#endif
+}
+
+static void
+tegra_platform_device_register(device_t self, void *aux)
+{
+	prop_dictionary_t dict = device_properties(self);
+
+	if (device_is_a(self, "tegrafb") &&
+	    match_bootconf_option(boot_args, "console", "fb")) {
+		prop_dictionary_set_bool(dict, "is_console", true);
+#if NUKBD > 0
+		ukbd_cnattach();
+#endif
+	}
+
+	if (device_is_a(self, "tegradrm")) {
+		const char *video = get_bootconf_string(boot_args, "video");
+		if (video)
+			prop_dictionary_set_cstring(dict, "HDMI-A-1", video);
+		if (match_bootconf_option(boot_args, "hdmi.forcemode", "dvi"))
+			prop_dictionary_set_bool(dict, "force-dvi", true);
+	}
+
+	if (device_is_a(self, "tegracec"))
+		prop_dictionary_set_cstring(dict, "hdmi-device", "tegradrm0");
+
+	if (device_is_a(self, "nouveau")) {
+		const char *config = get_bootconf_string(boot_args,
+		    "nouveau.config");
+		if (config)
+			prop_dictionary_set_cstring(dict, "config", config);
+		const char *debug = get_bootconf_string(boot_args,
+		    "nouveau.debug");
+		if (debug)
+			prop_dictionary_set_cstring(dict, "debug", debug);
+	}
+
+	if (device_is_a(self, "tegrapcie")) {
+		const char * const jetsontk1_compat[] = {
+		    "nvidia,jetson-tk1", NULL
+		};
+		const int phandle = OF_peer(0);
+		if (of_match_compatible(phandle, jetsontk1_compat)) {
+			/* rfkill GPIO at GPIO X7 */
+			struct tegra_gpio_pin *pin =
+			    tegra_gpio_acquire("X7", GPIO_PIN_OUTPUT);
+			if (pin)
+				tegra_gpio_write(pin, 1);
+		}
+	}
+}
+
+static void
+tegra_platform_reset(void)
+{
+	tegra_pmc_reset();
+}
+
+static void
+tegra_platform_consinit(void)
+{
+	static bool consinit_called = false;
+
+	if (consinit_called)
+		return;
+	consinit_called = true;
+
+#if NCOM > 0
+	bus_addr_t addr;
+	int speed;
+
+#ifdef CONSADDR
+	addr = CONSADDR;
+#else
+	fdtbus_get_reg(fdtbus_get_stdout_phandle(), 0, &addr, NULL);
+#endif
+
+#ifdef CONSPEED
+	speed = CONSPEED;
+#else
+	speed = fdtbus_get_stdout_speed();
+	if (speed < 0)
+		speed = 115200;	/* default */
+#endif
+
+	const bus_space_tag_t bst = &armv7_generic_a4x_bs_tag;
+	const u_int freq = 408000000;	/* 408MHz PLLP_OUT0 */
+	if (comcnattach(bst, addr, speed, freq, COM_TYPE_TEGRA, CONMODE))
+		panic("Serial console cannot be initialized.");
+#endif
+}
+
+static const struct armv7_platform tegra_platform = {
+	.devmap = tegra_platform_devmap,
+	.bootstrap = tegra_platform_bootstrap,
+	.early_putchar = tegra_platform_early_putchar,
+	.device_register = tegra_platform_device_register,
+	.reset = tegra_platform_reset,
+	.consinit = tegra_platform_consinit,
+};
+
+ARMV7_PLATFORM(tegra124, "nvidia,tegra124", &tegra_platform);
+ARMV7_PLATFORM(tegra210, "nvidia,tegra210", &tegra_platform);

Reply via email to