Module Name:    src
Committed By:   jmcneill
Date:           Sat May  9 18:56:51 UTC 2015

Modified Files:
        src/sys/arch/arm/nvidia: tegra_car.c tegra_carreg.h tegra_ehci.c
            tegra_var.h
Added Files:
        src/sys/arch/arm/nvidia: tegra_ehcireg.h

Log Message:
Tegra USB PHY support


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/nvidia/tegra_car.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/nvidia/tegra_carreg.h
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/nvidia/tegra_ehci.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/nvidia/tegra_ehcireg.h
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/arm/nvidia/tegra_var.h

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/tegra_car.c
diff -u src/sys/arch/arm/nvidia/tegra_car.c:1.5 src/sys/arch/arm/nvidia/tegra_car.c:1.6
--- src/sys/arch/arm/nvidia/tegra_car.c:1.5	Sat May  9 11:17:59 2015
+++ src/sys/arch/arm/nvidia/tegra_car.c	Sat May  9 18:56:51 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_car.c,v 1.5 2015/05/09 11:17:59 jmcneill Exp $ */
+/* $NetBSD: tegra_car.c,v 1.6 2015/05/09 18:56:51 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
@@ -29,7 +29,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_car.c,v 1.5 2015/05/09 11:17:59 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_car.c,v 1.6 2015/05/09 18:56:51 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -283,3 +283,91 @@ tegra_car_periph_sdmmc_set_div(u_int por
 
 	return 0;
 }
+
+int
+tegra_car_periph_usb_enable(u_int port)
+{
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+	bus_size_t rst_reg, enb_reg;
+	uint32_t dev_bit;
+
+	tegra_car_get_bs(&bst, &bsh);
+	switch (port) {
+	case 0:
+		rst_reg = CAR_RST_DEV_L_SET_REG;
+		enb_reg = CAR_CLK_ENB_L_SET_REG;
+		dev_bit = CAR_DEV_L_USBD;
+		break;
+	case 1:
+		rst_reg = CAR_RST_DEV_H_SET_REG;
+		enb_reg = CAR_CLK_ENB_H_SET_REG;
+		dev_bit = CAR_DEV_H_USB2;
+		break;
+	case 2:
+		rst_reg = CAR_RST_DEV_H_SET_REG;
+		enb_reg = CAR_CLK_ENB_H_SET_REG;
+		dev_bit = CAR_DEV_H_USB3;
+		break;
+	default:
+		return EINVAL;
+	}
+
+	/* enter reset */
+	bus_space_write_4(bst, bsh, rst_reg, dev_bit);
+	/* enable clk */
+	bus_space_write_4(bst, bsh, enb_reg, dev_bit);
+
+	/* leave reset */
+	bus_space_write_4(bst, bsh, rst_reg+4, dev_bit);
+
+	return 0;
+}
+
+void
+tegra_car_utmip_init(void)
+{
+	const u_int enable_dly_count = 0x02;
+	const u_int stable_count = 0x33;
+	const u_int active_dly_count = 0x09;
+	const u_int xtal_freq_count = 0x7f;
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+
+	tegra_car_get_bs(&bst, &bsh);
+
+	tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG2_REG,
+	    __SHIFTIN(stable_count, CAR_UTMIP_PLL_CFG2_STABLE_COUNT) |
+	    __SHIFTIN(active_dly_count, CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT),
+	    CAR_UTMIP_PLL_CFG2_STABLE_COUNT |
+	    CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT);
+
+	tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG,
+	    __SHIFTIN(enable_dly_count, CAR_UTMIP_PLL_CFG1_ENABLE_DLY_COUNT) |
+	    __SHIFTIN(xtal_freq_count, CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT),
+	    CAR_UTMIP_PLL_CFG1_ENABLE_DLY_COUNT |
+	    CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT);
+
+	tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG,
+	    0,
+	    CAR_UTMIP_PLL_CFG1_PLLU_POWERDOWN |
+	    CAR_UTMIP_PLL_CFG1_PLL_ENABLE_POWERDOWN);
+}
+
+void
+tegra_car_utmip_enable(u_int port)
+{
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+	uint32_t bit = 0;
+
+	tegra_car_get_bs(&bst, &bsh);
+
+	switch (port) {
+	case 0:	bit = CAR_UTMIP_PLL_CFG2_PD_SAMP_A_POWERDOWN; break;
+	case 1:	bit = CAR_UTMIP_PLL_CFG2_PD_SAMP_B_POWERDOWN; break;
+	case 2:	bit = CAR_UTMIP_PLL_CFG2_PD_SAMP_C_POWERDOWN; break;
+	}
+
+	tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG2_REG, 0, bit);
+}

Index: src/sys/arch/arm/nvidia/tegra_carreg.h
diff -u src/sys/arch/arm/nvidia/tegra_carreg.h:1.6 src/sys/arch/arm/nvidia/tegra_carreg.h:1.7
--- src/sys/arch/arm/nvidia/tegra_carreg.h:1.6	Sat May  9 11:17:59 2015
+++ src/sys/arch/arm/nvidia/tegra_carreg.h	Sat May  9 18:56:51 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_carreg.h,v 1.6 2015/05/09 11:17:59 jmcneill Exp $ */
+/* $NetBSD: tegra_carreg.h,v 1.7 2015/05/09 18:56:51 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
@@ -213,4 +213,24 @@
 #define CAR_DEV_H_AHBDMA		__BIT(1)
 #define CAR_DEV_H_MEM			__BIT(0)
 
+#define CAR_UTMIP_PLL_CFG0_REG		0x480
+
+#define CAR_UTMIP_PLL_CFG1_REG		0x484
+#define CAR_UTMIP_PLL_CFG1_ENABLE_DLY_COUNT	__BITS(31,27)
+#define CAR_UTMIP_PLL_CFG1_PLLU_POWERUP		__BIT(17)
+#define CAR_UTMIP_PLL_CFG1_PLLU_POWERDOWN	__BIT(16)
+#define CAR_UTMIP_PLL_CFG1_PLL_ENABLE_POWERUP 	__BIT(15)
+#define CAR_UTMIP_PLL_CFG1_PLL_ENABLE_POWERDOWN	__BIT(14)
+#define CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT	__BITS(11,0)
+
+#define CAR_UTMIP_PLL_CFG2_REG		0x488
+#define CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT	__BITS(23,18)
+#define CAR_UTMIP_PLL_CFG2_STABLE_COUNT		__BITS(17,6)
+#define CAR_UTMIP_PLL_CFG2_PD_SAMP_C_POWERUP	__BIT(5)
+#define CAR_UTMIP_PLL_CFG2_PD_SAMP_C_POWERDOWN	__BIT(4)
+#define CAR_UTMIP_PLL_CFG2_PD_SAMP_B_POWERUP	__BIT(3)
+#define CAR_UTMIP_PLL_CFG2_PD_SAMP_B_POWERDOWN	__BIT(2)
+#define CAR_UTMIP_PLL_CFG2_PD_SAMP_A_POWERUP	__BIT(1)
+#define CAR_UTMIP_PLL_CFG2_PD_SAMP_A_POWERDOWN	__BIT(0)
+
 #endif /* _ARM_TEGRA_CARREG_H */

Index: src/sys/arch/arm/nvidia/tegra_ehci.c
diff -u src/sys/arch/arm/nvidia/tegra_ehci.c:1.3 src/sys/arch/arm/nvidia/tegra_ehci.c:1.4
--- src/sys/arch/arm/nvidia/tegra_ehci.c:1.3	Sat May  9 12:07:52 2015
+++ src/sys/arch/arm/nvidia/tegra_ehci.c	Sat May  9 18:56:51 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_ehci.c,v 1.3 2015/05/09 12:07:52 jmcneill Exp $ */
+/* $NetBSD: tegra_ehci.c,v 1.4 2015/05/09 18:56:51 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
@@ -29,7 +29,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_ehci.c,v 1.3 2015/05/09 12:07:52 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_ehci.c,v 1.4 2015/05/09 18:56:51 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -46,19 +46,27 @@ __KERNEL_RCSID(0, "$NetBSD: tegra_ehci.c
 #include <dev/usb/ehcivar.h>
 
 #include <arm/nvidia/tegra_var.h>
+#include <arm/nvidia/tegra_ehcireg.h>
 
 #define TEGRA_EHCI_REG_OFFSET	0x100
 
 static int	tegra_ehci_match(device_t, cfdata_t, void *);
 static void	tegra_ehci_attach(device_t, device_t, void *);
 
+static void	tegra_ehci_init(struct ehci_softc *);
+
 struct tegra_ehci_softc {
 	struct ehci_softc	sc;
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_bsh;
 	void			*sc_ih;
+	u_int			sc_port;
 
 	struct tegra_gpio_pin	*sc_pin_vbus;
 };
 
+static void	tegra_ehci_utmip_init(struct tegra_ehci_softc *);
+
 CFATTACH_DECL2_NEW(tegra_ehci, sizeof(struct tegra_ehci_softc),
 	tegra_ehci_match, tegra_ehci_attach, NULL,
 	ehci_activate, NULL, ehci_childdet);
@@ -79,11 +87,16 @@ tegra_ehci_attach(device_t parent, devic
 	const char *pin;
 	int error;
 
+	sc->sc_bst = tio->tio_bst;
+	bus_space_subregion(tio->tio_bst, tio->tio_bsh,
+	    loc->loc_offset, loc->loc_size, &sc->sc_bsh);
+	sc->sc_port = loc->loc_port;
+
 	sc->sc.sc_dev = self;
 	sc->sc.sc_bus.hci_private = &sc->sc;
 	sc->sc.sc_bus.dmatag = tio->tio_dmat;
 	sc->sc.sc_bus.usbrev = USBREV_2_0;
-	sc->sc.sc_flags = EHCIF_ETTF;
+	sc->sc.sc_flags = 0;	/* XXX EHCIF_ETTF */
 	sc->sc.sc_id_vendor = 0x10de;
 	strlcpy(sc->sc.sc_vendor, "Tegra", sizeof(sc->sc.sc_vendor));
 	sc->sc.sc_size = loc->loc_size;
@@ -91,15 +104,27 @@ tegra_ehci_attach(device_t parent, devic
 	bus_space_subregion(tio->tio_bst, tio->tio_bsh,
 	    loc->loc_offset + TEGRA_EHCI_REG_OFFSET,
 	    loc->loc_size - TEGRA_EHCI_REG_OFFSET, &sc->sc.ioh);
+	sc->sc.sc_vendor_init = tegra_ehci_init;
 
 	aprint_naive("\n");
 	aprint_normal(": USB%d\n", loc->loc_port + 1);
 
+	tegra_car_periph_usb_enable(sc->sc_port);
+	delay(2);
+
+	tegra_ehci_utmip_init(sc);
+
 	if (prop_dictionary_get_cstring_nocopy(prop, "vbus-gpio", &pin)) {
-		sc->sc_pin_vbus = tegra_gpio_acquire(pin,
-		    GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN);
-		if (sc->sc_pin_vbus)
-			tegra_gpio_write(sc->sc_pin_vbus, 1);
+		const uint32_t v = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+		    TEGRA_EHCI_PHY_VBUS_SENSORS_REG);
+		if ((v & TEGRA_EHCI_PHY_VBUS_SENSORS_A_VBUS_VLD_STS) == 0) {
+			sc->sc_pin_vbus = tegra_gpio_acquire(pin,
+			    GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN);
+			if (sc->sc_pin_vbus)
+				tegra_gpio_write(sc->sc_pin_vbus, 1);
+		} else {
+			aprint_normal_dev(self, "VBUS input active\n");
+		}
         }
 
 	sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
@@ -121,3 +146,168 @@ tegra_ehci_attach(device_t parent, devic
 
 	sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint);
 }
+
+static void
+tegra_ehci_init(struct ehci_softc *esc)
+{
+	struct tegra_ehci_softc * const sc = device_private(esc->sc_dev);
+	uint32_t usbmode;
+
+	usbmode = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+	    TEGRA_EHCI_USBMODE_REG);
+
+	const u_int cm = __SHIFTOUT(usbmode, TEGRA_EHCI_USBMODE_CM);
+	if (cm != TEGRA_EHCI_USBMODE_CM_HOST) {
+		aprint_verbose_dev(esc->sc_dev, "switching to host mode\n");
+		usbmode &= ~TEGRA_EHCI_USBMODE_CM;
+		usbmode |= __SHIFTIN(TEGRA_EHCI_USBMODE_CM_HOST,
+				     TEGRA_EHCI_USBMODE_CM);
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+		    TEGRA_EHCI_USBMODE_REG, usbmode);
+	}
+
+	/* Parallel transceiver select */
+	tegra_reg_set_clear(sc->sc_bst, sc->sc_bsh,
+	    TEGRA_EHCI_HOSTPC1_DEVLC_REG,
+	    __SHIFTIN(TEGRA_EHCI_HOSTPC1_DEVLC_PTS_UTMI,
+		      TEGRA_EHCI_HOSTPC1_DEVLC_PTS),
+	    TEGRA_EHCI_HOSTPC1_DEVLC_PTS |
+	    TEGRA_EHCI_HOSTPC1_DEVLC_STS);
+
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, TEGRA_EHCI_TXFILLTUNING_REG,
+	    __SHIFTIN(0x10, TEGRA_EHCI_TXFILLTUNING_TXFIFOTHRES));
+}
+
+static void
+tegra_ehci_utmip_init(struct tegra_ehci_softc *sc)
+{
+	bus_space_tag_t bst = sc->sc_bst;
+	bus_space_handle_t bsh = sc->sc_bsh;
+	int retry;
+
+	/* Put UTMIP PHY into reset before programming UTMIP config registers */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_SUSP_CTRL_REG,
+	    TEGRA_EHCI_SUSP_CTRL_UTMIP_RESET, 0);
+
+	/* Enable UTMIP PHY mode */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_SUSP_CTRL_REG,
+	    TEGRA_EHCI_SUSP_CTRL_UTMIP_PHY_ENB, 0);
+
+	/* Stop crystal clock */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_MISC_CFG1_REG,
+	    0, TEGRA_EHCI_UTMIP_MISC_CFG1_PHY_XTAL_CLOCKEN);
+	delay(1);
+
+	/* Clear session status */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_PHY_VBUS_SENSORS_REG,
+	    0,
+	    TEGRA_EHCI_PHY_VBUS_SENSORS_B_VLD_SW_VALUE |
+	    TEGRA_EHCI_PHY_VBUS_SENSORS_B_VLD_SW_EN);
+
+	/* PLL configuration */
+	tegra_car_utmip_init();
+
+	/* Transceiver configuration */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_XCVR_CFG0_REG,
+	    __SHIFTIN(4, TEGRA_EHCI_UTMIP_XCVR_CFG0_SETUP) |
+	    __SHIFTIN(3, TEGRA_EHCI_UTMIP_XCVR_CFG0_SETUP_MSB) |
+	    __SHIFTIN(8, TEGRA_EHCI_UTMIP_XCVR_CFG0_HSSLEW_MSB),
+	    TEGRA_EHCI_UTMIP_XCVR_CFG0_SETUP |
+	    TEGRA_EHCI_UTMIP_XCVR_CFG0_SETUP_MSB |
+	    TEGRA_EHCI_UTMIP_XCVR_CFG0_HSSLEW_MSB);
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_XCVR_CFG1_REG,
+	    __SHIFTIN(7, TEGRA_EHCI_UTMIP_XCVR_CFG1_TERM_RANGE_ADJ),
+	    TEGRA_EHCI_UTMIP_XCVR_CFG1_TERM_RANGE_ADJ);
+
+	if (sc->sc_port == 0) {
+		tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_BIAS_CFG0_REG,
+		    TEGRA_EHCI_UTMIP_BIAS_CFG0_HSDISCON_LEVEL_MSB |
+		    __SHIFTIN(2, TEGRA_EHCI_UTMIP_BIAS_CFG0_HSDISCON_LEVEL),
+		    TEGRA_EHCI_UTMIP_BIAS_CFG0_HSDISCON_LEVEL); 
+	}
+
+	/* Misc config */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_MISC_CFG0_REG,
+	    0,
+	    TEGRA_EHCI_UTMIP_MISC_CFG0_SUSPEND_EXIT_ON_EDGE);
+
+	/* BIAS cell power down lag */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_BIAS_CFG1_REG,
+	    __SHIFTIN(6, TEGRA_EHCI_UTMIP_BIAS_CFG1_PDTRK_COUNT),
+	    TEGRA_EHCI_UTMIP_BIAS_CFG1_PDTRK_COUNT);
+
+	/* Debounce config */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_DEBOUNCE_CFG0_REG,
+	    __SHIFTIN(0x73f4, TEGRA_EHCI_UTMIP_DEBOUNCE_CFG0_A),
+	    TEGRA_EHCI_UTMIP_DEBOUNCE_CFG0_A);
+
+	/* Transmit signal preamble config */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_TX_CFG0_REG,
+	    TEGRA_EHCI_UTMIP_TX_CFG0_FS_PREAMBLE_J, 0);
+
+	/* Power-down battery charger circuit */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_BAT_CHRG_CFG0_REG,
+	    TEGRA_EHCI_UTMIP_BAT_CHRG_CFG0_PD_CHRG, 0);
+
+	/* Select low speed bias method */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_XCVR_CFG0_REG,
+	    0, TEGRA_EHCI_UTMIP_XCVR_CFG0_LSBIAS_SEL);
+
+	/* High speed receive config */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_HSRX_CFG0_REG,
+	    __SHIFTIN(17, TEGRA_EHCI_UTMIP_HSRX_CFG0_IDLE_WAIT) |
+	    __SHIFTIN(16, TEGRA_EHCI_UTMIP_HSRX_CFG0_ELASTIC_LIMIT),
+	    TEGRA_EHCI_UTMIP_HSRX_CFG0_IDLE_WAIT |
+	    TEGRA_EHCI_UTMIP_HSRX_CFG0_ELASTIC_LIMIT);
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_HSRX_CFG1_REG,
+	    __SHIFTIN(9, TEGRA_EHCI_UTMIP_HSRX_CFG1_SYNC_START_DLY),
+	    TEGRA_EHCI_UTMIP_HSRX_CFG1_SYNC_START_DLY);
+
+	/* Start crystal clock */
+	delay(1);
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_MISC_CFG1_REG,
+	    TEGRA_EHCI_UTMIP_MISC_CFG1_PHY_XTAL_CLOCKEN, 0);
+
+	/* Clear port PLL powerdown status */
+	tegra_car_utmip_enable(sc->sc_port);
+
+	/* Bring UTMIP PHY out of reset */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_SUSP_CTRL_REG,
+	    0, TEGRA_EHCI_SUSP_CTRL_UTMIP_RESET);
+	for (retry = 100000; retry > 0; retry--) {
+		const uint32_t susp = bus_space_read_4(bst, bsh,
+		    TEGRA_EHCI_SUSP_CTRL_REG);
+		if (susp & TEGRA_EHCI_SUSP_CTRL_PHY_CLK_VALID)
+			break;
+		delay(1);
+	}
+	if (retry == 0) {
+		aprint_error_dev(sc->sc.sc_dev, "PHY clock is not valid\n");
+		return;
+	}
+
+	/* Disable ICUSB transceiver */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_ICUSB_CTRL_REG,
+	    0,
+	    TEGRA_EHCI_ICUSB_CTRL_ENB1);
+
+	/* Power up UTMPI transceiver */
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_XCVR_CFG0_REG,
+	    0,
+	    TEGRA_EHCI_UTMIP_XCVR_CFG0_PD_POWERDOWN |
+	    TEGRA_EHCI_UTMIP_XCVR_CFG0_PD2_POWERDOWN |
+	    TEGRA_EHCI_UTMIP_XCVR_CFG0_PDZI_POWERDOWN);
+	tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_XCVR_CFG1_REG,
+	    0,
+	    TEGRA_EHCI_UTMIP_XCVR_CFG1_PDDISC_POWERDOWN |
+	    TEGRA_EHCI_UTMIP_XCVR_CFG1_PDCHRP_POWERDOWN |
+	    TEGRA_EHCI_UTMIP_XCVR_CFG1_PDDR_POWERDOWN);
+
+	if (sc->sc_port == 0) {
+		tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_BIAS_CFG0_REG,
+		    0, TEGRA_EHCI_UTMIP_BIAS_CFG0_BIASPD);
+		delay(25);
+		tegra_reg_set_clear(bst, bsh, TEGRA_EHCI_UTMIP_BIAS_CFG1_REG,
+		    0, TEGRA_EHCI_UTMIP_BIAS_CFG1_PDTRK_POWERDOWN);
+	}
+}

Index: src/sys/arch/arm/nvidia/tegra_var.h
diff -u src/sys/arch/arm/nvidia/tegra_var.h:1.10 src/sys/arch/arm/nvidia/tegra_var.h:1.11
--- src/sys/arch/arm/nvidia/tegra_var.h:1.10	Sat May  9 11:17:59 2015
+++ src/sys/arch/arm/nvidia/tegra_var.h	Sat May  9 18:56:51 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_var.h,v 1.10 2015/05/09 11:17:59 jmcneill Exp $ */
+/* $NetBSD: tegra_var.h,v 1.11 2015/05/09 18:56:51 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
@@ -81,6 +81,9 @@ u_int	tegra_car_pllp0_rate(void);
 u_int	tegra_car_uart_rate(u_int);
 u_int	tegra_car_periph_sdmmc_rate(u_int);
 int	tegra_car_periph_sdmmc_set_div(u_int, u_int);
+int	tegra_car_periph_usb_enable(u_int);
+void	tegra_car_utmip_init(void);
+void	tegra_car_utmip_enable(u_int);
 
 struct tegra_gpio_pin;
 struct tegra_gpio_pin *tegra_gpio_acquire(const char *, u_int);

Added files:

Index: src/sys/arch/arm/nvidia/tegra_ehcireg.h
diff -u /dev/null src/sys/arch/arm/nvidia/tegra_ehcireg.h:1.1
--- /dev/null	Sat May  9 18:56:51 2015
+++ src/sys/arch/arm/nvidia/tegra_ehcireg.h	Sat May  9 18:56:51 2015
@@ -0,0 +1,113 @@
+/* $NetBSD: tegra_ehcireg.h,v 1.1 2015/05/09 18:56:51 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_EHCIREG_H
+#define _ARM_TEGRA_EHCIREG_H
+
+#define TEGRA_EHCI_TXFILLTUNING_REG		0x154
+#define TEGRA_EHCI_TXFILLTUNING_TXFIFOTHRES	__BITS(21,16)
+
+#define TEGRA_EHCI_ICUSB_CTRL_REG		0x15c
+#define TEGRA_EHCI_ICUSB_CTRL_ENB1		__BIT(3)
+#define TEGRA_EHCI_ICUSB_CTRL_VDD1		__BITS(2,0)
+
+#define TEGRA_EHCI_HOSTPC1_DEVLC_REG		0x1b4
+#define TEGRA_EHCI_HOSTPC1_DEVLC_PTS		__BITS(31,29)
+#define TEGRA_EHCI_HOSTPC1_DEVLC_PTS_UTMI	0
+#define TEGRA_EHCI_HOSTPC1_DEVLC_PTS_ULPI	2
+#define TEGRA_EHCI_HOSTPC1_DEVLC_PTS_ICUSB_SER	3
+#define TEGRA_EHCI_HOSTPC1_DEVLC_STS		__BIT(28)
+
+#define TEGRA_EHCI_USBMODE_REG			0x1f8
+#define TEGRA_EHCI_USBMODE_CM			__BITS(1,0)
+#define TEGRA_EHCI_USBMODE_CM_IDLE		0
+#define TEGRA_EHCI_USBMODE_CM_DEVICE		2
+#define TEGRA_EHCI_USBMODE_CM_HOST		3
+
+#define TEGRA_EHCI_SUSP_CTRL_REG		0x400
+#define TEGRA_EHCI_SUSP_CTRL_UHSIC_RESET	__BIT(14)
+#define TEGRA_EHCI_SUSP_CTRL_ULPI_PHY_ENB	__BIT(13)
+#define TEGRA_EHCI_SUSP_CTRL_UTMIP_PHY_ENB	__BIT(12)
+#define TEGRA_EHCI_SUSP_CTRL_UTMIP_RESET	__BIT(11)
+#define TEGRA_EHCI_SUSP_CTRL_PHY_CLK_VALID	__BIT(7)
+
+#define TEGRA_EHCI_PHY_VBUS_SENSORS_REG		0x404
+#define TEGRA_EHCI_PHY_VBUS_SENSORS_A_VBUS_VLD_STS __BIT(26)
+#define TEGRA_EHCI_PHY_VBUS_SENSORS_B_VLD_SW_VALUE __BIT(12)
+#define TEGRA_EHCI_PHY_VBUS_SENSORS_B_VLD_SW_EN	__BIT(11)
+
+#define TEGRA_EHCI_UTMIP_XCVR_CFG0_REG		0x808
+#define TEGRA_EHCI_UTMIP_XCVR_CFG0_HSSLEW_MSB	__BITS(31,25)
+#define TEGRA_EHCI_UTMIP_XCVR_CFG0_SETUP_MSB	__BITS(24,22)
+#define TEGRA_EHCI_UTMIP_XCVR_CFG0_LSBIAS_SEL	__BIT(21)
+#define TEGRA_EHCI_UTMIP_XCVR_CFG0_SETUP	__BITS(3,0)
+#define TEGRA_EHCI_UTMIP_XCVR_CFG0_PDZI_POWERDOWN __BIT(18)
+#define TEGRA_EHCI_UTMIP_XCVR_CFG0_PD2_POWERDOWN __BIT(16)
+#define TEGRA_EHCI_UTMIP_XCVR_CFG0_PD_POWERDOWN	__BIT(14)
+
+#define TEGRA_EHCI_UTMIP_BIAS_CFG0_REG		0x80c
+#define TEGRA_EHCI_UTMIP_BIAS_CFG0_HSDISCON_LEVEL_MSB __BIT(24)
+#define TEGRA_EHCI_UTMIP_BIAS_CFG0_BIASPD	__BIT(10)
+#define TEGRA_EHCI_UTMIP_BIAS_CFG0_HSDISCON_LEVEL __BITS(3,2)
+
+#define TEGRA_EHCI_UTMIP_TX_CFG0_REG		0x820
+#define TEGRA_EHCI_UTMIP_TX_CFG0_FS_PREAMBLE_J	__BIT(19)
+
+#define TEGRA_EHCI_UTMIP_MISC_CFG0_REG		0x824
+#define TEGRA_EHCI_UTMIP_MISC_CFG0_SUSPEND_EXIT_ON_EDGE __BIT(22)
+
+#define TEGRA_EHCI_UTMIP_MISC_CFG1_REG		0x828
+#define TEGRA_EHCI_UTMIP_MISC_CFG1_PHY_XTAL_CLOCKEN __BIT(30)
+
+#define TEGRA_EHCI_UTMIP_DEBOUNCE_CFG0_REG	0x82c
+#define TEGRA_EHCI_UTMIP_DEBOUNCE_CFG0_B	__BITS(31,16)
+#define TEGRA_EHCI_UTMIP_DEBOUNCE_CFG0_A	__BITS(15,0)
+
+#define TEGRA_EHCI_UTMIP_BAT_CHRG_CFG0_REG	0x830
+#define TEGRA_EHCI_UTMIP_BAT_CHRG_CFG0_PD_CHRG	__BIT(0)
+
+#define TEGRA_EHCI_UTMIP_SPARE_CFG0_REG		0x834
+
+#define TEGRA_EHCI_UTMIP_XCVR_CFG1_REG		0x838
+#define TEGRA_EHCI_UTMIP_XCVR_CFG1_TERM_RANGE_ADJ __BITS(21,18)
+#define TEGRA_EHCI_UTMIP_XCVR_CFG1_PDDR_POWERDOWN __BIT(4)
+#define TEGRA_EHCI_UTMIP_XCVR_CFG1_PDCHRP_POWERDOWN __BIT(2)
+#define TEGRA_EHCI_UTMIP_XCVR_CFG1_PDDISC_POWERDOWN __BIT(0)
+
+#define TEGRA_EHCI_UTMIP_BIAS_CFG1_REG		0x83c
+#define TEGRA_EHCI_UTMIP_BIAS_CFG1_PDTRK_COUNT	__BITS(7,3)
+#define TEGRA_EHCI_UTMIP_BIAS_CFG1_PDTRK_POWERDOWN __BIT(0)
+
+#define TEGRA_EHCI_UTMIP_HSRX_CFG0_REG		0xc08
+#define TEGRA_EHCI_UTMIP_HSRX_CFG0_IDLE_WAIT	__BITS(19,15)
+#define TEGRA_EHCI_UTMIP_HSRX_CFG0_ELASTIC_LIMIT __BITS(14,10)
+
+#define TEGRA_EHCI_UTMIP_HSRX_CFG1_REG		0xc0c
+#define TEGRA_EHCI_UTMIP_HSRX_CFG1_SYNC_START_DLY __BITS(5,1)
+
+#endif /* _ARM_TEGRA_EHCIREG_H */

Reply via email to