The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/controller/musb_otg_allwinner.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
    3  * Copyright (c) 2018 Andrew Turner <andrew@FreeBSD.org>
    4  * All rights reserved.
    5  *
    6  * This software was developed by SRI International and the University of
    7  * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
    8  * ("CTSRD"), as part of the DARPA CRASH research programme.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  * $FreeBSD$
   32  */
   33 
   34 /*
   35  * Allwinner USB Dual-Role Device (DRD) controller
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD$");
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/bus.h>
   44 #include <sys/rman.h>
   45 #include <sys/kernel.h>
   46 #include <sys/condvar.h>
   47 #include <sys/module.h>
   48 
   49 #include <machine/bus.h>
   50 
   51 #include <dev/ofw/ofw_bus.h>
   52 #include <dev/ofw/ofw_bus_subr.h>
   53 
   54 #include <dev/usb/usb.h>
   55 #include <dev/usb/usbdi.h>
   56 
   57 #include <dev/usb/usb_core.h>
   58 #include <dev/usb/usb_busdma.h>
   59 #include <dev/usb/usb_process.h>
   60 #include <dev/usb/usb_util.h>
   61 
   62 #include <dev/usb/usb_controller.h>
   63 #include <dev/usb/usb_bus.h>
   64 #include <dev/usb/controller/musb_otg.h>
   65 
   66 #include <dev/extres/clk/clk.h>
   67 #include <dev/extres/hwreset/hwreset.h>
   68 #include <dev/extres/phy/phy.h>
   69 #include <dev/extres/phy/phy_usb.h>
   70 
   71 #ifdef __arm__
   72 #include <arm/allwinner/aw_machdep.h>
   73 #include <arm/allwinner/a10_sramc.h>
   74 #endif
   75 
   76 #define DRD_EP_MAX              5
   77 #define DRD_EP_MAX_H3           4
   78 
   79 #define MUSB2_REG_AWIN_VEND0    0x0043
   80 #define VEND0_PIO_MODE          0
   81 
   82 #if defined(__arm__)
   83 #define bs_parent_space(bs)     ((bs)->bs_parent)
   84 typedef bus_space_tag_t awusb_bs_tag;
   85 #elif defined(__aarch64__)
   86 #define bs_parent_space(bs)     (bs)
   87 typedef void *          awusb_bs_tag;
   88 #endif
   89 
   90 #define AWUSB_OKAY              0x01
   91 #define AWUSB_NO_CONFDATA       0x02
   92 static struct ofw_compat_data compat_data[] = {
   93         { "allwinner,sun4i-a10-musb",   AWUSB_OKAY },
   94         { "allwinner,sun6i-a31-musb",   AWUSB_OKAY },
   95         { "allwinner,sun8i-a33-musb",   AWUSB_OKAY | AWUSB_NO_CONFDATA },
   96         { "allwinner,sun8i-h3-musb",    AWUSB_OKAY | AWUSB_NO_CONFDATA },
   97         { NULL,                         0 }
   98 };
   99 
  100 static const struct musb_otg_ep_cfg musbotg_ep_allwinner[] = {
  101         {
  102                 .ep_end = DRD_EP_MAX,
  103                 .ep_fifosz_shift = 9,
  104                 .ep_fifosz_reg = MUSB2_VAL_FIFOSZ_512,
  105         },
  106         {
  107                 .ep_end = -1,
  108         },
  109 };
  110 
  111 static const struct musb_otg_ep_cfg musbotg_ep_allwinner_h3[] = {
  112         {
  113                 .ep_end = DRD_EP_MAX_H3,
  114                 .ep_fifosz_shift = 9,
  115                 .ep_fifosz_reg = MUSB2_VAL_FIFOSZ_512,
  116         },
  117         {
  118                 .ep_end = -1,
  119         },
  120 };
  121 
  122 struct awusbdrd_softc {
  123         struct musbotg_softc    sc;
  124         struct resource         *res[2];
  125         clk_t                   clk;
  126         hwreset_t               reset;
  127         phy_t                   phy;
  128         struct bus_space        bs;
  129         int                     flags;
  130 };
  131 
  132 static struct resource_spec awusbdrd_spec[] = {
  133         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
  134         { SYS_RES_IRQ,          0,      RF_ACTIVE },
  135         { -1, 0 }
  136 };
  137 
  138 #define REMAPFLAG       0x8000
  139 #define REGDECL(a, b)   [(a)] = ((b) | REMAPFLAG)
  140 
  141 /* Allwinner USB DRD register mappings */
  142 static const uint16_t awusbdrd_regmap[] = {
  143         REGDECL(MUSB2_REG_EPFIFO(0),    0x0000),
  144         REGDECL(MUSB2_REG_EPFIFO(1),    0x0004),
  145         REGDECL(MUSB2_REG_EPFIFO(2),    0x0008),
  146         REGDECL(MUSB2_REG_EPFIFO(3),    0x000c),
  147         REGDECL(MUSB2_REG_EPFIFO(4),    0x0010),
  148         REGDECL(MUSB2_REG_EPFIFO(5),    0x0014),
  149         REGDECL(MUSB2_REG_POWER,        0x0040),
  150         REGDECL(MUSB2_REG_DEVCTL,       0x0041),
  151         REGDECL(MUSB2_REG_EPINDEX,      0x0042),
  152         REGDECL(MUSB2_REG_INTTX,        0x0044),
  153         REGDECL(MUSB2_REG_INTRX,        0x0046),
  154         REGDECL(MUSB2_REG_INTTXE,       0x0048),
  155         REGDECL(MUSB2_REG_INTRXE,       0x004a),
  156         REGDECL(MUSB2_REG_INTUSB,       0x004c),
  157         REGDECL(MUSB2_REG_INTUSBE,      0x0050),
  158         REGDECL(MUSB2_REG_FRAME,        0x0054),
  159         REGDECL(MUSB2_REG_TESTMODE,     0x007c),
  160         REGDECL(MUSB2_REG_TXMAXP,       0x0080),
  161         REGDECL(MUSB2_REG_TXCSRL,       0x0082),
  162         REGDECL(MUSB2_REG_TXCSRH,       0x0083),
  163         REGDECL(MUSB2_REG_RXMAXP,       0x0084),
  164         REGDECL(MUSB2_REG_RXCSRL,       0x0086),
  165         REGDECL(MUSB2_REG_RXCSRH,       0x0087),
  166         REGDECL(MUSB2_REG_RXCOUNT,      0x0088),
  167         REGDECL(MUSB2_REG_TXTI,         0x008c),
  168         REGDECL(MUSB2_REG_TXNAKLIMIT,   0x008d),
  169         REGDECL(MUSB2_REG_RXNAKLIMIT,   0x008f),
  170         REGDECL(MUSB2_REG_RXTI,         0x008e),
  171         REGDECL(MUSB2_REG_TXFIFOSZ,     0x0090),
  172         REGDECL(MUSB2_REG_TXFIFOADD,    0x0092),
  173         REGDECL(MUSB2_REG_RXFIFOSZ,     0x0094),
  174         REGDECL(MUSB2_REG_RXFIFOADD,    0x0096),
  175         REGDECL(MUSB2_REG_FADDR,        0x0098),
  176         REGDECL(MUSB2_REG_TXFADDR(0),   0x0098),
  177         REGDECL(MUSB2_REG_TXHADDR(0),   0x009a),
  178         REGDECL(MUSB2_REG_TXHUBPORT(0), 0x009b),
  179         REGDECL(MUSB2_REG_RXFADDR(0),   0x009c),
  180         REGDECL(MUSB2_REG_RXHADDR(0),   0x009e),
  181         REGDECL(MUSB2_REG_RXHUBPORT(0), 0x009f),
  182         REGDECL(MUSB2_REG_TXFADDR(1),   0x0098),
  183         REGDECL(MUSB2_REG_TXHADDR(1),   0x009a),
  184         REGDECL(MUSB2_REG_TXHUBPORT(1), 0x009b),
  185         REGDECL(MUSB2_REG_RXFADDR(1),   0x009c),
  186         REGDECL(MUSB2_REG_RXHADDR(1),   0x009e),
  187         REGDECL(MUSB2_REG_RXHUBPORT(1), 0x009f),
  188         REGDECL(MUSB2_REG_TXFADDR(2),   0x0098),
  189         REGDECL(MUSB2_REG_TXHADDR(2),   0x009a),
  190         REGDECL(MUSB2_REG_TXHUBPORT(2), 0x009b),
  191         REGDECL(MUSB2_REG_RXFADDR(2),   0x009c),
  192         REGDECL(MUSB2_REG_RXHADDR(2),   0x009e),
  193         REGDECL(MUSB2_REG_RXHUBPORT(2), 0x009f),
  194         REGDECL(MUSB2_REG_TXFADDR(3),   0x0098),
  195         REGDECL(MUSB2_REG_TXHADDR(3),   0x009a),
  196         REGDECL(MUSB2_REG_TXHUBPORT(3), 0x009b),
  197         REGDECL(MUSB2_REG_RXFADDR(3),   0x009c),
  198         REGDECL(MUSB2_REG_RXHADDR(3),   0x009e),
  199         REGDECL(MUSB2_REG_RXHUBPORT(3), 0x009f),
  200         REGDECL(MUSB2_REG_TXFADDR(4),   0x0098),
  201         REGDECL(MUSB2_REG_TXHADDR(4),   0x009a),
  202         REGDECL(MUSB2_REG_TXHUBPORT(4), 0x009b),
  203         REGDECL(MUSB2_REG_RXFADDR(4),   0x009c),
  204         REGDECL(MUSB2_REG_RXHADDR(4),   0x009e),
  205         REGDECL(MUSB2_REG_RXHUBPORT(4), 0x009f),
  206         REGDECL(MUSB2_REG_TXFADDR(5),   0x0098),
  207         REGDECL(MUSB2_REG_TXHADDR(5),   0x009a),
  208         REGDECL(MUSB2_REG_TXHUBPORT(5), 0x009b),
  209         REGDECL(MUSB2_REG_RXFADDR(5),   0x009c),
  210         REGDECL(MUSB2_REG_RXHADDR(5),   0x009e),
  211         REGDECL(MUSB2_REG_RXHUBPORT(5), 0x009f),
  212         REGDECL(MUSB2_REG_CONFDATA,     0x00c0),
  213 };
  214 
  215 static bus_size_t
  216 awusbdrd_reg(bus_size_t o)
  217 {
  218         bus_size_t v;
  219 
  220         KASSERT(o < nitems(awusbdrd_regmap),
  221             ("%s: Invalid register %#lx", __func__, o));
  222         if (o >= nitems(awusbdrd_regmap))
  223                 return (o);
  224 
  225         v = awusbdrd_regmap[o];
  226 
  227         KASSERT((v & REMAPFLAG) != 0, ("%s: reg %#lx not in regmap",
  228             __func__, o));
  229 
  230         return (v & ~REMAPFLAG);
  231 }
  232 
  233 static int
  234 awusbdrd_filt(bus_size_t o)
  235 {
  236         switch (o) {
  237         case MUSB2_REG_MISC:
  238         case MUSB2_REG_RXDBDIS:
  239         case MUSB2_REG_TXDBDIS:
  240                 return (1);
  241         default:
  242                 return (0);
  243         }
  244 }
  245 
  246 static uint8_t
  247 awusbdrd_bs_r_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o)
  248 {
  249         struct bus_space *bs = t;
  250 
  251         switch (o) {
  252         case MUSB2_REG_HWVERS:
  253                 return (0);     /* no known equivalent */
  254         }
  255 
  256         return (bus_space_read_1(bs_parent_space(bs), h, awusbdrd_reg(o)));
  257 }
  258 
  259 static uint8_t
  260 awusbdrd_bs_r_1_noconf(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o)
  261 {
  262 
  263         /*
  264          * There is no confdata register on some SoCs, return the same
  265          * magic value as Linux.
  266          */
  267         if (o == MUSB2_REG_CONFDATA)
  268                 return (0xde);
  269 
  270         return (awusbdrd_bs_r_1(t, h, o));
  271 }
  272 
  273 
  274 static uint16_t
  275 awusbdrd_bs_r_2(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o)
  276 {
  277         struct bus_space *bs = t;
  278 
  279         if (awusbdrd_filt(o) != 0)
  280                 return (0);
  281         return bus_space_read_2(bs_parent_space(bs), h, awusbdrd_reg(o));
  282 }
  283 
  284 static void
  285 awusbdrd_bs_w_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
  286     uint8_t v)
  287 {
  288         struct bus_space *bs = t;
  289 
  290         if (awusbdrd_filt(o) != 0)
  291                 return;
  292 
  293         bus_space_write_1(bs_parent_space(bs), h, awusbdrd_reg(o), v);
  294 }
  295 
  296 static void
  297 awusbdrd_bs_w_2(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
  298     uint16_t v)
  299 {
  300         struct bus_space *bs = t;
  301 
  302         if (awusbdrd_filt(o) != 0)
  303                 return;
  304 
  305         bus_space_write_2(bs_parent_space(bs), h, awusbdrd_reg(o), v);
  306 }
  307 
  308 static void
  309 awusbdrd_bs_rm_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
  310     uint8_t *d, bus_size_t c)
  311 {
  312         struct bus_space *bs = t;
  313 
  314         bus_space_read_multi_1(bs_parent_space(bs), h, awusbdrd_reg(o), d, c);
  315 }
  316 
  317 static void
  318 awusbdrd_bs_rm_4(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
  319     uint32_t *d, bus_size_t c)
  320 {
  321         struct bus_space *bs = t;
  322 
  323         bus_space_read_multi_4(bs_parent_space(bs), h, awusbdrd_reg(o), d, c);
  324 }
  325 
  326 static void
  327 awusbdrd_bs_wm_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
  328     const uint8_t *d, bus_size_t c)
  329 {
  330         struct bus_space *bs = t;
  331 
  332         if (awusbdrd_filt(o) != 0)
  333                 return;
  334 
  335         bus_space_write_multi_1(bs_parent_space(bs), h, awusbdrd_reg(o), d, c);
  336 }
  337 
  338 static void
  339 awusbdrd_bs_wm_4(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o,
  340     const uint32_t *d, bus_size_t c)
  341 {
  342         struct bus_space *bs = t;
  343 
  344         if (awusbdrd_filt(o) != 0)
  345                 return;
  346 
  347         bus_space_write_multi_4(bs_parent_space(bs), h, awusbdrd_reg(o), d, c);
  348 }
  349 
  350 static void
  351 awusbdrd_intr(void *arg)
  352 {
  353         struct awusbdrd_softc *sc = arg;
  354         uint8_t intusb;
  355         uint16_t inttx, intrx;
  356 
  357         intusb = MUSB2_READ_1(&sc->sc, MUSB2_REG_INTUSB);
  358         inttx = MUSB2_READ_2(&sc->sc, MUSB2_REG_INTTX);
  359         intrx = MUSB2_READ_2(&sc->sc, MUSB2_REG_INTRX);
  360         if (intusb == 0 && inttx == 0 && intrx == 0)
  361                 return;
  362 
  363         if (intusb)
  364                 MUSB2_WRITE_1(&sc->sc, MUSB2_REG_INTUSB, intusb);
  365         if (inttx)
  366                 MUSB2_WRITE_2(&sc->sc, MUSB2_REG_INTTX, inttx);
  367         if (intrx)
  368                 MUSB2_WRITE_2(&sc->sc, MUSB2_REG_INTRX, intrx);
  369 
  370         musbotg_interrupt(arg, intrx, inttx, intusb);
  371 }
  372 
  373 static int
  374 awusbdrd_probe(device_t dev)
  375 {
  376         if (!ofw_bus_status_okay(dev))
  377                 return (ENXIO);
  378 
  379         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  380                 return (ENXIO);
  381 
  382         device_set_desc(dev, "Allwinner USB DRD");
  383         return (BUS_PROBE_DEFAULT);
  384 }
  385 
  386 static int
  387 awusbdrd_attach(device_t dev)
  388 {
  389         char usb_mode[24];
  390         struct awusbdrd_softc *sc;
  391         uint8_t musb_mode;
  392         int phy_mode;
  393         int error;
  394 
  395         sc = device_get_softc(dev);
  396         sc->flags = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
  397 
  398         error = bus_alloc_resources(dev, awusbdrd_spec, sc->res);
  399         if (error != 0)
  400                 return (error);
  401 
  402         musb_mode = MUSB2_HOST_MODE;    /* default */
  403         phy_mode = PHY_USB_MODE_HOST;
  404         if (OF_getprop(ofw_bus_get_node(dev), "dr_mode",
  405             &usb_mode, sizeof(usb_mode)) > 0) {
  406                 usb_mode[sizeof(usb_mode) - 1] = 0;
  407                 if (strcasecmp(usb_mode, "host") == 0) {
  408                         musb_mode = MUSB2_HOST_MODE;
  409                         phy_mode = PHY_USB_MODE_HOST;
  410                 } else if (strcasecmp(usb_mode, "peripheral") == 0) {
  411                         musb_mode = MUSB2_DEVICE_MODE;
  412                         phy_mode = PHY_USB_MODE_DEVICE;
  413                 } else if (strcasecmp(usb_mode, "otg") == 0) {
  414                         /*
  415                          * XXX phy has PHY_USB_MODE_OTG, but MUSB does not have
  416                          * it.  It's not clear how to propagate mode changes
  417                          * from phy layer (that detects them) to MUSB.
  418                          */
  419                         musb_mode = MUSB2_DEVICE_MODE;
  420                         phy_mode = PHY_USB_MODE_DEVICE;
  421                 } else {
  422                         device_printf(dev, "Invalid FDT dr_mode: %s\n",
  423                             usb_mode);
  424                 }
  425         }
  426 
  427         /* AHB gate clock is required */
  428         error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk);
  429         if (error != 0)
  430                 goto fail;
  431 
  432         /* AHB reset is only present on some SoCs */
  433         (void)hwreset_get_by_ofw_idx(dev, 0, 0, &sc->reset);
  434 
  435         /* Enable clocks */
  436         error = clk_enable(sc->clk);
  437         if (error != 0) {
  438                 device_printf(dev, "failed to enable clock: %d\n", error);
  439                 goto fail;
  440         }
  441         if (sc->reset != NULL) {
  442                 error = hwreset_deassert(sc->reset);
  443                 if (error != 0) {
  444                         device_printf(dev, "failed to de-assert reset: %d\n",
  445                             error);
  446                         goto fail;
  447                 }
  448         }
  449 
  450         /* XXX not sure if this is universally needed. */
  451         (void)phy_get_by_ofw_name(dev, 0, "usb", &sc->phy);
  452         if (sc->phy != NULL) {
  453                 device_printf(dev, "setting phy mode %d\n", phy_mode);
  454                 if (musb_mode == MUSB2_HOST_MODE) {
  455                         error = phy_enable(sc->phy);
  456                         if (error != 0) {
  457                                 device_printf(dev, "Could not enable phy\n");
  458                                 goto fail;
  459                         }
  460                 }
  461                 error = phy_usb_set_mode(sc->phy, phy_mode);
  462                 if (error != 0) {
  463                         device_printf(dev, "Could not set phy mode\n");
  464                         goto fail;
  465                 }
  466         }
  467 
  468         sc->sc.sc_bus.parent = dev;
  469         sc->sc.sc_bus.devices = sc->sc.sc_devices;
  470         sc->sc.sc_bus.devices_max = MUSB2_MAX_DEVICES;
  471         sc->sc.sc_bus.dma_bits = 32;
  472 
  473         error = usb_bus_mem_alloc_all(&sc->sc.sc_bus, USB_GET_DMA_TAG(dev),
  474             NULL);
  475         if (error != 0) {
  476                 error = ENOMEM;
  477                 goto fail;
  478         }
  479 
  480 #if defined(__arm__)
  481         sc->bs.bs_parent = rman_get_bustag(sc->res[0]);
  482 #elif defined(__aarch64__)
  483         sc->bs.bs_cookie = rman_get_bustag(sc->res[0]);
  484 #endif
  485 
  486         if ((sc->flags & AWUSB_NO_CONFDATA) == AWUSB_NO_CONFDATA)
  487                 sc->bs.bs_r_1 = awusbdrd_bs_r_1_noconf;
  488         else
  489                 sc->bs.bs_r_1 = awusbdrd_bs_r_1;
  490         sc->bs.bs_r_2 = awusbdrd_bs_r_2;
  491         sc->bs.bs_w_1 = awusbdrd_bs_w_1;
  492         sc->bs.bs_w_2 = awusbdrd_bs_w_2;
  493         sc->bs.bs_rm_1 = awusbdrd_bs_rm_1;
  494         sc->bs.bs_rm_4 = awusbdrd_bs_rm_4;
  495         sc->bs.bs_wm_1 = awusbdrd_bs_wm_1;
  496         sc->bs.bs_wm_4 = awusbdrd_bs_wm_4;
  497 
  498         sc->sc.sc_io_tag = &sc->bs;
  499         sc->sc.sc_io_hdl = rman_get_bushandle(sc->res[0]);
  500         sc->sc.sc_io_size = rman_get_size(sc->res[0]);
  501 
  502         sc->sc.sc_bus.bdev = device_add_child(dev, "usbus", -1);
  503         if (sc->sc.sc_bus.bdev == NULL) {
  504                 error = ENXIO;
  505                 goto fail;
  506         }
  507         device_set_ivars(sc->sc.sc_bus.bdev, &sc->sc.sc_bus);
  508         sc->sc.sc_id = 0;
  509         sc->sc.sc_platform_data = sc;
  510         sc->sc.sc_mode = musb_mode;
  511         if (ofw_bus_is_compatible(dev, "allwinner,sun8i-h3-musb")) {
  512                 sc->sc.sc_ep_cfg = musbotg_ep_allwinner_h3;
  513                 sc->sc.sc_ep_max = DRD_EP_MAX_H3;
  514         } else {
  515                 sc->sc.sc_ep_cfg = musbotg_ep_allwinner;
  516                 sc->sc.sc_ep_max = DRD_EP_MAX;
  517         }
  518 
  519         error = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_BIO,
  520             NULL, awusbdrd_intr, sc, &sc->sc.sc_intr_hdl);
  521         if (error != 0)
  522                 goto fail;
  523 
  524         /* Enable PIO mode */
  525         bus_write_1(sc->res[0], MUSB2_REG_AWIN_VEND0, VEND0_PIO_MODE);
  526 
  527 #ifdef __arm__
  528         /* Map SRAMD area to USB0 (sun4i/sun7i only) */
  529         switch (allwinner_soc_family()) {
  530         case ALLWINNERSOC_SUN4I:
  531         case ALLWINNERSOC_SUN7I:
  532                 a10_map_to_otg();
  533                 break;
  534         }
  535 #endif
  536 
  537         error = musbotg_init(&sc->sc);
  538         if (error != 0)
  539                 goto fail;
  540 
  541         error = device_probe_and_attach(sc->sc.sc_bus.bdev);
  542         if (error != 0)
  543                 goto fail;
  544 
  545         musbotg_vbus_interrupt(&sc->sc, 1);     /* XXX VBUS */
  546 
  547         return (0);
  548 
  549 fail:
  550         if (sc->phy != NULL) {
  551                 if (musb_mode == MUSB2_HOST_MODE)
  552                         (void)phy_disable(sc->phy);
  553                 phy_release(sc->phy);
  554         }
  555         if (sc->reset != NULL) {
  556                 hwreset_assert(sc->reset);
  557                 hwreset_release(sc->reset);
  558         }
  559         if (sc->clk != NULL)
  560                 clk_release(sc->clk);
  561         bus_release_resources(dev, awusbdrd_spec, sc->res);
  562         return (error);
  563 }
  564 
  565 static int
  566 awusbdrd_detach(device_t dev)
  567 {
  568         struct awusbdrd_softc *sc;
  569         device_t bdev;
  570         int error;
  571 
  572         sc = device_get_softc(dev);
  573 
  574         if (sc->sc.sc_bus.bdev != NULL) {
  575                 bdev = sc->sc.sc_bus.bdev;
  576                 device_detach(bdev);
  577                 device_delete_child(dev, bdev);
  578         }
  579 
  580         musbotg_uninit(&sc->sc);
  581         error = bus_teardown_intr(dev, sc->res[1], sc->sc.sc_intr_hdl);
  582         if (error != 0)
  583                 return (error);
  584 
  585         usb_bus_mem_free_all(&sc->sc.sc_bus, NULL);
  586 
  587         if (sc->phy != NULL) {
  588                 if (sc->sc.sc_mode == MUSB2_HOST_MODE)
  589                         phy_disable(sc->phy);
  590                 phy_release(sc->phy);
  591         }
  592         if (sc->reset != NULL) {
  593                 if (hwreset_assert(sc->reset) != 0)
  594                         device_printf(dev, "failed to assert reset\n");
  595                 hwreset_release(sc->reset);
  596         }
  597         if (sc->clk != NULL)
  598                 clk_release(sc->clk);
  599 
  600         bus_release_resources(dev, awusbdrd_spec, sc->res);
  601 
  602         device_delete_children(dev);
  603 
  604         return (0);
  605 }
  606 
  607 static device_method_t awusbdrd_methods[] = {
  608         /* Device interface */
  609         DEVMETHOD(device_probe,         awusbdrd_probe),
  610         DEVMETHOD(device_attach,        awusbdrd_attach),
  611         DEVMETHOD(device_detach,        awusbdrd_detach),
  612         DEVMETHOD(device_suspend,       bus_generic_suspend),
  613         DEVMETHOD(device_resume,        bus_generic_resume),
  614         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  615 
  616         DEVMETHOD_END
  617 };
  618 
  619 static driver_t awusbdrd_driver = {
  620         .name = "musbotg",
  621         .methods = awusbdrd_methods,
  622         .size = sizeof(struct awusbdrd_softc),
  623 };
  624 
  625 DRIVER_MODULE(musbotg, simplebus, awusbdrd_driver, 0, 0);
  626 MODULE_DEPEND(musbotg, usb, 1, 1, 1);

Cache object: 1ecbbad794004bbdc8efd7dd01b20c3c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.