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 <[email protected]>
@@ -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 <[email protected]>
@@ -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 <[email protected]>
@@ -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 <[email protected]>
+ * 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 <[email protected]>
+ * 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);