Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107430108
D5881.id39797.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
D5881.id39797.diff
View Options
Index: sys/arm/allwinner/aw_usbphy.c
===================================================================
--- sys/arm/allwinner/aw_usbphy.c
+++ sys/arm/allwinner/aw_usbphy.c
@@ -156,6 +156,18 @@
#define CLR4(res, o, m) WR4(res, o, RD4(res, o) & ~(m))
#define SET4(res, o, m) WR4(res, o, RD4(res, o) | (m))
+#define PHY_CSR 0x00
+#define ID_PULLUP_EN (1 << 17)
+#define DPDM_PULLUP_EN (1 << 16)
+#define FORCE_ID (0x3 << 14)
+#define FORCE_ID_SHIFT 14
+#define FORCE_ID_LOW 2
+#define FORCE_VBUS_VALID (0x3 << 12)
+#define FORCE_VBUS_VALID_SHIFT 12
+#define FORCE_VBUS_VALID_HIGH 3
+#define VBUS_CHANGE_DET (1 << 6)
+#define ID_CHANGE_DET (1 << 5)
+#define DPDM_CHANGE_DET (1 << 4)
#define OTG_PHY_CFG 0x20
#define OTG_PHY_ROUTE_OTG (1 << 0)
#define PMU_IRQ_ENABLE 0x00
@@ -189,6 +201,7 @@
struct awusbphy_softc *sc;
phandle_t node;
char pname[20];
+ uint32_t val;
int error, off, rid;
regulator_t reg;
hwreset_t rst;
@@ -264,6 +277,16 @@
}
}
+ /* Enable OTG PHY for host mode */
+ val = bus_read_4(sc->phy_ctrl, PHY_CSR);
+ val &= ~(VBUS_CHANGE_DET | ID_CHANGE_DET | DPDM_CHANGE_DET);
+ val |= (ID_PULLUP_EN | DPDM_PULLUP_EN);
+ val &= ~FORCE_ID;
+ val |= (FORCE_ID_LOW << FORCE_ID_SHIFT);
+ val &= ~FORCE_VBUS_VALID;
+ val |= (FORCE_VBUS_VALID_HIGH << FORCE_VBUS_VALID_SHIFT);
+ bus_write_4(sc->phy_ctrl, PHY_CSR, val);
+
return (0);
}
Index: sys/arm/allwinner/files.allwinner
===================================================================
--- sys/arm/allwinner/files.allwinner
+++ sys/arm/allwinner/files.allwinner
@@ -27,6 +27,7 @@
dev/iicbus/twsi/a10_twsi.c optional twsi
dev/usb/controller/generic_ohci.c optional ohci
dev/usb/controller/generic_usb_if.m optional ohci
+dev/usb/controller/musb_otg_allwinner.c optional musb
arm/allwinner/aw_sid.c standard
arm/allwinner/aw_thermal.c standard
dev/iicbus/sy8106a.c optional sy8106a
Index: sys/arm64/conf/GENERIC
===================================================================
--- sys/arm64/conf/GENERIC
+++ sys/arm64/conf/GENERIC
@@ -162,6 +162,7 @@
device aw_ehci # Allwinner EHCI USB interface (USB 2.0)
device aw_usbphy # Allwinner USB PHY
device dwcotg # DWC OTG controller
+device musb # Mentor Graphics USB OTG controller
device ohci # OHCI USB interface
device ehci # EHCI USB interface (USB 2.0)
device ehci_mv # Marvell EHCI USB interface
Index: sys/conf/files.arm64
===================================================================
--- sys/conf/files.arm64
+++ sys/conf/files.arm64
@@ -200,6 +200,8 @@
dev/usb/controller/generic_ehci.c optional ehci acpi
dev/usb/controller/generic_ohci.c optional ohci fdt
dev/usb/controller/generic_usb_if.m optional ohci fdt
+dev/usb/controller/musb_otg.c optional musb
+dev/usb/controller/musb_otg_allwinner.c optional musb fdt
dev/usb/controller/xhci_mv.c optional xhci_mv fdt
dev/vnic/mrml_bridge.c optional vnic fdt
dev/vnic/nic_main.c optional vnic pci
Index: sys/dev/usb/controller/musb_otg.c
===================================================================
--- sys/dev/usb/controller/musb_otg.c
+++ sys/dev/usb/controller/musb_otg.c
@@ -3141,19 +3141,24 @@
MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
- /* read out number of endpoints */
+ if (sc->sc_ep_max == 0) {
+ /* read out number of endpoints */
+
+ nrx =
+ (MUSB2_READ_1(sc, MUSB2_REG_EPINFO) / 16);
- nrx =
- (MUSB2_READ_1(sc, MUSB2_REG_EPINFO) / 16);
+ ntx =
+ (MUSB2_READ_1(sc, MUSB2_REG_EPINFO) % 16);
- ntx =
- (MUSB2_READ_1(sc, MUSB2_REG_EPINFO) % 16);
+ sc->sc_ep_max = (nrx > ntx) ? nrx : ntx;
+ } else {
+ nrx = ntx = sc->sc_ep_max;
+ }
/* these numbers exclude the control endpoint */
DPRINTFN(2, "RX/TX endpoints: %u/%u\n", nrx, ntx);
- sc->sc_ep_max = (nrx > ntx) ? nrx : ntx;
if (sc->sc_ep_max == 0) {
DPRINTFN(2, "ERROR: Looks like the clocks are off!\n");
}
Index: sys/dev/usb/controller/musb_otg_allwinner.c
===================================================================
--- /dev/null
+++ sys/dev/usb/controller/musb_otg_allwinner.c
@@ -0,0 +1,534 @@
+/*-
+ * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
+ * Copyright (c) 2018 Andrew Turner <andrew@FreeBSD.org>
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Allwinner USB Dual-Role Device (DRD) controller
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/condvar.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/musb_otg.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+
+#ifdef __arm__
+#include <arm/allwinner/allwinner_machdep.h>
+#include <arm/allwinner/a10_sramc.h>
+#endif
+
+#define DRD_EP_MAX 5
+
+#define MUSB2_REG_AWIN_VEND0 0x0043
+#define VEND0_PIO_MODE 0
+
+#if defined(__arm__)
+#define bs_parent_space(bs) ((bs)->bs_parent)
+typedef bus_space_tag_t awusb_bs_tag;
+#elif defined(__aarch64__)
+#define bs_parent_space(bs) (bs)
+typedef void * awusb_bs_tag;
+#endif
+
+#define AWUSB_OKAY 0x01
+#define AWUSB_NO_CONFDATA 0x02
+static struct ofw_compat_data compat_data[] = {
+ { "allwinner,sun4i-a10-musb", AWUSB_OKAY },
+ { "allwinner,sun6i-a31-musb", AWUSB_OKAY },
+ { "allwinner,sun8i-a33-musb", AWUSB_OKAY | AWUSB_NO_CONFDATA },
+ { NULL, 0 }
+};
+
+struct awusbdrd_softc {
+ struct musbotg_softc sc;
+ struct resource *res[2];
+ clk_t clk;
+ hwreset_t reset;
+ struct bus_space bs;
+ int flags;
+};
+
+static struct resource_spec awusbdrd_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+#define REMAPFLAG 0x8000
+#define REGDECL(a, b) [(a)] = ((b) | REMAPFLAG)
+
+/* Allwinner USB DRD register mappings */
+static const uint16_t awusbdrd_regmap[] = {
+ REGDECL(MUSB2_REG_EPFIFO(0), 0x0000),
+ REGDECL(MUSB2_REG_EPFIFO(1), 0x0004),
+ REGDECL(MUSB2_REG_EPFIFO(2), 0x0008),
+ REGDECL(MUSB2_REG_EPFIFO(3), 0x000c),
+ REGDECL(MUSB2_REG_EPFIFO(4), 0x0010),
+ REGDECL(MUSB2_REG_EPFIFO(5), 0x0014),
+ REGDECL(MUSB2_REG_POWER, 0x0040),
+ REGDECL(MUSB2_REG_DEVCTL, 0x0041),
+ REGDECL(MUSB2_REG_EPINDEX, 0x0042),
+ REGDECL(MUSB2_REG_INTTX, 0x0044),
+ REGDECL(MUSB2_REG_INTRX, 0x0046),
+ REGDECL(MUSB2_REG_INTTXE, 0x0048),
+ REGDECL(MUSB2_REG_INTRXE, 0x004a),
+ REGDECL(MUSB2_REG_INTUSB, 0x004c),
+ REGDECL(MUSB2_REG_INTUSBE, 0x0050),
+ REGDECL(MUSB2_REG_FRAME, 0x0054),
+ REGDECL(MUSB2_REG_TESTMODE, 0x007c),
+ REGDECL(MUSB2_REG_TXMAXP, 0x0080),
+ REGDECL(MUSB2_REG_TXCSRL, 0x0082),
+ REGDECL(MUSB2_REG_TXCSRH, 0x0083),
+ REGDECL(MUSB2_REG_RXMAXP, 0x0084),
+ REGDECL(MUSB2_REG_RXCSRL, 0x0086),
+ REGDECL(MUSB2_REG_RXCSRH, 0x0087),
+ REGDECL(MUSB2_REG_RXCOUNT, 0x0088),
+ REGDECL(MUSB2_REG_TXTI, 0x008c),
+ REGDECL(MUSB2_REG_TXNAKLIMIT, 0x008d),
+ REGDECL(MUSB2_REG_RXNAKLIMIT, 0x008d),
+ REGDECL(MUSB2_REG_RXTI, 0x008e),
+ REGDECL(MUSB2_REG_TXFIFOSZ, 0x0090),
+ REGDECL(MUSB2_REG_TXFIFOADD, 0x0092),
+ REGDECL(MUSB2_REG_RXFIFOSZ, 0x0094),
+ REGDECL(MUSB2_REG_RXFIFOADD, 0x0096),
+ REGDECL(MUSB2_REG_FADDR, 0x0098),
+ REGDECL(MUSB2_REG_TXFADDR(0), 0x0098),
+ REGDECL(MUSB2_REG_TXHADDR(0), 0x009a),
+ REGDECL(MUSB2_REG_TXHUBPORT(0), 0x009b),
+ REGDECL(MUSB2_REG_RXFADDR(0), 0x009c),
+ REGDECL(MUSB2_REG_RXHADDR(0), 0x009e),
+ REGDECL(MUSB2_REG_RXHUBPORT(0), 0x009f),
+ REGDECL(MUSB2_REG_TXFADDR(1), 0x0098),
+ REGDECL(MUSB2_REG_TXHADDR(1), 0x009a),
+ REGDECL(MUSB2_REG_TXHUBPORT(1), 0x009b),
+ REGDECL(MUSB2_REG_RXFADDR(1), 0x009c),
+ REGDECL(MUSB2_REG_RXHADDR(1), 0x009e),
+ REGDECL(MUSB2_REG_RXHUBPORT(1), 0x009f),
+ REGDECL(MUSB2_REG_TXFADDR(2), 0x0098),
+ REGDECL(MUSB2_REG_TXHADDR(2), 0x009a),
+ REGDECL(MUSB2_REG_TXHUBPORT(2), 0x009b),
+ REGDECL(MUSB2_REG_RXFADDR(2), 0x009c),
+ REGDECL(MUSB2_REG_RXHADDR(2), 0x009e),
+ REGDECL(MUSB2_REG_RXHUBPORT(2), 0x009f),
+ REGDECL(MUSB2_REG_TXFADDR(3), 0x0098),
+ REGDECL(MUSB2_REG_TXHADDR(3), 0x009a),
+ REGDECL(MUSB2_REG_TXHUBPORT(3), 0x009b),
+ REGDECL(MUSB2_REG_RXFADDR(3), 0x009c),
+ REGDECL(MUSB2_REG_RXHADDR(3), 0x009e),
+ REGDECL(MUSB2_REG_RXHUBPORT(3), 0x009f),
+ REGDECL(MUSB2_REG_TXFADDR(4), 0x0098),
+ REGDECL(MUSB2_REG_TXHADDR(4), 0x009a),
+ REGDECL(MUSB2_REG_TXHUBPORT(4), 0x009b),
+ REGDECL(MUSB2_REG_RXFADDR(4), 0x009c),
+ REGDECL(MUSB2_REG_RXHADDR(4), 0x009e),
+ REGDECL(MUSB2_REG_RXHUBPORT(4), 0x009f),
+ REGDECL(MUSB2_REG_TXFADDR(5), 0x0098),
+ REGDECL(MUSB2_REG_TXHADDR(5), 0x009a),
+ REGDECL(MUSB2_REG_TXHUBPORT(5), 0x009b),
+ REGDECL(MUSB2_REG_RXFADDR(5), 0x009c),
+ REGDECL(MUSB2_REG_RXHADDR(5), 0x009e),
+ REGDECL(MUSB2_REG_RXHUBPORT(5), 0x009f),
+ REGDECL(MUSB2_REG_CONFDATA, 0x00c0),
+};
+
+static bus_size_t
+awusbdrd_reg(bus_size_t o)
+{
+ bus_size_t v;
+
+ KASSERT(o < nitems(awusbdrd_regmap),
+ ("%s: Invalid register %#lx", __func__, o));
+ if (o >= nitems(awusbdrd_regmap))
+ return (o);
+
+ v = awusbdrd_regmap[o];
+
+ KASSERT((v & REMAPFLAG) != 0, ("%s: reg %#lx not in regmap",
+ __func__, o));
+
+ return (v & ~REMAPFLAG);
+}
+
+static int
+awusbdrd_filt(bus_size_t o)
+{
+ switch (o) {
+ case MUSB2_REG_MISC:
+ case MUSB2_REG_RXDBDIS:
+ case MUSB2_REG_TXDBDIS:
+ return (1);
+ default:
+ return (0);
+ }
+}
+
+static uint8_t
+awusbdrd_bs_r_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o)
+{
+ const struct bus_space *bs = t;
+
+ switch (o) {
+ case MUSB2_REG_HWVERS:
+ return (0); /* no known equivalent */
+ case MUSB2_REG_CONFDATA:
+ return (0xde);
+ }
+
+
+ return (bus_space_read_1(bs_parent_space(bs), h, awusbdrd_reg(o)));
+}
+
+static uint8_t
+awusbdrd_bs_r_1_noconf(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o)
+{
+
+ /*
+ * There is no confdata register on some SoCs, return the same
+ * magic value as Linux.
+ */
+ if (o == MUSB2_REG_CONFDATA)
+ return (0xde);
+
+ return (awusbdrd_bs_r_1(t, h, o));
+}
+
+
+static uint16_t
+awusbdrd_bs_r_2(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o)
+{
+ const struct bus_space *bs = t;
+
+ return bus_space_read_2(bs_parent_space(bs), h, awusbdrd_reg(o));
+}
+
+static void
+awusbdrd_bs_w_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
+ uint8_t v)
+{
+ const struct bus_space *bs = t;
+
+ if (awusbdrd_filt(o) != 0)
+ return;
+
+ bus_space_write_1(bs_parent_space(bs), h, awusbdrd_reg(o), v);
+}
+
+static void
+awusbdrd_bs_w_2(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
+ uint16_t v)
+{
+ const struct bus_space *bs = t;
+
+ if (awusbdrd_filt(o) != 0)
+ return;
+
+ bus_space_write_2(bs_parent_space(bs), h, awusbdrd_reg(o), v);
+}
+
+static void
+awusbdrd_bs_rm_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
+ uint8_t *d, bus_size_t c)
+{
+ const struct bus_space *bs = t;
+
+ bus_space_read_multi_1(bs_parent_space(bs), h, awusbdrd_reg(o), d, c);
+}
+
+static void
+awusbdrd_bs_rm_4(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
+ uint32_t *d, bus_size_t c)
+{
+ const struct bus_space *bs = t;
+
+ bus_space_read_multi_4(bs_parent_space(bs), h, awusbdrd_reg(o), d, c);
+}
+
+static void
+awusbdrd_bs_wm_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
+ const uint8_t *d, bus_size_t c)
+{
+ const struct bus_space *bs = t;
+
+ if (awusbdrd_filt(o) != 0)
+ return;
+
+ bus_space_write_multi_1(bs_parent_space(bs), h, awusbdrd_reg(o), d, c);
+}
+
+static void
+awusbdrd_bs_wm_4(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
+ const uint32_t *d, bus_size_t c)
+{
+ const struct bus_space *bs = t;
+
+ if (awusbdrd_filt(o) != 0)
+ return;
+
+ bus_space_write_multi_4(bs_parent_space(bs), h, awusbdrd_reg(o), d, c);
+}
+
+static void
+awusbdrd_intr(void *arg)
+{
+ struct awusbdrd_softc *sc = arg;
+ uint8_t intusb;
+ uint16_t inttx, intrx;
+
+ intusb = MUSB2_READ_1(&sc->sc, MUSB2_REG_INTUSB);
+ inttx = MUSB2_READ_2(&sc->sc, MUSB2_REG_INTTX);
+ intrx = MUSB2_READ_2(&sc->sc, MUSB2_REG_INTRX);
+ if (intusb == 0 && inttx == 0 && intrx == 0)
+ return;
+
+ if (intusb)
+ MUSB2_WRITE_1(&sc->sc, MUSB2_REG_INTUSB, intusb);
+ if (inttx)
+ MUSB2_WRITE_2(&sc->sc, MUSB2_REG_INTTX, inttx);
+ if (intrx)
+ MUSB2_WRITE_2(&sc->sc, MUSB2_REG_INTRX, intrx);
+
+ musbotg_interrupt(arg, intrx, inttx, intusb);
+}
+
+static int
+awusbdrd_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Allwinner USB DRD");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+awusbdrd_attach(device_t dev)
+{
+ struct awusbdrd_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ sc->flags = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+
+ error = bus_alloc_resources(dev, awusbdrd_spec, sc->res);
+ if (error != 0)
+ return (error);
+
+ /* AHB gate clock is required */
+ error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk);
+ if (error != 0)
+ goto fail;
+
+ /* AHB reset is only present on some SoCs */
+ (void)hwreset_get_by_ofw_idx(dev, 0, 0, &sc->reset);
+
+ /* Enable clocks */
+ error = clk_enable(sc->clk);
+ if (error != 0) {
+ device_printf(dev, "failed to enable clock: %d\n", error);
+ goto fail;
+ }
+ if (sc->reset != NULL) {
+ error = hwreset_deassert(sc->reset);
+ if (error != 0) {
+ device_printf(dev, "failed to de-assert reset: %d\n",
+ error);
+ goto fail;
+ }
+ }
+
+ sc->sc.sc_bus.parent = dev;
+ sc->sc.sc_bus.devices = sc->sc.sc_devices;
+ sc->sc.sc_bus.devices_max = MUSB2_MAX_DEVICES;
+ sc->sc.sc_bus.dma_bits = 32;
+
+ error = usb_bus_mem_alloc_all(&sc->sc.sc_bus, USB_GET_DMA_TAG(dev),
+ NULL);
+ if (error != 0) {
+ error = ENOMEM;
+ goto fail;
+ }
+
+#if defined(__arm__)
+ sc->bs.bs_parent = rman_get_bustag(sc->res[0]);
+#elif defined(__aarch64__)
+ sc->bs.bs_cookie = rman_get_bustag(sc->res[0]);
+#endif
+
+ if ((sc->flags & AWUSB_NO_CONFDATA) == AWUSB_NO_CONFDATA)
+ sc->bs.bs_r_1 = awusbdrd_bs_r_1_noconf;
+ else
+ sc->bs.bs_r_1 = awusbdrd_bs_r_1;
+ sc->bs.bs_r_2 = awusbdrd_bs_r_2;
+ sc->bs.bs_w_1 = awusbdrd_bs_w_1;
+ sc->bs.bs_w_2 = awusbdrd_bs_w_2;
+ sc->bs.bs_rm_1 = awusbdrd_bs_rm_1;
+ sc->bs.bs_rm_4 = awusbdrd_bs_rm_4;
+ sc->bs.bs_wm_1 = awusbdrd_bs_wm_1;
+ sc->bs.bs_wm_4 = awusbdrd_bs_wm_4;
+
+ sc->sc.sc_io_tag = &sc->bs;
+ sc->sc.sc_io_hdl = rman_get_bushandle(sc->res[0]);
+ sc->sc.sc_io_size = rman_get_size(sc->res[0]);
+
+ sc->sc.sc_bus.bdev = device_add_child(dev, "usbus", -1);
+ if (sc->sc.sc_bus.bdev == NULL) {
+ error = ENXIO;
+ goto fail;
+ }
+ device_set_ivars(sc->sc.sc_bus.bdev, &sc->sc.sc_bus);
+ sc->sc.sc_id = 0;
+ sc->sc.sc_platform_data = sc;
+ sc->sc.sc_mode = MUSB2_HOST_MODE; /* XXX HOST vs DEVICE mode */
+ sc->sc.sc_ep_max = DRD_EP_MAX;
+
+ error = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_BIO,
+ NULL, awusbdrd_intr, sc, &sc->sc.sc_intr_hdl);
+ if (error != 0)
+ goto fail;
+
+ /* Enable PIO mode */
+ bus_write_1(sc->res[0], MUSB2_REG_AWIN_VEND0, VEND0_PIO_MODE);
+
+#ifdef __arm__
+ /* Map SRAMD area to USB0 (sun4i/sun7i only) */
+ switch (allwinner_soc_family()) {
+ case ALLWINNERSOC_SUN4I:
+ case ALLWINNERSOC_SUN7I:
+ a10_map_to_otg();
+ break;
+ }
+#endif
+
+ error = musbotg_init(&sc->sc);
+ if (error != 0)
+ goto fail;
+
+ error = device_probe_and_attach(sc->sc.sc_bus.bdev);
+ if (error != 0)
+ goto fail;
+
+ musbotg_vbus_interrupt(&sc->sc, 1); /* XXX VBUS */
+
+ return (0);
+
+fail:
+ if (sc->reset != NULL)
+ hwreset_release(sc->reset);
+ if (sc->clk != NULL)
+ clk_release(sc->clk);
+ bus_release_resources(dev, awusbdrd_spec, sc->res);
+ return (error);
+}
+
+static int
+awusbdrd_detach(device_t dev)
+{
+ struct awusbdrd_softc *sc;
+ device_t bdev;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ if (sc->sc.sc_bus.bdev != NULL) {
+ bdev = sc->sc.sc_bus.bdev;
+ device_detach(bdev);
+ device_delete_child(dev, bdev);
+ }
+
+ musbotg_uninit(&sc->sc);
+ error = bus_teardown_intr(dev, sc->res[1], sc->sc.sc_intr_hdl);
+ if (error != 0)
+ return (error);
+
+ usb_bus_mem_free_all(&sc->sc.sc_bus, NULL);
+
+ if (sc->reset != NULL)
+ hwreset_release(sc->reset);
+ if (sc->clk != NULL)
+ clk_release(sc->clk);
+
+ bus_release_resources(dev, awusbdrd_spec, sc->res);
+
+ device_delete_children(dev);
+
+ return (0);
+}
+
+static device_method_t awusbdrd_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, awusbdrd_probe),
+ DEVMETHOD(device_attach, awusbdrd_attach),
+ DEVMETHOD(device_detach, awusbdrd_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ DEVMETHOD_END
+};
+
+static driver_t awusbdrd_driver = {
+ .name = "musbotg",
+ .methods = awusbdrd_methods,
+ .size = sizeof(struct awusbdrd_softc),
+};
+
+static devclass_t awusbdrd_devclass;
+
+DRIVER_MODULE(musbotg, simplebus, awusbdrd_driver, awusbdrd_devclass, 0, 0);
+MODULE_DEPEND(musbotg, usb, 1, 1, 1);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 15, 1:27 AM (7 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15803765
Default Alt Text
D5881.id39797.diff (18 KB)
Attached To
Mode
D5881: Allwinner USB DRD support (musb_otg)
Attached
Detach File
Event Timeline
Log In to Comment