Module Name: src
Committed By: jmcneill
Date: Wed Oct 30 21:41:40 UTC 2019
Modified Files:
src/sys/arch/arm/ti: files.ti omap3_cm.c ti_prcm.h
Added Files:
src/sys/arch/arm/ti: ti_ehci.c ti_usb.c ti_usbtll.c
Log Message:
Add OMAP3 USB support.
To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/arm/ti/files.ti
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/ti/omap3_cm.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/ti/ti_ehci.c \
src/sys/arch/arm/ti/ti_usb.c src/sys/arch/arm/ti/ti_usbtll.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/ti/ti_prcm.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/ti/files.ti
diff -u src/sys/arch/arm/ti/files.ti:1.16 src/sys/arch/arm/ti/files.ti:1.17
--- src/sys/arch/arm/ti/files.ti:1.16 Tue Oct 29 22:19:13 2019
+++ src/sys/arch/arm/ti/files.ti Wed Oct 30 21:41:40 2019
@@ -1,4 +1,4 @@
-# $NetBSD: files.ti,v 1.16 2019/10/29 22:19:13 jmcneill Exp $
+# $NetBSD: files.ti,v 1.17 2019/10/30 21:41:40 jmcneill Exp $
#
file arch/arm/ti/ti_cpufreq.c soc_ti
@@ -88,6 +88,17 @@ device tiotg { } : fdt
attach tiotg at fdt with ti_otg
file arch/arm/ti/ti_otg.c ti_otg
+device tiusb { } : fdt
+attach tiusb at fdt with ti_usb
+file arch/arm/ti/ti_usb.c ti_usb
+
+device tiusbtll
+attach tiusbtll at fdt with ti_usbtll
+file arch/arm/ti/ti_usbtll.c ti_usbtll
+
+attach ehci at fdt with ti_ehci
+file arch/arm/ti/ti_ehci.c ti_ehci
+
attach motg at fdt with ti_motg
file arch/arm/ti/ti_motg.c ti_motg
Index: src/sys/arch/arm/ti/omap3_cm.c
diff -u src/sys/arch/arm/ti/omap3_cm.c:1.1 src/sys/arch/arm/ti/omap3_cm.c:1.2
--- src/sys/arch/arm/ti/omap3_cm.c:1.1 Tue Oct 29 22:19:13 2019
+++ src/sys/arch/arm/ti/omap3_cm.c Wed Oct 30 21:41:40 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: omap3_cm.c,v 1.1 2019/10/29 22:19:13 jmcneill Exp $ */
+/* $NetBSD: omap3_cm.c,v 1.2 2019/10/30 21:41:40 jmcneill Exp $ */
/*-
* Copyright (c) 2017 Jared McNeill <[email protected]>
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: omap3_cm.c,v 1.1 2019/10/29 22:19:13 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: omap3_cm.c,v 1.2 2019/10/30 21:41:40 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -43,11 +43,20 @@ __KERNEL_RCSID(1, "$NetBSD: omap3_cm.c,v
#define CM_CORE1_BASE 0x0a00
#define CM_CORE3_BASE 0x0a08
#define CM_WKUP_BASE 0x0c00
+#define CM_CLK_CTRL_REG_BASE 0x0d00
#define CM_PER_BASE 0x1000
#define CM_USBHOST_BASE 0x1400
#define CM_FCLKEN 0x00
#define CM_ICLKEN 0x10
+#define CM_AUTOIDLE 0x30
+#define CM_CLKSEL 0x40
+
+#define CM_CLKEN2_PLL 0x04
+#define CM_IDLEST2_CKGEN 0x24
+#define CM_AUTOIDLE2_PLL 0x34
+#define CM_CLKSEL4_PLL 0x4c
+#define CM_CLKSEL5_PLL 0x50
static int omap3_cm_match(device_t, cfdata_t, void *);
static void omap3_cm_attach(device_t, device_t, void *);
@@ -71,19 +80,25 @@ omap3_cm_hwmod_enable(struct ti_prcm_sof
val &= ~tc->u.hwmod.mask;
PRCM_WRITE(sc, tc->u.hwmod.reg + CM_ICLKEN, val);
+ if (tc->u.hwmod.flags & TI_HWMOD_DISABLE_AUTOIDLE) {
+ val = PRCM_READ(sc, tc->u.hwmod.reg + CM_AUTOIDLE);
+ val &= ~tc->u.hwmod.mask;
+ PRCM_WRITE(sc, tc->u.hwmod.reg + CM_AUTOIDLE, val);
+ }
+
return 0;
}
-#define OMAP3_CM_HWMOD_CORE1(_name, _bit, _parent) \
- TI_PRCM_HWMOD_MASK((_name), CM_CORE1_BASE, __BIT(_bit), (_parent), omap3_cm_hwmod_enable)
-#define OMAP3_CM_HWMOD_CORE3(_name, _bit, _parent) \
- TI_PRCM_HWMOD_MASK((_name), CM_CORE3_BASE, __BIT(_bit), (_parent), omap3_cm_hwmod_enable)
-#define OMAP3_CM_HWMOD_WKUP(_name, _bit, _parent) \
- TI_PRCM_HWMOD_MASK((_name), CM_WKUP_BASE, __BIT(_bit), (_parent), omap3_cm_hwmod_enable)
-#define OMAP3_CM_HWMOD_PER(_name, _bit, _parent) \
- TI_PRCM_HWMOD_MASK((_name), CM_PER_BASE, __BIT(_bit), (_parent), omap3_cm_hwmod_enable)
-#define OMAP3_CM_HWMOD_USBHOST(_name, _mask, _parent) \
- TI_PRCM_HWMOD_MASK((_name), CM_USBHOST_BASE, (_mask), (_parent), omap3_cm_hwmod_enable)
+#define OMAP3_CM_HWMOD_CORE1(_name, _bit, _parent, _flags) \
+ TI_PRCM_HWMOD_MASK((_name), CM_CORE1_BASE, __BIT(_bit), (_parent), omap3_cm_hwmod_enable, (_flags))
+#define OMAP3_CM_HWMOD_CORE3(_name, _bit, _parent, _flags) \
+ TI_PRCM_HWMOD_MASK((_name), CM_CORE3_BASE, __BIT(_bit), (_parent), omap3_cm_hwmod_enable, (_flags))
+#define OMAP3_CM_HWMOD_WKUP(_name, _bit, _parent, _flags) \
+ TI_PRCM_HWMOD_MASK((_name), CM_WKUP_BASE, __BIT(_bit), (_parent), omap3_cm_hwmod_enable, (_flags))
+#define OMAP3_CM_HWMOD_PER(_name, _bit, _parent, _flags) \
+ TI_PRCM_HWMOD_MASK((_name), CM_PER_BASE, __BIT(_bit), (_parent), omap3_cm_hwmod_enable, (_flags))
+#define OMAP3_CM_HWMOD_USBHOST(_name, _bit, _parent, _flags) \
+ TI_PRCM_HWMOD_MASK((_name), CM_USBHOST_BASE, __BIT(_bit), (_parent), omap3_cm_hwmod_enable, (_flags))
static const char * const compatible[] = {
"ti,omap3-cm",
@@ -96,59 +111,79 @@ CFATTACH_DECL_NEW(omap3_cm, sizeof(struc
static struct ti_prcm_clk omap3_cm_clks[] = {
/* XXX until we get a proper clock tree */
TI_PRCM_FIXED("FIXED_32K", 32768),
- TI_PRCM_FIXED("FIXED_48MHZ", 48000000),
- TI_PRCM_FIXED("FIXED_96MHZ", 96000000),
- TI_PRCM_FIXED_FACTOR("PERIPH_CLK", 1, 1, "FIXED_48MHZ"),
- TI_PRCM_FIXED_FACTOR("MMC_CLK", 1, 1, "FIXED_96MHZ"),
-
- OMAP3_CM_HWMOD_CORE1("usb_otg_hs", 4, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("mcbsp1", 9, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("mcbsp5", 10, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("timer10", 11, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("timer11", 12, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("uart1", 13, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("uart2", 14, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("i2c1", 15, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("i2c2", 16, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("i2c3", 17, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("mcspi1", 18, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("mcspi2", 19, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("mcspi3", 20, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("mcspi4", 21, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("hdq1w", 22, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_CORE1("mmc1", 24, "MMC_CLK"),
- OMAP3_CM_HWMOD_CORE1("mmc2", 25, "MMC_CLK"),
- OMAP3_CM_HWMOD_CORE1("mmc3", 30, "MMC_CLK"),
-
- OMAP3_CM_HWMOD_CORE3("usb_tll_hs", 2, "PERIPH_CLK"),
-
- OMAP3_CM_HWMOD_WKUP("timer1", 0, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_WKUP("counter_32k", 2, "FIXED_32K"),
- OMAP3_CM_HWMOD_WKUP("gpio1", 3, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_WKUP("wd_timer2", 5, "FIXED_32K"),
-
- OMAP3_CM_HWMOD_PER("mcbsp2", 0, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("mcbsp3", 1, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("mcbsp4", 2, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("timer2", 3, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("timer3", 4, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("timer4", 5, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("timer5", 6, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("timer6", 7, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("timer7", 8, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("timer8", 9, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("timer9", 10, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("uart3", 11, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("wd_timer3", 12, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("gpio2", 13, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("gpio3", 14, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("gpio4", 15, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("gpio5", 16, "PERIPH_CLK"),
- OMAP3_CM_HWMOD_PER("gpio6", 17, "PERIPH_CLK"),
+ TI_PRCM_FIXED("SYS_CLK", 13000000),
+ TI_PRCM_FIXED("MMC_CLK", 96000000),
+ TI_PRCM_FIXED_FACTOR("PERIPH_CLK", 1, 1, "SYS_CLK"),
+
+ OMAP3_CM_HWMOD_CORE1("usb_otg_hs", 4, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("mcbsp1", 9, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("mcbsp5", 10, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("timer10", 11, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("timer11", 12, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("uart1", 13, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("uart2", 14, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("i2c1", 15, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("i2c2", 16, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("i2c3", 17, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("mcspi1", 18, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("mcspi2", 19, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("mcspi3", 20, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("mcspi4", 21, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("hdq1w", 22, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("mmc1", 24, "MMC_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("mmc2", 25, "MMC_CLK", 0),
+ OMAP3_CM_HWMOD_CORE1("mmc3", 30, "MMC_CLK", 0),
+
+ OMAP3_CM_HWMOD_CORE3("usb_tll_hs", 2, "PERIPH_CLK", TI_HWMOD_DISABLE_AUTOIDLE),
+
+ OMAP3_CM_HWMOD_WKUP("timer1", 0, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_WKUP("counter_32k", 2, "FIXED_32K", 0),
+ OMAP3_CM_HWMOD_WKUP("gpio1", 3, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_WKUP("wd_timer2", 5, "FIXED_32K", 0),
+
+ OMAP3_CM_HWMOD_PER("mcbsp2", 0, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("mcbsp3", 1, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("mcbsp4", 2, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("timer2", 3, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("timer3", 4, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("timer4", 5, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("timer5", 6, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("timer6", 7, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("timer7", 8, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("timer8", 9, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("timer9", 10, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("uart3", 11, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("wd_timer3", 12, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("gpio2", 13, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("gpio3", 14, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("gpio4", 15, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("gpio5", 16, "PERIPH_CLK", 0),
+ OMAP3_CM_HWMOD_PER("gpio6", 17, "PERIPH_CLK", 0),
- OMAP3_CM_HWMOD_USBHOST("usb_host_hs", __BITS(1,0), "PERIPH_CLK"),
+ OMAP3_CM_HWMOD_USBHOST("usb_host_hs", 0, "PERIPH_CLK", 0),
};
+static void
+omap3_cm_initclocks(struct ti_prcm_softc *sc)
+{
+ uint32_t val;
+
+ /* Select SYS_CLK for GPTIMER 2 and 3 */
+ val = PRCM_READ(sc, CM_PER_BASE + CM_CLKSEL);
+ val |= __BIT(0); /* CLKSEL_GPT2 0x1: source is SYS_CLK */
+ val |= __BIT(1); /* CLKSEL_GPT3 0x1: source is SYS_CLK */
+ PRCM_WRITE(sc, CM_PER_BASE + CM_CLKSEL, val);
+
+ /* Enable DPLL5 */
+ const u_int m = 443, n = 11, m2 = 4;
+ PRCM_WRITE(sc, CM_CLK_CTRL_REG_BASE + CM_CLKEN2_PLL, (0x4 << 4) | 0x7);
+ PRCM_WRITE(sc, CM_CLK_CTRL_REG_BASE + CM_CLKSEL4_PLL, (m << 8) | n);
+ PRCM_WRITE(sc, CM_CLK_CTRL_REG_BASE + CM_CLKSEL5_PLL, m2);
+ PRCM_WRITE(sc, CM_CLK_CTRL_REG_BASE + CM_AUTOIDLE2_PLL, 1);
+ while ((PRCM_READ(sc, CM_CLK_CTRL_REG_BASE + CM_IDLEST2_CKGEN) & 1) == 0)
+ delay(100);
+}
+
static int
omap3_cm_match(device_t parent, cfdata_t cf, void *aux)
{
@@ -177,6 +212,8 @@ omap3_cm_attach(device_t parent, device_
aprint_naive("\n");
aprint_normal(": OMAP3xxx CM\n");
+ omap3_cm_initclocks(sc);
+
clocks = of_find_firstchild_byname(sc->sc_phandle, "clocks");
if (clocks > 0)
fdt_add_bus(self, clocks, faa);
Index: src/sys/arch/arm/ti/ti_prcm.h
diff -u src/sys/arch/arm/ti/ti_prcm.h:1.3 src/sys/arch/arm/ti/ti_prcm.h:1.4
--- src/sys/arch/arm/ti/ti_prcm.h:1.3 Tue Oct 29 22:19:13 2019
+++ src/sys/arch/arm/ti/ti_prcm.h Wed Oct 30 21:41:40 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ti_prcm.h,v 1.3 2019/10/29 22:19:13 jmcneill Exp $ */
+/* $NetBSD: ti_prcm.h,v 1.4 2019/10/30 21:41:40 jmcneill Exp $ */
/*-
* Copyright (c) 2017 Jared McNeill <[email protected]>
@@ -57,8 +57,11 @@ struct ti_prcm_hwmod {
bus_size_t reg;
uint32_t mask;
const char *parent;
+ u_int flags;
};
+#define TI_HWMOD_DISABLE_AUTOIDLE 0x01
+
struct ti_prcm_clk {
struct clk base;
enum ti_prcm_clktype type;
@@ -138,13 +141,14 @@ ti_prcm_hwmod_get_parent(struct ti_prcm_
}
#define TI_PRCM_HWMOD(_name, _reg, _parent, _enable) \
- TI_PRCM_HWMOD_MASK(_name, _reg, 0, _parent, _enable)
+ TI_PRCM_HWMOD_MASK(_name, _reg, 0, _parent, _enable, 0)
-#define TI_PRCM_HWMOD_MASK(_name, _reg, _mask, _parent, _enable) \
+#define TI_PRCM_HWMOD_MASK(_name, _reg, _mask, _parent, _enable, _flags) \
{ \
.type = TI_PRCM_HWMOD, .base.name = (_name), \
.u.hwmod.reg = (_reg), \
.u.hwmod.mask = (_mask), \
+ .u.hwmod.flags = (_flags), \
.u.hwmod.parent = (_parent), \
.enable = (_enable), \
.get_parent = ti_prcm_hwmod_get_parent, \
Added files:
Index: src/sys/arch/arm/ti/ti_ehci.c
diff -u /dev/null src/sys/arch/arm/ti/ti_ehci.c:1.1
--- /dev/null Wed Oct 30 21:41:40 2019
+++ src/sys/arch/arm/ti/ti_ehci.c Wed Oct 30 21:41:40 2019
@@ -0,0 +1,157 @@
+/* $NetBSD: ti_ehci.c,v 1.1 2019/10/30 21:41:40 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015-2019 Jared 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 <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ti_ehci.c,v 1.1 2019/10/30 21:41:40 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 <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+#include <dev/usb/ehcireg.h>
+#include <dev/usb/ehcivar.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#define TI_EHCI_NPORTS 3
+
+static int ti_ehci_match(device_t, cfdata_t, void *);
+static void ti_ehci_attach(device_t, device_t, void *);
+
+CFATTACH_DECL2_NEW(ti_ehci, sizeof(struct ehci_softc),
+ ti_ehci_match, ti_ehci_attach, NULL,
+ ehci_activate, NULL, ehci_childdet);
+
+static int
+ti_ehci_match(device_t parent, cfdata_t cf, void *aux)
+{
+ const char * const compatible[] = {
+ "ti,ehci-omap",
+ NULL
+ };
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+ti_ehci_attach(device_t parent, device_t self, void *aux)
+{
+ struct ehci_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ struct fdtbus_reset *rst;
+ struct fdtbus_phy *phy;
+ struct clk *clk;
+ char intrstr[128];
+ bus_addr_t addr;
+ bus_size_t size;
+ int error;
+ void *ih;
+ u_int n;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+
+ /* Enable clocks */
+ for (n = 0; (clk = fdtbus_clock_get_index(phandle, n)) != NULL; n++)
+ if (clk_enable(clk) != 0) {
+ aprint_error(": couldn't enable clock #%d\n", n);
+ return;
+ }
+ /* De-assert resets */
+ for (n = 0; (rst = fdtbus_reset_get_index(phandle, n)) != NULL; n++)
+ if (fdtbus_reset_deassert(rst) != 0) {
+ aprint_error(": couldn't de-assert reset #%d\n", n);
+ return;
+ }
+
+ sc->sc_dev = self;
+ sc->sc_bus.ub_hcpriv = sc;
+ sc->sc_bus.ub_dmatag = faa->faa_dmat;
+ sc->sc_bus.ub_revision = USBREV_2_0;
+ if (of_hasprop(phandle, "has-transaction-translator"))
+ sc->sc_flags |= EHCIF_ETTF;
+ else
+ sc->sc_ncomp = 1;
+ sc->sc_size = size;
+ sc->iot = faa->faa_bst;
+ if (bus_space_map(sc->iot, addr, size, 0, &sc->ioh) != 0) {
+ aprint_error(": couldn't map registers\n");
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": EHCI\n");
+
+ /* Enable PHYs */
+ for (n = 0; n < TI_EHCI_NPORTS; n++) {
+ phy = fdtbus_phy_get_index(phandle, n);
+ if (phy && fdtbus_phy_enable(phy, true) != 0) {
+ aprint_error(": couldn't enable phy\n");
+ return;
+ }
+ }
+
+ /* Disable interrupts */
+ sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH);
+ EOWRITE4(sc, EHCI_USBINTR, 0);
+
+ if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(self, "failed to decode interrupt\n");
+ return;
+ }
+
+ ih = fdtbus_intr_establish(phandle, 0, IPL_USB, FDT_INTR_MPSAFE,
+ ehci_intr, sc);
+ if (ih == NULL) {
+ aprint_error_dev(self, "couldn't establish interrupt on %s\n",
+ intrstr);
+ return;
+ }
+ aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+ error = ehci_init(sc);
+ if (error) {
+ aprint_error_dev(self, "init failed, error = %d\n", error);
+ return;
+ }
+
+ pmf_device_register1(self, NULL, NULL, ehci_shutdown);
+
+ sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint);
+}
Index: src/sys/arch/arm/ti/ti_usb.c
diff -u /dev/null src/sys/arch/arm/ti/ti_usb.c:1.1
--- /dev/null Wed Oct 30 21:41:40 2019
+++ src/sys/arch/arm/ti/ti_usb.c Wed Oct 30 21:41:40 2019
@@ -0,0 +1,221 @@
+/* $NetBSD: ti_usb.c,v 1.1 2019/10/30 21:41:40 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jared 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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 <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ti_usb.c,v 1.1 2019/10/30 21:41:40 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/ti/ti_prcm.h>
+
+#define UHH_SYSCONFIG 0x10
+#define UHH_SYSCONFIG_MIDLEMODE_MASK 0x00003000
+#define UHH_SYSCONFIG_MIDLEMODE_SMARTSTANDBY 0x00002000
+#define UHH_SYSCONFIG_CLOCKACTIVITY 0x00000100
+#define UHH_SYSCONFIG_SIDLEMODE_MASK 0x00000018
+#define UHH_SYSCONFIG_SIDLEMODE_SMARTIDLE 0x00000008
+#define UHH_SYSCONFIG_ENAWAKEUP 0x00000004
+#define UHH_SYSCONFIG_SOFTRESET 0x00000002
+#define UHH_SYSCONFIG_AUTOIDLE 0x00000001
+
+#define UHH_HOSTCONFIG 0x40
+#define UHH_HOSTCONFIG_APP_START_CLK __BIT(31)
+#define UHH_HOSTCONFIG_P3_MODE __BITS(21,20)
+#define UHH_HOSTCONFIG_P2_MODE __BITS(19,18)
+#define UHH_HOSTCONFIG_P1_MODE __BITS(17,16)
+#define UHH_HOSTCONFIG_PMODE_ULPI_PHY 0
+#define UHH_HOSTCONFIG_PMODE_UTMI 1
+#define UHH_HOSTCONFIG_PMODE_HSIC 3
+#define UHH_HOSTCONFIG_P3_ULPI_BYPASS __BIT(12)
+#define UHH_HOSTCONFIG_P2_ULPI_BYPASS __BIT(11)
+#define UHH_HOSTCONFIG_P3_CONNECT_STATUS __BIT(10)
+#define UHH_HOSTCONFIG_P2_CONNECT_STATUS __BIT(9)
+#define UHH_HOSTCONFIG_P1_CONNECT_STATUS __BIT(8)
+#define UHH_HOSTCONFIG_ENA_INCR_ALIGN __BIT(5)
+#define UHH_HOSTCONFIG_ENA_INCR16 __BIT(4)
+#define UHH_HOSTCONFIG_ENA_INCR8 __BIT(3)
+#define UHH_HOSTCONFIG_ENA_INCR4 __BIT(2)
+#define UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN __BIT(1)
+#define UHH_HOSTCONFIG_P1_ULPI_BYPASS __BIT(0)
+
+extern void tl_usbtll_enable_port(u_int);
+
+static const char * const compatible[] = {
+ "ti,usbhs-host",
+ NULL
+};
+
+#define TI_USB_NPORTS 3
+
+enum {
+ CONNECT_STATUS,
+ ULPI_BYPASS,
+ TI_USB_NBITS
+};
+
+static const uint32_t ti_usb_portbits[TI_USB_NPORTS][TI_USB_NBITS] = {
+ [0] = {
+ [CONNECT_STATUS] = UHH_HOSTCONFIG_P1_CONNECT_STATUS,
+ [ULPI_BYPASS] = UHH_HOSTCONFIG_P1_ULPI_BYPASS,
+ },
+ [1] = {
+ [CONNECT_STATUS] = UHH_HOSTCONFIG_P2_CONNECT_STATUS,
+ [ULPI_BYPASS] = UHH_HOSTCONFIG_P2_ULPI_BYPASS,
+ },
+ [2] = {
+ [CONNECT_STATUS] = UHH_HOSTCONFIG_P3_CONNECT_STATUS,
+ [ULPI_BYPASS] = UHH_HOSTCONFIG_P3_ULPI_BYPASS,
+ },
+};
+
+enum {
+ PORT_UNUSED,
+ PORT_EHCI_PHY,
+ PORT_EHCI_TLL,
+ PORT_EHCI_HSIC,
+};
+
+struct ti_usb_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+
+ u_int sc_portmode[TI_USB_NPORTS];
+};
+
+static int ti_usb_match(device_t, cfdata_t, void *);
+static void ti_usb_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(ti_usb, sizeof(struct ti_usb_softc),
+ ti_usb_match, ti_usb_attach, NULL, NULL);
+
+#define RD4(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define WR4(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+
+static void
+ti_usb_init(struct ti_usb_softc *sc)
+{
+ uint32_t val;
+ int port;
+
+ val = RD4(sc, UHH_SYSCONFIG);
+ val &= ~(UHH_SYSCONFIG_SIDLEMODE_MASK|UHH_SYSCONFIG_MIDLEMODE_MASK);
+ val |= UHH_SYSCONFIG_MIDLEMODE_SMARTSTANDBY;
+ val |= UHH_SYSCONFIG_CLOCKACTIVITY;
+ val |= UHH_SYSCONFIG_SIDLEMODE_SMARTIDLE;
+ val |= UHH_SYSCONFIG_ENAWAKEUP;
+ val &= ~UHH_SYSCONFIG_AUTOIDLE;
+ WR4(sc, UHH_SYSCONFIG, val);
+
+ val = RD4(sc, UHH_SYSCONFIG);
+
+ val = RD4(sc, UHH_HOSTCONFIG);
+ val |= UHH_HOSTCONFIG_ENA_INCR16;
+ val |= UHH_HOSTCONFIG_ENA_INCR8;
+ val |= UHH_HOSTCONFIG_ENA_INCR4;
+ val |= UHH_HOSTCONFIG_APP_START_CLK;
+ val &= ~UHH_HOSTCONFIG_ENA_INCR_ALIGN;
+ for (port = 0; port < TI_USB_NPORTS; port++) {
+ if (sc->sc_portmode[port] == PORT_UNUSED)
+ val &= ~ti_usb_portbits[port][CONNECT_STATUS];
+ if (sc->sc_portmode[port] == PORT_EHCI_PHY)
+ val &= ~ti_usb_portbits[port][ULPI_BYPASS];
+ else
+ val |= ti_usb_portbits[port][ULPI_BYPASS];
+ }
+ WR4(sc, UHH_HOSTCONFIG, val);
+}
+
+static int
+ti_usb_match(device_t parent, cfdata_t match, void *aux)
+{
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+ti_usb_attach(device_t parent, device_t self, void *aux)
+{
+ struct ti_usb_softc *sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_addr_t addr;
+ bus_size_t size;
+ char propname[16];
+ const char *portmode;
+ int port;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+
+ if (ti_prcm_enable_hwmod(phandle, 0) != 0) {
+ aprint_error(": couldn't enable module\n");
+ return;
+ }
+
+ sc->sc_dev = self;
+ sc->sc_bst = faa->faa_bst;
+ if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+ aprint_error(": couldn't map registers\n");
+ return;
+ }
+
+ for (port = 0; port < TI_USB_NPORTS; port++) {
+ snprintf(propname, sizeof(propname), "port%d-mode", port + 1);
+ portmode = fdtbus_get_string(phandle, propname);
+ if (portmode == NULL)
+ continue;
+ if (strcmp(portmode, "ehci-phy") == 0)
+ sc->sc_portmode[port] = PORT_EHCI_PHY;
+ else if (strcmp(portmode, "ehci-tll") == 0)
+ sc->sc_portmode[port] = PORT_EHCI_TLL;
+ else if (strcmp(portmode, "ehci-hsic") == 0)
+ sc->sc_portmode[port] = PORT_EHCI_HSIC;
+
+ if (sc->sc_portmode[port] != PORT_UNUSED)
+ tl_usbtll_enable_port(port);
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": OMAP HS USB Host\n");
+
+ ti_usb_init(sc);
+
+ fdt_add_bus(self, phandle, faa);
+}
Index: src/sys/arch/arm/ti/ti_usbtll.c
diff -u /dev/null src/sys/arch/arm/ti/ti_usbtll.c:1.1
--- /dev/null Wed Oct 30 21:41:40 2019
+++ src/sys/arch/arm/ti/ti_usbtll.c Wed Oct 30 21:41:40 2019
@@ -0,0 +1,203 @@
+/* $NetBSD: ti_usbtll.c,v 1.1 2019/10/30 21:41:40 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jared 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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 <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ti_usbtll.c,v 1.1 2019/10/30 21:41:40 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/ti/ti_prcm.h>
+
+#define USBTLL_SYSCONFIG 0x10
+#define USBTLL_SYSCONFIG_CLOCKACTIVITY 0x00000100
+#define USBTLL_SYSCONFIG_SIDLEMODE 0x00000018
+#define USBTLL_SYSCONFIG_ENAWAKEUP 0x00000004
+#define USBTLL_SYSCONFIG_SOFTRESET 0x00000002
+#define USBTLL_SYSCONFIG_AUTOIDLE 0x00000001
+
+#define USBTLL_SYSSTATUS 0x14
+#define USBTLL_SYSSTATUS_RESETDONE 0x00000001
+
+#define USBTLL_SHARED_CONF 0x30
+#define USBTLL_SHARED_CONF_USB_90D_DDR_EN 0x00000040
+#define USBTLL_SHARED_CONF_USB_180D_SDR_EN 0x00000020
+#define USBTLL_SHARED_CONF_USB_DIVRATIO 0x0000001c
+#define USBTLL_SHARED_CONF_FCLK_REQ 0x00000002
+#define USBTLL_SHARED_CONF_FCLK_IS_ON 0x00000001
+
+#define USBTLL_CHANNEL_CONF(i) (0x40 + (0x04 * (i)))
+#define USBTLL_CHANNEL_CONF_FSLSLINESTATE 0x30000000
+#define USBTLL_CHANNEL_CONF_FSLSMODE 0x0f000000
+#define USBTLL_CHANNEL_CONF_TESTTXSE0 0x00100000
+#define USBTLL_CHANNEL_CONF_TESTTXDAT 0x00080000
+#define USBTLL_CHANNEL_CONF_TESTTXEN 0x00040000
+#define USBTLL_CHANNEL_CONF_TESTEN 0x00020000
+#define USBTLL_CHANNEL_CONF_DRVVBUS 0x00010000
+#define USBTLL_CHANNEL_CONF_CHRGVBUS 0x00008000
+#define USBTLL_CHANNEL_CONF_ULPINOBITSTUFF 0x00000800
+#define USBTLL_CHANNEL_CONF_ULPIAUTOIDLE 0x00000400
+#define USBTLL_CHANNEL_CONF_UTMIAUTOIDLE 0x00000200
+#define USBTLL_CHANNEL_CONF_ULPIDDRMODE 0x00000100
+#define USBTLL_CHANNEL_CONF_ULPIOUTCLKMODE 0x00000080
+#define USBTLL_CHANNEL_CONF_TLLFULLSPEED 0x00000040
+#define USBTLL_CHANNEL_CONF_TLLCONNECT 0x00000020
+#define USBTLL_CHANNEL_CONF_TLLATTACH 0x00000010
+#define USBTLL_CHANNEL_CONF_UTMIISADEV 0x00000008
+#define USBTLL_CHANNEL_CONF_CHANMODE 0x00000006
+#define USBTLL_CHANNEL_CONF_CHANEN 0x00000001
+
+static const char * const compatible[] = {
+ "ti,usbhs-tll",
+ NULL
+};
+
+struct ti_usbtll_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+};
+
+static int ti_usbtll_match(device_t, cfdata_t, void *);
+static void ti_usbtll_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(ti_usbtll, sizeof(struct ti_usbtll_softc),
+ ti_usbtll_match, ti_usbtll_attach, NULL, NULL);
+
+#define RD4(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define WR4(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+
+static struct ti_usbtll_softc *ti_usbtll_sc = NULL;
+
+void tl_usbtll_enable_port(u_int);
+
+void
+tl_usbtll_enable_port(u_int port)
+{
+ struct ti_usbtll_softc *sc = ti_usbtll_sc;
+ uint32_t val;
+
+ if (sc == NULL) {
+ printf("%s: driver not loaded\n", __func__);
+ return;
+ }
+
+ val = RD4(sc, USBTLL_CHANNEL_CONF(port));
+ val &= ~(USBTLL_CHANNEL_CONF_ULPINOBITSTUFF|
+ USBTLL_CHANNEL_CONF_ULPIAUTOIDLE|
+ USBTLL_CHANNEL_CONF_ULPIDDRMODE);
+ val |= USBTLL_CHANNEL_CONF_CHANEN;
+ WR4(sc, USBTLL_CHANNEL_CONF(port), val);
+}
+
+static void
+ti_usbtll_reset(struct ti_usbtll_softc *sc)
+{
+ uint32_t val;
+ int retry = 5000;
+
+ WR4(sc, USBTLL_SYSCONFIG, USBTLL_SYSCONFIG_SOFTRESET);
+ do {
+ val = RD4(sc, USBTLL_SYSSTATUS);
+ if (val & USBTLL_SYSSTATUS_RESETDONE)
+ break;
+ delay(10);
+ } while (--retry > 0);
+ if (retry == 0)
+ aprint_error_dev(sc->sc_dev, "reset timeout\n");
+}
+
+static void
+ti_usbtll_init(struct ti_usbtll_softc *sc)
+{
+ uint32_t val;
+
+ ti_usbtll_reset(sc);
+
+ val = USBTLL_SYSCONFIG_ENAWAKEUP |
+ USBTLL_SYSCONFIG_AUTOIDLE |
+ USBTLL_SYSCONFIG_SIDLEMODE |
+ USBTLL_SYSCONFIG_CLOCKACTIVITY;
+ WR4(sc, USBTLL_SYSCONFIG, val);
+
+ val = RD4(sc, USBTLL_SHARED_CONF);
+ val |= (USBTLL_SHARED_CONF_FCLK_IS_ON | (1 << 2));
+ val &= ~USBTLL_SHARED_CONF_USB_90D_DDR_EN;
+ val &= ~USBTLL_SHARED_CONF_USB_180D_SDR_EN;
+ WR4(sc, USBTLL_SHARED_CONF, val);
+}
+
+static int
+ti_usbtll_match(device_t parent, cfdata_t match, void *aux)
+{
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+ti_usbtll_attach(device_t parent, device_t self, void *aux)
+{
+ struct ti_usbtll_softc *sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_addr_t addr;
+ bus_size_t size;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+
+ if (ti_prcm_enable_hwmod(phandle, 0) != 0) {
+ aprint_error(": couldn't enable module\n");
+ return;
+ }
+
+ sc->sc_dev = self;
+ sc->sc_bst = faa->faa_bst;
+ if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+ aprint_error(": couldn't map registers\n");
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": OMAP HS USB Host TLL\n");
+
+ ti_usbtll_init(sc);
+
+ if (ti_usbtll_sc == NULL)
+ ti_usbtll_sc = sc;
+}