Module Name:    src
Committed By:   jmcneill
Date:           Tue Sep 19 20:46:12 UTC 2017

Modified Files:
        src/sys/arch/arm/nvidia: files.tegra tegra_ahcisata.c tegra_var.h
            tegra_xusb-fw.mk tegra_xusb.c tegra_xusbpad.c
        src/sys/arch/evbarm/conf: TEGRA
Added Files:
        src/sys/arch/arm/nvidia: tegra124_xusbpad.c tegra124_xusbpadreg.h
            tegra_xusbpad.h
Removed Files:
        src/sys/arch/arm/nvidia: tegra_xusbpadreg.h

Log Message:
The xusbpad driver is tegra 124 specific so split it out into a separate
driver. Add (not yet working) tegra 210 support to the xusb driver.


To generate a diff of this commit:
cvs rdiff -u -r1.41 -r1.42 src/sys/arch/arm/nvidia/files.tegra
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/nvidia/tegra124_xusbpad.c \
    src/sys/arch/arm/nvidia/tegra124_xusbpadreg.h \
    src/sys/arch/arm/nvidia/tegra_xusbpad.h
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/arm/nvidia/tegra_ahcisata.c
cvs rdiff -u -r1.39 -r1.40 src/sys/arch/arm/nvidia/tegra_var.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/nvidia/tegra_xusb-fw.mk
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/nvidia/tegra_xusb.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/nvidia/tegra_xusbpad.c
cvs rdiff -u -r1.2 -r0 src/sys/arch/arm/nvidia/tegra_xusbpadreg.h
cvs rdiff -u -r1.27 -r1.28 src/sys/arch/evbarm/conf/TEGRA

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/nvidia/files.tegra
diff -u src/sys/arch/arm/nvidia/files.tegra:1.41 src/sys/arch/arm/nvidia/files.tegra:1.42
--- src/sys/arch/arm/nvidia/files.tegra:1.41	Fri Jul 21 01:01:22 2017
+++ src/sys/arch/arm/nvidia/files.tegra	Tue Sep 19 20:46:12 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.tegra,v 1.41 2017/07/21 01:01:22 jmcneill Exp $
+#	$NetBSD: files.tegra,v 1.42 2017/09/19 20:46:12 jmcneill Exp $
 #
 # Configuration info for NVIDIA Tegra ARM Peripherals
 #
@@ -77,12 +77,20 @@ device	tegraapbdma
 attach	tegraapbdma at fdt with tegra_apbdma
 file	arch/arm/nvidia/tegra_apbdma.c		tegra_apbdma
 
-# XUSB PADCTL
-device	tegraxusbpad
-attach	tegraxusbpad at fdt with tegra_xusbpad
+# XUSB PADCTL (common)
 file	arch/arm/nvidia/tegra_xusbpad.c		tegra_xusbpad
 defflag	opt_tegra.h				TEGRA_XUSBPAD_DEBUG
 
+# XUSB PADCTL (Tegra124)
+device	tegra124xusbpad: tegra_xusbpad
+attach	tegra124xusbpad at fdt with tegra124_xusbpad
+file	arch/arm/nvidia/tegra124_xusbpad.c	tegra124_xusbpad
+
+# XUSB PADCTL (Tegra210)
+device	tegra210xusbpad: tegra_xusbpad
+attach	tegra210xusbpad at fdt with tegra210_xusbpad
+file	arch/arm/nvidia/tegra210_xusbpad.c	tegra210_xusbpad
+
 # UART
 attach	com at fdt with tegra_com
 file	arch/arm/nvidia/tegra_com.c		tegra_com needs-flag

Index: src/sys/arch/arm/nvidia/tegra_ahcisata.c
diff -u src/sys/arch/arm/nvidia/tegra_ahcisata.c:1.10 src/sys/arch/arm/nvidia/tegra_ahcisata.c:1.11
--- src/sys/arch/arm/nvidia/tegra_ahcisata.c:1.10	Sun Apr 16 12:28:21 2017
+++ src/sys/arch/arm/nvidia/tegra_ahcisata.c	Tue Sep 19 20:46:12 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_ahcisata.c,v 1.10 2017/04/16 12:28:21 jmcneill Exp $ */
+/* $NetBSD: tegra_ahcisata.c,v 1.11 2017/09/19 20:46:12 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_ahcisata.c,v 1.10 2017/04/16 12:28:21 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_ahcisata.c,v 1.11 2017/09/19 20:46:12 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -42,6 +42,7 @@ __KERNEL_RCSID(0, "$NetBSD: tegra_ahcisa
 #include <arm/nvidia/tegra_var.h>
 #include <arm/nvidia/tegra_pmcreg.h>
 #include <arm/nvidia/tegra_ahcisatareg.h>
+#include <arm/nvidia/tegra_xusbpad.h>
 
 #include <dev/fdt/fdtvar.h>
 

Index: src/sys/arch/arm/nvidia/tegra_var.h
diff -u src/sys/arch/arm/nvidia/tegra_var.h:1.39 src/sys/arch/arm/nvidia/tegra_var.h:1.40
--- src/sys/arch/arm/nvidia/tegra_var.h:1.39	Thu Jul 20 01:46:15 2017
+++ src/sys/arch/arm/nvidia/tegra_var.h	Tue Sep 19 20:46:12 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_var.h,v 1.39 2017/07/20 01:46:15 jmcneill Exp $ */
+/* $NetBSD: tegra_var.h,v 1.40 2017/09/19 20:46:12 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
@@ -78,9 +78,6 @@ uint32_t tegra_fuse_read(u_int);
 
 void	tegra_timer_delay(u_int);
 
-void	tegra_xusbpad_sata_enable(void);
-void	tegra_xusbpad_xhci_enable(void);
-
 struct videomode;
 int	tegra_dc_port(device_t);
 int	tegra_dc_enable(device_t, device_t, const struct videomode *,

Index: src/sys/arch/arm/nvidia/tegra_xusb-fw.mk
diff -u src/sys/arch/arm/nvidia/tegra_xusb-fw.mk:1.1 src/sys/arch/arm/nvidia/tegra_xusb-fw.mk:1.2
--- src/sys/arch/arm/nvidia/tegra_xusb-fw.mk:1.1	Mon Sep 26 20:05:03 2016
+++ src/sys/arch/arm/nvidia/tegra_xusb-fw.mk	Tue Sep 19 20:46:12 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: tegra_xusb-fw.mk,v 1.1 2016/09/26 20:05:03 jakllsch Exp $
+#	$NetBSD: tegra_xusb-fw.mk,v 1.2 2017/09/19 20:46:12 jmcneill Exp $
 
 .if defined(TEGRA124_XUSB_BIN_STATIC)
 MD_OBJS+=	tegra124_xusb_bin.o
@@ -10,3 +10,14 @@ tegra124_xusb_bin.o:	$S/arch/arm/nvidia/
 	${OBJCOPY} -I binary -O default -B arm tegra124_xusb.bin \
 	    --rename-section .data=.rodata ${.TARGET}
 .endif
+
+.if defined(TEGRA210_XUSB_BIN_STATIC)
+MD_OBJS+=	tegra210_xusb_bin.o
+CPPFLAGS+=	-DTEGRA210_XUSB_BIN_STATIC
+
+tegra210_xusb_bin.o:	$S/arch/arm/nvidia/tegra210_xusb.bin
+	-rm -f ${.OBJDIR}/tegra210_xusb.bin
+	-ln -s $S/arch/arm/nvidia/tegra210_xusb.bin ${.OBJDIR}
+	${OBJCOPY} -I binary -O default -B arm tegra210_xusb.bin \
+	    --rename-section .data=.rodata ${.TARGET}
+.endif

Index: src/sys/arch/arm/nvidia/tegra_xusb.c
diff -u src/sys/arch/arm/nvidia/tegra_xusb.c:1.6 src/sys/arch/arm/nvidia/tegra_xusb.c:1.7
--- src/sys/arch/arm/nvidia/tegra_xusb.c:1.6	Fri Apr 28 09:46:49 2017
+++ src/sys/arch/arm/nvidia/tegra_xusb.c	Tue Sep 19 20:46:12 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_xusb.c,v 1.6 2017/04/28 09:46:49 jmcneill Exp $ */
+/* $NetBSD: tegra_xusb.c,v 1.7 2017/09/19 20:46:12 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2016 Jonathan A. Kollasch
@@ -30,7 +30,7 @@
 #include "opt_tegra.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_xusb.c,v 1.6 2017/04/28 09:46:49 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_xusb.c,v 1.7 2017/09/19 20:46:12 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: tegra_xusb.c
 
 #include <arm/nvidia/tegra_reg.h>
 #include <arm/nvidia/tegra_var.h>
+#include <arm/nvidia/tegra_xusbpad.h>
 
 #include <arm/nvidia/tegra_xusbreg.h>
 #include <dev/pci/pcireg.h>
@@ -76,6 +77,24 @@ extern const char _binary_tegra124_xusb_
 extern const char _binary_tegra124_xusb_bin_start[];
 #endif
 
+#ifdef TEGRA210_XUSB_BIN_STATIC
+extern const char _binary_tegra210_xusb_bin_size[];
+extern const char _binary_tegra210_xusb_bin_start[];
+#endif
+
+enum xusb_type {
+	XUSB_T124 = 1,
+	XUSB_T210
+};
+
+static const struct of_compat_data compat_data[] = {
+	{ "nvidia,tegra124-xusb",		XUSB_T124 },
+#if notyet
+	{ "nvidia,tegra210-xusb",		XUSB_T210 },
+#endif
+	{ NULL }
+};
+
 struct fw_dma {
 	bus_dmamap_t            map;
 	void *                  addr;
@@ -94,6 +113,7 @@ struct tegra_xusb_softc {
 	void			*sc_ih_mbox;
 	struct fw_dma		sc_fw_dma;
 	struct clk		*sc_clk_ss_src;
+	enum xusb_type		sc_type;
 };
 
 static uint32_t	csb_read_4(struct tegra_xusb_softc * const, bus_size_t);
@@ -101,7 +121,9 @@ static void	csb_write_4(struct tegra_xus
     uint32_t);
 	
 static void	tegra_xusb_init(struct tegra_xusb_softc * const);
-static int	tegra_xusb_load_fw(struct tegra_xusb_softc * const);
+static int	tegra_xusb_open_fw(struct tegra_xusb_softc * const);
+static int	tegra_xusb_load_fw(struct tegra_xusb_softc * const, void *,
+    size_t);
 
 static int	xusb_mailbox_send(struct tegra_xusb_softc * const, uint32_t);
 
@@ -111,10 +133,9 @@ CFATTACH_DECL_NEW(tegra_xusb, sizeof(str
 static int
 tegra_xusb_match(device_t parent, cfdata_t cf, void *aux)
 {
-	const char * const compatible[] = { "nvidia,tegra124-xusb", NULL };
 	struct fdt_attach_args * const faa = aux;
 
-	return of_match_compatible(faa->faa_phandle, compatible);
+	return of_match_compat_data(faa->faa_phandle, compat_data);
 }
 
 #define tegra_xusb_attach_check(sc, cond, fmt, ...)			\
@@ -131,6 +152,7 @@ tegra_xusb_attach(device_t parent, devic
 	struct tegra_xusb_softc * const psc = device_private(self);
 	struct xhci_softc * const sc = &psc->sc_xhci;
 	struct fdt_attach_args * const faa = aux;
+	bool wait_for_root = true;
 	char intrstr[128];
 	bus_addr_t addr;
 	bus_size_t size;
@@ -147,6 +169,7 @@ tegra_xusb_attach(device_t parent, devic
 	sc->sc_bus.ub_hcpriv = sc;
 	sc->sc_bus.ub_dmatag = faa->faa_dmat;
 	psc->sc_phandle = faa->faa_phandle;
+	psc->sc_type = of_search_compatible(faa->faa_phandle, compat_data)->data;
 
 	if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
 		aprint_error(": couldn't get registers\n");
@@ -252,22 +275,25 @@ tegra_xusb_attach(device_t parent, devic
 	tegra_xusb_attach_check(sc, psc->sc_clk_ss_src == NULL,
 		"failed to get xusb_ss_src clock");
 
-	rate = clk_get_rate(psc->sc_clk_ss_src);
-	DPRINTF(sc->sc_dev, "xusb_ss_src rate %u\n", rate);
-	error = clk_set_rate(psc->sc_clk_ss_src, 2000000);
-	rate = clk_get_rate(psc->sc_clk_ss_src);
-	DPRINTF(sc->sc_dev, "xusb_ss_src rate %u error %d\n", rate, error);
-	tegra_xusb_attach_check(sc, error, "failed to get xusb_ss_src clock rate");
+	if (psc->sc_type == XUSB_T124) {
+		rate = clk_get_rate(psc->sc_clk_ss_src);
+		DPRINTF(sc->sc_dev, "xusb_ss_src rate %u\n", rate);
+		error = clk_set_rate(psc->sc_clk_ss_src, 2000000);
+		rate = clk_get_rate(psc->sc_clk_ss_src);
+		DPRINTF(sc->sc_dev, "xusb_ss_src rate %u error %d\n", rate, error);
+		tegra_xusb_attach_check(sc, error, "failed to get xusb_ss_src clock rate");
 
-	rate = clk_get_rate(psc->sc_clk_ss_src);
-	DPRINTF(sc->sc_dev, "ss_src rate %u\n", rate);
-	tegra_xusb_attach_check(sc, error, "failed to set xusb_ss_src clock rate");
+		rate = clk_get_rate(psc->sc_clk_ss_src);
+		DPRINTF(sc->sc_dev, "ss_src rate %u\n", rate);
+		tegra_xusb_attach_check(sc, error, "failed to set xusb_ss_src clock rate");
 
-	error = clk_set_rate(psc->sc_clk_ss_src, 120000000);
-	rate = clk_get_rate(psc->sc_clk_ss_src);
-	DPRINTF(sc->sc_dev, "ss_src rate %u error %d\n", rate, error);
-	tegra_xusb_attach_check(sc, error, "failed to get xusb_ss_src clock rate");
+		error = clk_set_rate(psc->sc_clk_ss_src, 120000000);
+		rate = clk_get_rate(psc->sc_clk_ss_src);
+		DPRINTF(sc->sc_dev, "ss_src rate %u error %d\n", rate, error);
+		tegra_xusb_attach_check(sc, error, "failed to get xusb_ss_src clock rate");
+	}
 
+	rate = clk_get_rate(psc->sc_clk_ss_src);
 	error = clk_enable(psc->sc_clk_ss_src);
 	DPRINTF(sc->sc_dev, "ss_src rate %u error %d\n", rate, error);
 	tegra_xusb_attach_check(sc, error, "failed to enable xusb_ss_src clock");
@@ -299,10 +325,18 @@ tegra_xusb_attach(device_t parent, devic
 	tegra_xusb_init(psc);
 
 #if defined(TEGRA124_XUSB_BIN_STATIC)
-	tegra_xusb_mountroot(sc->sc_dev);
-#else
-	config_mountroot(sc->sc_dev, tegra_xusb_mountroot);
+	if (psc->sc_type == XUSB_T124)
+		wait_for_root = false;
+#endif
+#if defined(TEGRA210_XUSB_BIN_STATIC)
+	if (psc->sc_type == XUSB_T210)
+		wait_for_root = false;
 #endif
+
+	if (wait_for_root)
+		config_mountroot(sc->sc_dev, tegra_xusb_mountroot);
+	else
+		tegra_xusb_mountroot(sc->sc_dev);
 }
 
 static void
@@ -323,7 +357,7 @@ tegra_xusb_mountroot(device_t self)
 	val = bus_space_read_4(bst, ipfsh, 0x0);
 	DPRINTF(sc->sc_dev, "%s ipfs 0x0 = 0x%x\n", __func__, val);
 
-	if (tegra_xusb_load_fw(psc) != 0)
+	if (tegra_xusb_open_fw(psc) != 0)
 		return;
 	DPRINTF(sc->sc_dev, "post fw\n");
 
@@ -569,51 +603,75 @@ fw_dma_free(struct tegra_xusb_softc * co
 #define FWHEADER__LEN 256
 
 static int
-tegra_xusb_load_fw(struct tegra_xusb_softc * const psc)
+tegra_xusb_open_fw(struct tegra_xusb_softc * const psc)
 {
 	struct xhci_softc * const sc = &psc->sc_xhci;
-#if !defined(TEGRA124_XUSB_BIN_STATIC)
 	firmware_handle_t fw;
-#endif
+	size_t firmware_size = 0;
+	void *firmware_image;
+	const char *fw_path = NULL;
+	void *fw_static = NULL;
 	int error;
-	size_t firmware_size;
-	void * firmware_image;
-	const uint8_t *header;
 
+	switch (psc->sc_type) {
+	case XUSB_T124:
 #if defined(TEGRA124_XUSB_BIN_STATIC)
-	firmware_size = (uintptr_t)&_binary_tegra124_xusb_bin_size;
+		firmware_size = (uintptr_t)&_binary_tegra124_xusb_bin_size;
+		fw_static = _binary_tegra124_xusb_bin_start;
 #else
-	if ((error = firmware_open("nvidia/tegra124", "xusb.bin", &fw)) != 0) {
-		aprint_error_dev(sc->sc_dev,
-		    "couldn't load firmware from 'nvidia/tegra124/xusb.bin': %d\n", error);
-		return error;
-	}
-	firmware_size = firmware_get_size(fw);
+		fw_path = "nvidia/tegra124";
 #endif
-
-	error = fw_dma_alloc(psc, firmware_size, PAGE_SIZE, &psc->sc_fw_dma);
-	if (error != 0) {
-#if !defined(TEGRA124_XUSB_BIN_STATIC)
-		firmware_close(fw);
+		break;
+	case XUSB_T210:
+#if defined(TEGRA210_XUSB_BIN_STATIC)
+		firmware_size = (uintptr_t)&_binary_tegra210_xusb_bin_size;
+		fw_static = _binary_tegra210_xusb_bin_start;
+#else
+		fw_path = "nvidia/tegra210";
 #endif
-		return error;
+		break;
+	default:
+		return EINVAL;
+	}
+
+	if (fw_path != NULL) {
+		error = firmware_open(fw_path, "xusb.bin", &fw);
+		if (error != 0) {
+			aprint_error_dev(sc->sc_dev,
+			    "couldn't load firmware from %s/xusb.bin: %d\n",
+			    fw_path, error);
+			return error;
+		}
+		firmware_size = firmware_get_size(fw);
 	}
 
+	error = fw_dma_alloc(psc, firmware_size, PAGE_SIZE,
+	    &psc->sc_fw_dma);
+	if (error != 0)
+		return error;
 	firmware_image = psc->sc_fw_dma.addr;
-	DPRINTF(sc->sc_dev, "blob %p len %zu\n", firmware_image,
-	    firmware_size);
 
-#if defined(TEGRA124_XUSB_BIN_STATIC)
-	memcpy(firmware_image, _binary_tegra124_xusb_bin_start, firmware_size);
-#else
-	error = firmware_read(fw, 0, firmware_image, firmware_size);
-	if (error != 0) {
-		fw_dma_free(psc, &psc->sc_fw_dma);
+	if (fw_path != NULL) {
+		error = firmware_read(fw, 0, firmware_image, firmware_size);
+		if (error != 0) {
+			fw_dma_free(psc, &psc->sc_fw_dma);
+			firmware_close(fw);
+			return error;
+		}
 		firmware_close(fw);
-		return error;
+	} else {
+		memcpy(firmware_image, fw_static, firmware_size);
 	}
-	firmware_close(fw);
-#endif
+
+	return tegra_xusb_load_fw(psc, firmware_image, firmware_size);
+}
+
+static int
+tegra_xusb_load_fw(struct tegra_xusb_softc * const psc, void *firmware_image,
+    size_t firmware_size)
+{
+	struct xhci_softc * const sc = &psc->sc_xhci;
+	const uint8_t *header;
 
 	header = firmware_image;
 

Index: src/sys/arch/arm/nvidia/tegra_xusbpad.c
diff -u src/sys/arch/arm/nvidia/tegra_xusbpad.c:1.5 src/sys/arch/arm/nvidia/tegra_xusbpad.c:1.6
--- src/sys/arch/arm/nvidia/tegra_xusbpad.c:1.5	Fri Apr 14 00:19:34 2017
+++ src/sys/arch/arm/nvidia/tegra_xusbpad.c	Tue Sep 19 20:46:12 2017
@@ -1,7 +1,7 @@
-/* $NetBSD: tegra_xusbpad.c,v 1.5 2017/04/14 00:19:34 jmcneill Exp $ */
+/* $NetBSD: tegra_xusbpad.c,v 1.6 2017/09/19 20:46:12 jmcneill Exp $ */
 
 /*-
- * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
+ * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,327 +26,48 @@
  * SUCH DAMAGE.
  */
 
-#include "opt_tegra.h"
-
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_xusbpad.c,v 1.5 2017/04/14 00:19:34 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_xusbpad.c,v 1.6 2017/09/19 20:46:12 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
+#include <sys/cpu.h>
 #include <sys/device.h>
-#include <sys/intr.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-
-#include <arm/nvidia/tegra_reg.h>
-#include <arm/nvidia/tegra_xusbpadreg.h>
-#include <arm/nvidia/tegra_var.h>
 
 #include <dev/fdt/fdtvar.h>
 
-#define TEGRA_FUSE_SKU_CALIB_REG 0xf0
-
-static int	tegra_xusbpad_match(device_t, cfdata_t, void *);
-static void	tegra_xusbpad_attach(device_t, device_t, void *);
-
-struct tegra_xusbpad_softc {
-	device_t		sc_dev;
-	bus_space_tag_t		sc_bst;
-	bus_space_handle_t	sc_bsh;
-};
+#include <arm/nvidia/tegra_xusbpad.h>
 
-#ifdef TEGRA_XUSBPAD_DEBUG
-static void	padregdump(void);
-#endif
+static const struct tegra_xusbpad_ops *xusbpad_ops = NULL;
+static device_t xusbpad_device = NULL;
 
-static struct tegra_xusbpad_softc *xusbpad_softc = NULL;
-
-CFATTACH_DECL_NEW(tegra_xusbpad, sizeof(struct tegra_xusbpad_softc),
-	tegra_xusbpad_match, tegra_xusbpad_attach, NULL, NULL);
-
-static int
-tegra_xusbpad_match(device_t parent, cfdata_t cf, void *aux)
+void
+tegra_xusbpad_register(device_t dev, const struct tegra_xusbpad_ops *ops)
 {
-	const char * const compatible[] =
-	    { "nvidia,tegra124-xusb-padctl", NULL };
-	struct fdt_attach_args * const faa = aux;
+	KASSERT(dev != NULL && ops != NULL);
+	KASSERT(xusbpad_ops == NULL);
+	KASSERT(xusbpad_device == NULL);
 
-	return of_match_compatible(faa->faa_phandle, compatible);
-}
-
-static void
-tegra_xusbpad_attach(device_t parent, device_t self, void *aux)
-{
-	struct tegra_xusbpad_softc * const sc = device_private(self);
-	struct fdt_attach_args * const faa = aux;
-	bus_addr_t addr;
-	bus_size_t size;
-	int error;
-
-	if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
-		aprint_error(": couldn't get registers\n");
-		return;
-	}
-
-	sc->sc_dev = self;
-	sc->sc_bst = faa->faa_bst;
-	error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh);
-	if (error) {
-		aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error);
-		return;
-	}
-
-	KASSERT(xusbpad_softc == NULL);
-	xusbpad_softc = sc;
-
-	aprint_naive("\n");
-	aprint_normal(": XUSB PADCTL\n");
-}
-
-static void
-tegra_xusbpad_get_bs(bus_space_tag_t *pbst, bus_space_handle_t *pbsh)
-{
-	if (xusbpad_softc) {
-		*pbst = xusbpad_softc->sc_bst;
-		*pbsh = xusbpad_softc->sc_bsh;
-	} else {
-		*pbst = &armv7_generic_bs_tag;
-		bus_space_subregion(*pbst, tegra_apb_bsh,
-		    TEGRA_XUSB_PADCTL_OFFSET, TEGRA_XUSB_PADCTL_SIZE, pbsh);
-	}
+	xusbpad_ops = ops;
+	xusbpad_device = dev;
 }
 
 void
 tegra_xusbpad_sata_enable(void)
 {
-	bus_space_tag_t bst;
-	bus_space_handle_t bsh;
-	int retry;
-
-	tegra_xusbpad_get_bs(&bst, &bsh);
-
-	tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_USB3_PAD_MUX_REG,
-	    __SHIFTIN(XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0_SATA,
-		      XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0) |
-	    XUSB_PADCTL_USB3_PAD_MUX_FORCE_SATA_PAD_IDDQ_DISABLE_MASK0,
-	    XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0);
-
-	tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_REG,
-	    0,
-	    XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ |
-	    XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD);
-	tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG,
-	    0,
-	    XUSB_PADCTL_IOPHY_PLL_S0_CTL1_IDDQ |
-	    XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PWR_OVRD);
-	tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG,
-	    XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE, 0);
-	tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG,
-	    XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST, 0);
-
-	for (retry = 1000; retry > 0; retry--) {
-		const uint32_t v = bus_space_read_4(bst, bsh,
-		    XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG);
-		if (v & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET)
-			break;
-		delay(100);
-	}
-	if (retry == 0) {
-		printf("WARNING: SATA PHY power-on failed\n");
-	}
-}
-
-#ifdef TEGRA_XUSBPAD_DEBUG
-static void
-padregdump(void)
-{
-	bus_space_tag_t bst;
-	bus_space_handle_t bsh;
-	bus_size_t i;
-	u_int j;
-
-	tegra_xusbpad_get_bs(&bst, &bsh);
-
-	for (i = 0x000; i < 0x160; ) {
-		printf("0x%03jx:", (uintmax_t)i);
-		for (j = 0; i < 0x160 && j < 0x10; j += 4, i += 4) {
-			printf(" %08x", bus_space_read_4(bst, bsh, i));
-		}
-		printf("\n");
+	if (xusbpad_ops == NULL || xusbpad_ops->sata_enable == NULL) {
+		aprint_error("%s: could not enable SATA\n", __func__);
+		return;
 	}
+	xusbpad_ops->sata_enable(xusbpad_device);
 }
-#endif
 
 void
 tegra_xusbpad_xhci_enable(void)
 {
-	struct tegra_xusbpad_softc * const sc = xusbpad_softc;
-	const uint32_t skucalib = tegra_fuse_read(TEGRA_FUSE_SKU_CALIB_REG);
-#ifdef TEGRA_XUSBPAD_DEBUG
-	uint32_t val;
-#endif
-
-	if (sc == NULL) {
-		aprint_error("%s: xusbpad driver not loaded\n", __func__);
+	if (xusbpad_ops == NULL || xusbpad_ops->xhci_enable == NULL) {
+		aprint_error("%s: could not enable XHCI\n", __func__);
 		return;
 	}
-
-
-#ifdef TEGRA_XUSBPAD_DEBUG
-	padregdump(void);
-	printf("SKU CALIB 0x%x\n", skucalib);
-#endif
-	const uint32_t hcl[3] = {
-		(skucalib >>  0) & 0x3f,
-		(skucalib >> 15) & 0x3f,
-		(skucalib >> 15) & 0x3f,
-	};
-	const uint32_t hic = (skucalib >> 13) & 3;
-	const uint32_t hsl = (skucalib >> 11) & 3;
-	const uint32_t htra = (skucalib >> 7) & 0xf;
-
-
-#ifdef TEGRA_XUSBPAD_DEBUG
-	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PAD_MUX_REG);
-	device_printf(sc->sc_dev, "XUSB_PADCTL_USB2_PAD_MUX_REG is 0x%x\n", val);
-	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PORT_CAP_REG);
-	device_printf(sc->sc_dev, "XUSB_PADCTL_USB2_PORT_CAP_REG is 0x%x\n", val);
-	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_SS_PORT_MAP_REG);
-	device_printf(sc->sc_dev, "XUSB_PADCTL_SS_PORT_MAP_REG is 0x%x\n", val);
-#endif
-
-	bus_space_write_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PAD_MUX_REG, (0<<0)|(0<<2)|(1<<4));
-	bus_space_write_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PORT_CAP_REG, (1<<0)|(1<<4)|(1<<8));
-	bus_space_write_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_SS_PORT_MAP_REG, (2<<0)|(7<<4));
-
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_REG,
-	    __SHIFTIN(hsl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL) |
-	    __SHIFTIN(XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL,
-		      XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL),
-	    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL |
-	    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL);
-
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
-	    XUSB_PADCTL_USB2_OTG_PAD0_CTL0_REG,
-	    __SHIFTIN(hcl[0],
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL) |
-	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL,
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW) |
-	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(0),
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW),
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
-	    XUSB_PADCTL_USB2_OTG_PAD1_CTL0_REG,
-	    __SHIFTIN(hcl[1],
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL) |
-	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL,
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW) |
-	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(1),
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW),
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
-	    XUSB_PADCTL_USB2_OTG_PAD2_CTL0_REG,
-	    __SHIFTIN(hcl[2],
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL) |
-	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL,
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW) |
-	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(2),
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW),
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
-
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
-	    XUSB_PADCTL_USB2_OTG_PAD0_CTL1_REG,
-	    __SHIFTIN(htra,
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ) |
-	    __SHIFTIN(hic,
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP),
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
-	    XUSB_PADCTL_USB2_OTG_PAD1_CTL1_REG,
-	    __SHIFTIN(htra,
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ) |
-	    __SHIFTIN(hic,
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP),
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
-	    XUSB_PADCTL_USB2_OTG_PAD2_CTL1_REG,
-	    __SHIFTIN(htra,
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ) |
-	    __SHIFTIN(hic,
-		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP),
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP |
-	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP);
-
-	//tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_BATTERY_CHRG_BIASPAD_REG, 0, 1); /* PD_OTG */
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD0_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD1_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD2_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD0_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD1_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD2_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD0_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD1_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD2_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD0_CTL1_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD1_CTL1_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD2_CTL1_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_REG, 0, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_REG, 0, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD_TRK);
-
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG,
-	    0, XUSB_PADCTL_ELPG_PROGRAM_SSP0_ELPG_CLAMP_EN);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG,
-	    0, XUSB_PADCTL_ELPG_PROGRAM_SSP0_ELPG_CLAMP_EN_EARLY);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG,
-	    0, XUSB_PADCTL_ELPG_PROGRAM_SSP0_ELPG_VCORE_DOWN);
-
-	DELAY(200);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG, 0, __BIT(26));
-	DELAY(200);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG, 0, __BIT(25));
-	DELAY(200);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG, 0, __BIT(24));
-	DELAY(200);
-
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_OC_DET_REG, 0, __BITS(22,16));
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_OC_DET_REG, __BIT(4), 0);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_OC_DET_REG, __BIT(8), 0);
-	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_OC_DET_REG, __BIT(9), 0);
-
-#ifdef TEGRA_XUSBPAD_DEBUG
-	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PAD_MUX_REG);
-	device_printf(sc->sc_dev, "XUSB_PADCTL_USB2_PAD_MUX_REG is 0x%x\n", val);
-	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PORT_CAP_REG);
-	device_printf(sc->sc_dev, "XUSB_PADCTL_USB2_PORT_CAP_REG is 0x%x\n", val);
-	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_SS_PORT_MAP_REG);
-	device_printf(sc->sc_dev, "XUSB_PADCTL_SS_PORT_MAP_REG is 0x%x\n", val);
-
-	padregdump();
-#endif
+	xusbpad_ops->xhci_enable(xusbpad_device);
 }

Index: src/sys/arch/evbarm/conf/TEGRA
diff -u src/sys/arch/evbarm/conf/TEGRA:1.27 src/sys/arch/evbarm/conf/TEGRA:1.28
--- src/sys/arch/evbarm/conf/TEGRA:1.27	Fri Sep  8 10:17:18 2017
+++ src/sys/arch/evbarm/conf/TEGRA	Tue Sep 19 20:46:12 2017
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: TEGRA,v 1.27 2017/09/08 10:17:18 jmcneill Exp $
+#	$NetBSD: TEGRA,v 1.28 2017/09/19 20:46:12 jmcneill Exp $
 #
 #	NVIDIA Tegra family SoCs
 #
@@ -93,7 +93,7 @@ gpio*		at gpiobus?
 tegrampio*	at fdt?			# MPIO
 
 # XUSB PADCTL
-tegraxusbpad*	at fdt?			# XUSB PADCTL
+tegra124xusbpad*	at fdt?			# XUSB PADCTL
 
 # PCIE
 tegrapcie0	at fdt?			# PCIE

Added files:

Index: src/sys/arch/arm/nvidia/tegra124_xusbpad.c
diff -u /dev/null src/sys/arch/arm/nvidia/tegra124_xusbpad.c:1.1
--- /dev/null	Tue Sep 19 20:46:12 2017
+++ src/sys/arch/arm/nvidia/tegra124_xusbpad.c	Tue Sep 19 20:46:12 2017
@@ -0,0 +1,343 @@
+/* $NetBSD: tegra124_xusbpad.c,v 1.1 2017/09/19 20:46:12 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 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 <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: tegra124_xusbpad.c,v 1.1 2017/09/19 20:46:12 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <arm/nvidia/tegra_reg.h>
+#include <arm/nvidia/tegra_xusbpad.h>
+#include <arm/nvidia/tegra124_xusbpadreg.h>
+#include <arm/nvidia/tegra_var.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#define TEGRA_FUSE_SKU_CALIB_REG 0xf0
+
+static int	tegra124_xusbpad_match(device_t, cfdata_t, void *);
+static void	tegra124_xusbpad_attach(device_t, device_t, void *);
+static void	tegra124_xusbpad_sata_enable(device_t);
+static void	tegra124_xusbpad_xhci_enable(device_t);
+
+static const struct tegra_xusbpad_ops tegra124_xusbpad_ops = {
+	.sata_enable = tegra124_xusbpad_sata_enable,
+	.xhci_enable = tegra124_xusbpad_xhci_enable,
+};
+
+struct tegra124_xusbpad_softc {
+	device_t		sc_dev;
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_bsh;
+};
+
+#ifdef TEGRA_XUSBPAD_DEBUG
+static void	padregdump(void);
+#endif
+
+CFATTACH_DECL_NEW(tegra124_xusbpad, sizeof(struct tegra124_xusbpad_softc),
+	tegra124_xusbpad_match, tegra124_xusbpad_attach, NULL, NULL);
+
+static int
+tegra124_xusbpad_match(device_t parent, cfdata_t cf, void *aux)
+{
+	const char * const compatible[] =
+	    { "nvidia,tegra124-xusb-padctl", NULL };
+	struct fdt_attach_args * const faa = aux;
+
+	return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+tegra124_xusbpad_attach(device_t parent, device_t self, void *aux)
+{
+	struct tegra124_xusbpad_softc * const sc = device_private(self);
+	struct fdt_attach_args * const faa = aux;
+	bus_addr_t addr;
+	bus_size_t size;
+	int error;
+
+	if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
+		aprint_error(": couldn't get registers\n");
+		return;
+	}
+
+	sc->sc_dev = self;
+	sc->sc_bst = faa->faa_bst;
+	error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh);
+	if (error) {
+		aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error);
+		return;
+	}
+
+	aprint_naive("\n");
+	aprint_normal(": XUSB PADCTL\n");
+
+	tegra_xusbpad_register(self, &tegra124_xusbpad_ops);
+}
+
+static void
+tegra124_xusbpad_sata_enable(device_t dev)
+{
+	struct tegra124_xusbpad_softc * const sc = device_private(dev);
+	bus_space_tag_t bst = sc->sc_bst;
+	bus_space_handle_t bsh = sc->sc_bsh;
+	int retry;
+
+	tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_USB3_PAD_MUX_REG,
+	    __SHIFTIN(XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0_SATA,
+		      XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0) |
+	    XUSB_PADCTL_USB3_PAD_MUX_FORCE_SATA_PAD_IDDQ_DISABLE_MASK0,
+	    XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0);
+
+	tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_REG,
+	    0,
+	    XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ |
+	    XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD);
+	tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG,
+	    0,
+	    XUSB_PADCTL_IOPHY_PLL_S0_CTL1_IDDQ |
+	    XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PWR_OVRD);
+	tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG,
+	    XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE, 0);
+	tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG,
+	    XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST, 0);
+
+	for (retry = 1000; retry > 0; retry--) {
+		const uint32_t v = bus_space_read_4(bst, bsh,
+		    XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG);
+		if (v & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET)
+			break;
+		delay(100);
+	}
+	if (retry == 0) {
+		printf("WARNING: SATA PHY power-on failed\n");
+	}
+}
+
+#ifdef TEGRA_XUSBPAD_DEBUG
+static void
+padregdump(void)
+{
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+	bus_size_t i;
+	u_int j;
+
+	tegra124_xusbpad_get_bs(&bst, &bsh);
+
+	for (i = 0x000; i < 0x160; ) {
+		printf("0x%03jx:", (uintmax_t)i);
+		for (j = 0; i < 0x160 && j < 0x10; j += 4, i += 4) {
+			printf(" %08x", bus_space_read_4(bst, bsh, i));
+		}
+		printf("\n");
+	}
+}
+#endif
+
+static void
+tegra124_xusbpad_xhci_enable(device_t dev)
+{
+	struct tegra124_xusbpad_softc * const sc = device_private(dev);
+	const uint32_t skucalib = tegra_fuse_read(TEGRA_FUSE_SKU_CALIB_REG);
+#ifdef TEGRA_XUSBPAD_DEBUG
+	uint32_t val;
+#endif
+
+	if (sc == NULL) {
+		aprint_error("%s: xusbpad driver not loaded\n", __func__);
+		return;
+	}
+
+
+#ifdef TEGRA_XUSBPAD_DEBUG
+	padregdump(void);
+	printf("SKU CALIB 0x%x\n", skucalib);
+#endif
+	const uint32_t hcl[3] = {
+		(skucalib >>  0) & 0x3f,
+		(skucalib >> 15) & 0x3f,
+		(skucalib >> 15) & 0x3f,
+	};
+	const uint32_t hic = (skucalib >> 13) & 3;
+	const uint32_t hsl = (skucalib >> 11) & 3;
+	const uint32_t htra = (skucalib >> 7) & 0xf;
+
+
+#ifdef TEGRA_XUSBPAD_DEBUG
+	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PAD_MUX_REG);
+	device_printf(sc->sc_dev, "XUSB_PADCTL_USB2_PAD_MUX_REG is 0x%x\n", val);
+	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PORT_CAP_REG);
+	device_printf(sc->sc_dev, "XUSB_PADCTL_USB2_PORT_CAP_REG is 0x%x\n", val);
+	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_SS_PORT_MAP_REG);
+	device_printf(sc->sc_dev, "XUSB_PADCTL_SS_PORT_MAP_REG is 0x%x\n", val);
+#endif
+
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PAD_MUX_REG, (0<<0)|(0<<2)|(1<<4));
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PORT_CAP_REG, (1<<0)|(1<<4)|(1<<8));
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_SS_PORT_MAP_REG, (2<<0)|(7<<4));
+
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_REG,
+	    __SHIFTIN(hsl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL) |
+	    __SHIFTIN(XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL,
+		      XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL),
+	    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL |
+	    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL);
+
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
+	    XUSB_PADCTL_USB2_OTG_PAD0_CTL0_REG,
+	    __SHIFTIN(hcl[0],
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL) |
+	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL,
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW) |
+	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(0),
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW),
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
+	    XUSB_PADCTL_USB2_OTG_PAD1_CTL0_REG,
+	    __SHIFTIN(hcl[1],
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL) |
+	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL,
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW) |
+	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(1),
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW),
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
+	    XUSB_PADCTL_USB2_OTG_PAD2_CTL0_REG,
+	    __SHIFTIN(hcl[2],
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL) |
+	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL,
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW) |
+	    __SHIFTIN(XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(2),
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW),
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
+
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
+	    XUSB_PADCTL_USB2_OTG_PAD0_CTL1_REG,
+	    __SHIFTIN(htra,
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ) |
+	    __SHIFTIN(hic,
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP),
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
+	    XUSB_PADCTL_USB2_OTG_PAD1_CTL1_REG,
+	    __SHIFTIN(htra,
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ) |
+	    __SHIFTIN(hic,
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP),
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
+	    XUSB_PADCTL_USB2_OTG_PAD2_CTL1_REG,
+	    __SHIFTIN(htra,
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ) |
+	    __SHIFTIN(hic,
+		      XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP),
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP |
+	    XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP);
+
+	//tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_BATTERY_CHRG_BIASPAD_REG, 0, 1); /* PD_OTG */
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD0_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD1_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD2_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD0_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD1_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD2_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD0_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD1_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD2_CTL0_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD0_CTL1_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD1_CTL1_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_OTG_PAD2_CTL1_REG, 0, XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_REG, 0, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_REG, 0, XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD_TRK);
+
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG,
+	    0, XUSB_PADCTL_ELPG_PROGRAM_SSP0_ELPG_CLAMP_EN);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG,
+	    0, XUSB_PADCTL_ELPG_PROGRAM_SSP0_ELPG_CLAMP_EN_EARLY);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG,
+	    0, XUSB_PADCTL_ELPG_PROGRAM_SSP0_ELPG_VCORE_DOWN);
+
+	DELAY(200);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG, 0, __BIT(26));
+	DELAY(200);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG, 0, __BIT(25));
+	DELAY(200);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_ELPG_PROGRAM_REG, 0, __BIT(24));
+	DELAY(200);
+
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_OC_DET_REG, 0, __BITS(22,16));
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_OC_DET_REG, __BIT(4), 0);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_OC_DET_REG, __BIT(8), 0);
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_OC_DET_REG, __BIT(9), 0);
+
+#ifdef TEGRA_XUSBPAD_DEBUG
+	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PAD_MUX_REG);
+	device_printf(sc->sc_dev, "XUSB_PADCTL_USB2_PAD_MUX_REG is 0x%x\n", val);
+	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_USB2_PORT_CAP_REG);
+	device_printf(sc->sc_dev, "XUSB_PADCTL_USB2_PORT_CAP_REG is 0x%x\n", val);
+	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XUSB_PADCTL_SS_PORT_MAP_REG);
+	device_printf(sc->sc_dev, "XUSB_PADCTL_SS_PORT_MAP_REG is 0x%x\n", val);
+
+	padregdump();
+#endif
+}
Index: src/sys/arch/arm/nvidia/tegra124_xusbpadreg.h
diff -u /dev/null src/sys/arch/arm/nvidia/tegra124_xusbpadreg.h:1.1
--- /dev/null	Tue Sep 19 20:46:12 2017
+++ src/sys/arch/arm/nvidia/tegra124_xusbpadreg.h	Tue Sep 19 20:46:12 2017
@@ -0,0 +1,161 @@
+/* $NetBSD: tegra124_xusbpadreg.h,v 1.1 2017/09/19 20:46:12 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 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_TEGRA_XUSBPADCTLREG_H
+#define _ARM_TEGRA_XUSBPADCTLREG_H
+
+#define XUSB_PADCTL_BOOT_MEDIA_REG			0x000
+#define XUSB_PADCTL_USB2_PAD_MUX_REG			0x004
+#define XUSB_PADCTL_USB2_PORT_CAP_REG			0x008
+#define XUSB_PADCTL_SNPS_OC_MAP_REG			0x00c
+#define XUSB_PADCTL_USB2_OC_MAP_REG			0x010
+#define XUSB_PADCTL_SS_PORT_MAP_REG			0x014
+#define XUSB_PADCTL_OC_DET_REG				0x018
+#define XUSB_PADCTL_ELPG_PROGRAM_REG			0x01c
+#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD0_CTL0_REG	0x020
+#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD0_CTL1_REG	0x024
+#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD1_CTL0_REG	0x028
+#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD1_CTL1_REG	0x02c
+#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD2_CTL0_REG	0x030
+#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD2_CTL1_REG	0x034
+#define XUSB_PADCTL_USB2_BATTERY_CHRG_BIASPAD_REG	0x038
+#define XUSB_PADCTL_USB2_BATTERY_CHRG_TDCD_DBNC_TIMER_REG 0x03c
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REG		0x040
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REG		0x044
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL3_REG		0x048
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL4_REG		0x04c
+#define XUSB_PADCTL_IOPHY_USB3_PAD0_CTL1_REG		0x050
+#define XUSB_PADCTL_IOPHY_USB3_PAD1_CTL1_REG		0x054
+#define XUSB_PADCTL_IOPHY_USB3_PAD0_CTL2_REG		0x058
+#define XUSB_PADCTL_IOPHY_USB3_PAD1_CTL2_REG		0x05c
+#define XUSB_PADCTL_IOPHY_USB3_PAD0_CTL3_REG		0x060
+#define XUSB_PADCTL_IOPHY_USB3_PAD1_CTL3_REG		0x064
+#define XUSB_PADCTL_IOPHY_USB3_PAD0_CTL4_REG		0x068
+#define XUSB_PADCTL_IOPHY_USB3_PAD1_CTL4_REG		0x06c
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P0_CTL1_REG		0x070
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P1_CTL1_REG		0x074
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P0_CTL2_REG		0x078
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P1_CTL2_REG		0x07c
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P0_CTL3_REG		0x080
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P1_CTL3_REG		0x084
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P0_CTL4_REG		0x088
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P1_CTL4_REG		0x08c
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P0_CTL5_REG		0x090
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P1_CTL5_REG		0x094
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P0_CTL6_REG		0x098
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P1_CTL6_REG		0x09c
+#define XUSB_PADCTL_USB2_OTG_PAD0_CTL0_REG		0x0a0
+#define XUSB_PADCTL_USB2_OTG_PAD1_CTL0_REG		0x0a4
+#define XUSB_PADCTL_USB2_OTG_PAD2_CTL0_REG		0x0a8
+#define XUSB_PADCTL_USB2_OTG_PAD0_CTL1_REG		0x0ac
+#define XUSB_PADCTL_USB2_OTG_PAD1_CTL1_REG		0x0b0
+#define XUSB_PADCTL_USB2_OTG_PAD2_CTL1_REG		0x0b4
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_REG		0x0b8
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_REG		0x0bc
+#define XUSB_PADCTL_HSIC_PAD0_CTL0_REG			0x0c0
+#define XUSB_PADCTL_HSIC_PAD1_CTL0_REG			0x0c4
+#define XUSB_PADCTL_HSIC_PAD0_CTL1_REG			0x0c8
+#define XUSB_PADCTL_HSIC_PAD1_CTL1_REG			0x0cc
+#define XUSB_PADCTL_HSIC_PAD0_CTL2_REG			0x0d0
+#define XUSB_PADCTL_HSIC_PAD1_CTL2_REG			0x0d4
+#define XUSB_PADCTL_ULPI_LINK_TRIM_CONTROL_REG		0x0d8
+#define XUSB_PADCTL_ULPI_NULL_CLK_TRIM_CONTROL_REG	0x0dc
+#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_REG		0x0e0
+#define XUSB_PADCTL_WAKE_CTRL_REG			0x0e4
+#define XUSB_PADCTL_PM_SPARE_REG			0x0e8
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P2_CTL1_REG		0x0ec
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P3_CTL1_REG		0x0f0
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P4_CTL1_REG		0x0f4
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P2_CTL2_REG		0x0f8
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P3_CTL2_REG		0x0fc
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P4_CTL2_REG		0x100
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P2_CTL3_REG		0x104
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P3_CTL3_REG		0x108
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P4_CTL3_REG		0x10c
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P2_CTL4_REG		0x110
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P3_CTL4_REG		0x114
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P4_CTL4_REG		0x118
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P2_CTL5_REG		0x11c
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P3_CTL5_REG		0x120
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P4_CTL5_REG		0x124
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P2_CTL6_REG		0x128
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P3_CTL6_REG		0x12c
+#define XUSB_PADCTL_IOPHY_MISC_PAD_P4_CTL6_REG		0x130
+#define XUSB_PADCTL_USB3_PAD_MUX_REG			0x134
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG		0x138
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_REG		0x13c
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3_REG		0x140
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL4_REG		0x144
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_REG		0x148
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2_REG		0x14c
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL3_REG		0x150
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL4_REG		0x154
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5_REG		0x158
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6_REG		0x15c
+
+#define XUSB_PADCTL_ELPG_PROGRAM_SSP0_ELPG_VCORE_DOWN		__BIT(18)
+#define XUSB_PADCTL_ELPG_PROGRAM_SSP0_ELPG_CLAMP_EN_EARLY	__BIT(17)
+#define XUSB_PADCTL_ELPG_PROGRAM_SSP0_ELPG_CLAMP_EN		__BIT(16)
+
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI 			__BIT(21)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2			__BIT(20)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD			__BIT(19)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW			__BITS(15,14)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(pad)		((pad >= 1) ? 0x0 : 0x3)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW			__BITS(11,6)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL		0x0e
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL		__BITS(5,0)
+
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP		__BITS(10,9)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ		__BITS(6,3)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR			__BIT(2)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP	__BIT(1)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP	__BIT(0)
+
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD_TRK			__BIT(13)
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD			__BIT(12)
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL		__BITS(4,2)
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL	0x5
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL		__BITS(1,0)
+
+#define XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0		__BITS(27,26)
+#define XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0_PCIE	0
+#define XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0_USB3_SS	1
+#define XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0_SATA	2
+#define XUSB_PADCTL_USB3_PAD_MUX_FORCE_SATA_PAD_IDDQ_DISABLE_MASK0 __BIT(6)
+
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET	__BIT(27)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE		__BIT(24)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PWR_OVRD		__BIT(3)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST		__BIT(1)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_IDDQ		__BIT(0)
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD	__BIT(1)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ		__BIT(0)
+
+#endif /* _ARM_TEGRA_XUSBPADCTLREG_H */
Index: src/sys/arch/arm/nvidia/tegra_xusbpad.h
diff -u /dev/null src/sys/arch/arm/nvidia/tegra_xusbpad.h:1.1
--- /dev/null	Tue Sep 19 20:46:12 2017
+++ src/sys/arch/arm/nvidia/tegra_xusbpad.h	Tue Sep 19 20:46:12 2017
@@ -0,0 +1,42 @@
+/* $NetBSD: tegra_xusbpad.h,v 1.1 2017/09/19 20:46:12 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared 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_TEGRA_XUSBPAD_H
+#define _ARM_TEGRA_XUSBPAD_H
+
+struct tegra_xusbpad_ops {
+	void	(*sata_enable)(device_t);
+	void	(*xhci_enable)(device_t);
+};
+
+void	tegra_xusbpad_register(device_t, const struct tegra_xusbpad_ops *);
+
+void	tegra_xusbpad_sata_enable(void);
+void	tegra_xusbpad_xhci_enable(void);
+
+#endif /* _ARM_TEGRA_XUSBPAD_H */

Reply via email to