11b4bd023SJared McNeill /*- 21b4bd023SJared McNeill * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca> 31b4bd023SJared McNeill * All rights reserved. 41b4bd023SJared McNeill * 51b4bd023SJared McNeill * Redistribution and use in source and binary forms, with or without 61b4bd023SJared McNeill * modification, are permitted provided that the following conditions 71b4bd023SJared McNeill * are met: 81b4bd023SJared McNeill * 1. Redistributions of source code must retain the above copyright 91b4bd023SJared McNeill * notice, this list of conditions and the following disclaimer. 101b4bd023SJared McNeill * 2. Redistributions in binary form must reproduce the above copyright 111b4bd023SJared McNeill * notice, this list of conditions and the following disclaimer in the 121b4bd023SJared McNeill * documentation and/or other materials provided with the distribution. 131b4bd023SJared McNeill * 141b4bd023SJared McNeill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 151b4bd023SJared McNeill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 161b4bd023SJared McNeill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 171b4bd023SJared McNeill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 181b4bd023SJared McNeill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 191b4bd023SJared McNeill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 201b4bd023SJared McNeill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 211b4bd023SJared McNeill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 221b4bd023SJared McNeill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231b4bd023SJared McNeill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241b4bd023SJared McNeill * SUCH DAMAGE. 251b4bd023SJared McNeill * 261b4bd023SJared McNeill * $FreeBSD$ 271b4bd023SJared McNeill */ 281b4bd023SJared McNeill 291b4bd023SJared McNeill /* 301b4bd023SJared McNeill * Allwinner USB PHY 311b4bd023SJared McNeill */ 321b4bd023SJared McNeill 331b4bd023SJared McNeill #include <sys/cdefs.h> 341b4bd023SJared McNeill __FBSDID("$FreeBSD$"); 351b4bd023SJared McNeill 361b4bd023SJared McNeill #include <sys/param.h> 371b4bd023SJared McNeill #include <sys/systm.h> 381b4bd023SJared McNeill #include <sys/bus.h> 391b4bd023SJared McNeill #include <sys/rman.h> 401b4bd023SJared McNeill #include <sys/kernel.h> 411b4bd023SJared McNeill #include <sys/module.h> 421b4bd023SJared McNeill #include <sys/gpio.h> 4363dc81d8SJared McNeill #include <machine/bus.h> 441b4bd023SJared McNeill 451b4bd023SJared McNeill #include <dev/ofw/ofw_bus.h> 461b4bd023SJared McNeill #include <dev/ofw/ofw_bus_subr.h> 47627c360fSJared McNeill #include <dev/gpio/gpiobusvar.h> 481b4bd023SJared McNeill 496a05f063SJared McNeill #include <dev/extres/clk/clk.h> 506a05f063SJared McNeill #include <dev/extres/hwreset/hwreset.h> 516a05f063SJared McNeill #include <dev/extres/regulator/regulator.h> 52627c360fSJared McNeill #include <dev/extres/phy/phy.h> 531b4bd023SJared McNeill 54627c360fSJared McNeill #include "phy_if.h" 55627c360fSJared McNeill 5663dc81d8SJared McNeill enum awusbphy_type { 5763dc81d8SJared McNeill AWUSBPHY_TYPE_A10 = 1, 5863dc81d8SJared McNeill AWUSBPHY_TYPE_A13, 5963dc81d8SJared McNeill AWUSBPHY_TYPE_A20, 6063dc81d8SJared McNeill AWUSBPHY_TYPE_A31, 6163dc81d8SJared McNeill AWUSBPHY_TYPE_H3, 62*5b48129eSKyle Evans AWUSBPHY_TYPE_A64, 63*5b48129eSKyle Evans AWUSBPHY_TYPE_A83T 6463dc81d8SJared McNeill }; 651b4bd023SJared McNeill 6636dcd6a4SEmmanuel Vadot struct aw_usbphy_conf { 6736dcd6a4SEmmanuel Vadot int num_phys; 6836dcd6a4SEmmanuel Vadot enum awusbphy_type phy_type; 6936dcd6a4SEmmanuel Vadot bool pmu_unk1; 7036dcd6a4SEmmanuel Vadot bool phy0_route; 7136dcd6a4SEmmanuel Vadot }; 7236dcd6a4SEmmanuel Vadot 7336dcd6a4SEmmanuel Vadot static const struct aw_usbphy_conf a10_usbphy_conf = { 7436dcd6a4SEmmanuel Vadot .num_phys = 3, 7536dcd6a4SEmmanuel Vadot .phy_type = AWUSBPHY_TYPE_A10, 7636dcd6a4SEmmanuel Vadot .pmu_unk1 = false, 7736dcd6a4SEmmanuel Vadot .phy0_route = false, 7836dcd6a4SEmmanuel Vadot }; 7936dcd6a4SEmmanuel Vadot 8036dcd6a4SEmmanuel Vadot static const struct aw_usbphy_conf a13_usbphy_conf = { 8136dcd6a4SEmmanuel Vadot .num_phys = 2, 8236dcd6a4SEmmanuel Vadot .phy_type = AWUSBPHY_TYPE_A13, 8336dcd6a4SEmmanuel Vadot .pmu_unk1 = false, 8436dcd6a4SEmmanuel Vadot .phy0_route = false, 8536dcd6a4SEmmanuel Vadot }; 8636dcd6a4SEmmanuel Vadot 8736dcd6a4SEmmanuel Vadot static const struct aw_usbphy_conf a20_usbphy_conf = { 8836dcd6a4SEmmanuel Vadot .num_phys = 3, 8936dcd6a4SEmmanuel Vadot .phy_type = AWUSBPHY_TYPE_A20, 9036dcd6a4SEmmanuel Vadot .pmu_unk1 = false, 9136dcd6a4SEmmanuel Vadot .phy0_route = false, 9236dcd6a4SEmmanuel Vadot }; 9336dcd6a4SEmmanuel Vadot 9436dcd6a4SEmmanuel Vadot static const struct aw_usbphy_conf a31_usbphy_conf = { 9536dcd6a4SEmmanuel Vadot .num_phys = 3, 9636dcd6a4SEmmanuel Vadot .phy_type = AWUSBPHY_TYPE_A31, 9736dcd6a4SEmmanuel Vadot .pmu_unk1 = false, 9836dcd6a4SEmmanuel Vadot .phy0_route = false, 9936dcd6a4SEmmanuel Vadot }; 10036dcd6a4SEmmanuel Vadot 10136dcd6a4SEmmanuel Vadot static const struct aw_usbphy_conf h3_usbphy_conf = { 10236dcd6a4SEmmanuel Vadot .num_phys = 4, 10336dcd6a4SEmmanuel Vadot .phy_type = AWUSBPHY_TYPE_H3, 10436dcd6a4SEmmanuel Vadot .pmu_unk1 = true, 10536dcd6a4SEmmanuel Vadot .phy0_route = false, 10636dcd6a4SEmmanuel Vadot }; 10736dcd6a4SEmmanuel Vadot 10836dcd6a4SEmmanuel Vadot static const struct aw_usbphy_conf a64_usbphy_conf = { 10936dcd6a4SEmmanuel Vadot .num_phys = 2, 11036dcd6a4SEmmanuel Vadot .phy_type = AWUSBPHY_TYPE_A64, 11136dcd6a4SEmmanuel Vadot .pmu_unk1 = true, 11236dcd6a4SEmmanuel Vadot .phy0_route = true, 11336dcd6a4SEmmanuel Vadot }; 11436dcd6a4SEmmanuel Vadot 115*5b48129eSKyle Evans static const struct aw_usbphy_conf a83t_usbphy_conf = { 116*5b48129eSKyle Evans .num_phys = 3, 117*5b48129eSKyle Evans .phy_type = AWUSBPHY_TYPE_A83T, 118*5b48129eSKyle Evans .pmu_unk1 = false, 119*5b48129eSKyle Evans .phy0_route = false, 120*5b48129eSKyle Evans }; 121*5b48129eSKyle Evans 1221b4bd023SJared McNeill static struct ofw_compat_data compat_data[] = { 12336dcd6a4SEmmanuel Vadot { "allwinner,sun4i-a10-usb-phy", (uintptr_t)&a10_usbphy_conf }, 12436dcd6a4SEmmanuel Vadot { "allwinner,sun5i-a13-usb-phy", (uintptr_t)&a13_usbphy_conf }, 12536dcd6a4SEmmanuel Vadot { "allwinner,sun6i-a31-usb-phy", (uintptr_t)&a31_usbphy_conf }, 12636dcd6a4SEmmanuel Vadot { "allwinner,sun7i-a20-usb-phy", (uintptr_t)&a20_usbphy_conf }, 12736dcd6a4SEmmanuel Vadot { "allwinner,sun8i-h3-usb-phy", (uintptr_t)&h3_usbphy_conf }, 12836dcd6a4SEmmanuel Vadot { "allwinner,sun50i-a64-usb-phy", (uintptr_t)&a64_usbphy_conf }, 129*5b48129eSKyle Evans { "allwinner,sun8i-a83t-usb-phy", (uintptr_t)&a83t_usbphy_conf }, 1301b4bd023SJared McNeill { NULL, 0 } 1311b4bd023SJared McNeill }; 1321b4bd023SJared McNeill 133627c360fSJared McNeill struct awusbphy_softc { 13436dcd6a4SEmmanuel Vadot struct resource * phy_ctrl; 13536dcd6a4SEmmanuel Vadot struct resource ** pmu; 13636dcd6a4SEmmanuel Vadot regulator_t * reg; 137627c360fSJared McNeill gpio_pin_t id_det_pin; 138627c360fSJared McNeill int id_det_valid; 139627c360fSJared McNeill gpio_pin_t vbus_det_pin; 140627c360fSJared McNeill int vbus_det_valid; 14136dcd6a4SEmmanuel Vadot struct aw_usbphy_conf *phy_conf; 142627c360fSJared McNeill }; 143627c360fSJared McNeill 14436dcd6a4SEmmanuel Vadot #define RD4(res, o) bus_read_4(res, (o)) 14536dcd6a4SEmmanuel Vadot #define WR4(res, o, v) bus_write_4(res, (o), (v)) 14636dcd6a4SEmmanuel Vadot #define CLR4(res, o, m) WR4(res, o, RD4(res, o) & ~(m)) 14736dcd6a4SEmmanuel Vadot #define SET4(res, o, m) WR4(res, o, RD4(res, o) | (m)) 14863dc81d8SJared McNeill 14963dc81d8SJared McNeill #define OTG_PHY_CFG 0x20 15063dc81d8SJared McNeill #define OTG_PHY_ROUTE_OTG (1 << 0) 15163dc81d8SJared McNeill #define PMU_IRQ_ENABLE 0x00 15263dc81d8SJared McNeill #define PMU_AHB_INCR8 (1 << 10) 15363dc81d8SJared McNeill #define PMU_AHB_INCR4 (1 << 9) 15463dc81d8SJared McNeill #define PMU_AHB_INCRX_ALIGN (1 << 8) 15563dc81d8SJared McNeill #define PMU_ULPI_BYPASS (1 << 0) 15663dc81d8SJared McNeill #define PMU_UNK_H3 0x10 15763dc81d8SJared McNeill #define PMU_UNK_H3_CLR 0x2 15863dc81d8SJared McNeill 15963dc81d8SJared McNeill static void 16063dc81d8SJared McNeill awusbphy_configure(device_t dev, int phyno) 16163dc81d8SJared McNeill { 16263dc81d8SJared McNeill struct awusbphy_softc *sc; 16363dc81d8SJared McNeill 16463dc81d8SJared McNeill sc = device_get_softc(dev); 16563dc81d8SJared McNeill 16636dcd6a4SEmmanuel Vadot if (sc->pmu[phyno] == NULL) 16763dc81d8SJared McNeill return; 16863dc81d8SJared McNeill 16936dcd6a4SEmmanuel Vadot if (sc->phy_conf->pmu_unk1 == true) 1701eca1d26SEmmanuel Vadot CLR4(sc->pmu[phyno], PMU_UNK_H3, PMU_UNK_H3_CLR); 17163dc81d8SJared McNeill 17236dcd6a4SEmmanuel Vadot SET4(sc->pmu[phyno], PMU_IRQ_ENABLE, PMU_ULPI_BYPASS | 17363dc81d8SJared McNeill PMU_AHB_INCR8 | PMU_AHB_INCR4 | PMU_AHB_INCRX_ALIGN); 17463dc81d8SJared McNeill } 17563dc81d8SJared McNeill 1761b4bd023SJared McNeill static int 1771b4bd023SJared McNeill awusbphy_init(device_t dev) 1781b4bd023SJared McNeill { 179627c360fSJared McNeill struct awusbphy_softc *sc; 180627c360fSJared McNeill phandle_t node; 1811b4bd023SJared McNeill char pname[20]; 18236dcd6a4SEmmanuel Vadot int error, off, rid; 1836a05f063SJared McNeill regulator_t reg; 1846a05f063SJared McNeill hwreset_t rst; 1856a05f063SJared McNeill clk_t clk; 1861b4bd023SJared McNeill 187627c360fSJared McNeill sc = device_get_softc(dev); 188627c360fSJared McNeill node = ofw_bus_get_node(dev); 189627c360fSJared McNeill 19036dcd6a4SEmmanuel Vadot sc->phy_conf = (struct aw_usbphy_conf *)ofw_bus_search_compatible(dev, compat_data)->ocd_data; 19136dcd6a4SEmmanuel Vadot 19236dcd6a4SEmmanuel Vadot /* Get phy_ctrl region */ 19336dcd6a4SEmmanuel Vadot if (ofw_bus_find_string_index(node, "reg-names", "phy_ctrl", &rid) != 0) { 19436dcd6a4SEmmanuel Vadot device_printf(dev, "Cannot locate phy control resource\n"); 19536dcd6a4SEmmanuel Vadot return (ENXIO); 19636dcd6a4SEmmanuel Vadot } 19736dcd6a4SEmmanuel Vadot sc->phy_ctrl = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 19836dcd6a4SEmmanuel Vadot RF_ACTIVE); 19936dcd6a4SEmmanuel Vadot if (sc->phy_ctrl == NULL) { 20036dcd6a4SEmmanuel Vadot device_printf(dev, "Cannot allocate resource\n"); 20136dcd6a4SEmmanuel Vadot return (ENXIO); 20236dcd6a4SEmmanuel Vadot } 20363dc81d8SJared McNeill 2046a05f063SJared McNeill /* Enable clocks */ 205dac93553SMichal Meloun for (off = 0; clk_get_by_ofw_index(dev, 0, off, &clk) == 0; off++) { 2066a05f063SJared McNeill error = clk_enable(clk); 2076a05f063SJared McNeill if (error != 0) { 2086a05f063SJared McNeill device_printf(dev, "couldn't enable clock %s\n", 2096a05f063SJared McNeill clk_get_name(clk)); 2106a05f063SJared McNeill return (error); 2116a05f063SJared McNeill } 2126a05f063SJared McNeill } 2131b4bd023SJared McNeill 2146a05f063SJared McNeill /* De-assert resets */ 215dac93553SMichal Meloun for (off = 0; hwreset_get_by_ofw_idx(dev, 0, off, &rst) == 0; off++) { 2166a05f063SJared McNeill error = hwreset_deassert(rst); 2176a05f063SJared McNeill if (error != 0) { 2186a05f063SJared McNeill device_printf(dev, "couldn't de-assert reset %d\n", 2196a05f063SJared McNeill off); 2206a05f063SJared McNeill return (error); 2216a05f063SJared McNeill } 2226a05f063SJared McNeill } 2236a05f063SJared McNeill 224627c360fSJared McNeill /* Get GPIOs */ 225627c360fSJared McNeill error = gpio_pin_get_by_ofw_property(dev, node, "usb0_id_det-gpios", 226627c360fSJared McNeill &sc->id_det_pin); 227627c360fSJared McNeill if (error == 0) 228627c360fSJared McNeill sc->id_det_valid = 1; 229627c360fSJared McNeill error = gpio_pin_get_by_ofw_property(dev, node, "usb0_vbus_det-gpios", 230627c360fSJared McNeill &sc->vbus_det_pin); 231627c360fSJared McNeill if (error == 0) 232627c360fSJared McNeill sc->vbus_det_valid = 1; 233627c360fSJared McNeill 23436dcd6a4SEmmanuel Vadot sc->reg = malloc(sizeof(*(sc->reg)) * sc->phy_conf->num_phys, M_DEVBUF, 23536dcd6a4SEmmanuel Vadot M_WAITOK | M_ZERO); 23636dcd6a4SEmmanuel Vadot sc->pmu = malloc(sizeof(*(sc->pmu)) * sc->phy_conf->num_phys, M_DEVBUF, 23736dcd6a4SEmmanuel Vadot M_WAITOK | M_ZERO); 23836dcd6a4SEmmanuel Vadot /* Get regulators */ 23936dcd6a4SEmmanuel Vadot for (off = 0; off < sc->phy_conf->num_phys; off++) { 24036dcd6a4SEmmanuel Vadot snprintf(pname, sizeof(pname), "usb%d_vbus-supply", off); 24136dcd6a4SEmmanuel Vadot if (regulator_get_by_ofw_property(dev, 0, pname, ®) == 0) 24236dcd6a4SEmmanuel Vadot sc->reg[off] = reg; 24336dcd6a4SEmmanuel Vadot 24436dcd6a4SEmmanuel Vadot snprintf(pname, sizeof(pname), "pmu%d", off); 24536dcd6a4SEmmanuel Vadot if (ofw_bus_find_string_index(node, "reg-names", 24636dcd6a4SEmmanuel Vadot pname, &rid) != 0) 24736dcd6a4SEmmanuel Vadot continue; 24836dcd6a4SEmmanuel Vadot 24936dcd6a4SEmmanuel Vadot sc->pmu[off] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 25036dcd6a4SEmmanuel Vadot RF_ACTIVE); 25136dcd6a4SEmmanuel Vadot if (sc->pmu[off] == NULL) { 25236dcd6a4SEmmanuel Vadot device_printf(dev, "Cannot allocate resource\n"); 25336dcd6a4SEmmanuel Vadot return (ENXIO); 25436dcd6a4SEmmanuel Vadot } 25536dcd6a4SEmmanuel Vadot } 25663dc81d8SJared McNeill 257627c360fSJared McNeill return (0); 258627c360fSJared McNeill } 259627c360fSJared McNeill 260627c360fSJared McNeill static int 261627c360fSJared McNeill awusbphy_vbus_detect(device_t dev, int *val) 262627c360fSJared McNeill { 263627c360fSJared McNeill struct awusbphy_softc *sc; 264627c360fSJared McNeill bool active; 265627c360fSJared McNeill int error; 266627c360fSJared McNeill 267627c360fSJared McNeill sc = device_get_softc(dev); 268627c360fSJared McNeill 269627c360fSJared McNeill if (sc->vbus_det_valid) { 270627c360fSJared McNeill error = gpio_pin_is_active(sc->vbus_det_pin, &active); 271de355beaSEmmanuel Vadot if (error != 0) { 272de355beaSEmmanuel Vadot device_printf(dev, "Cannot get status of id pin %d\n", 273de355beaSEmmanuel Vadot error); 274627c360fSJared McNeill return (error); 275de355beaSEmmanuel Vadot } 276627c360fSJared McNeill *val = active; 277627c360fSJared McNeill return (0); 278627c360fSJared McNeill } 279627c360fSJared McNeill 280627c360fSJared McNeill *val = 1; 281627c360fSJared McNeill return (0); 282627c360fSJared McNeill } 283627c360fSJared McNeill 284627c360fSJared McNeill static int 2857dd62272SJared McNeill awusbphy_phy_enable(device_t dev, intptr_t phy, bool enable) 286627c360fSJared McNeill { 287627c360fSJared McNeill struct awusbphy_softc *sc; 288627c360fSJared McNeill regulator_t reg; 289627c360fSJared McNeill int error, vbus_det; 290627c360fSJared McNeill 291627c360fSJared McNeill sc = device_get_softc(dev); 292627c360fSJared McNeill 29336dcd6a4SEmmanuel Vadot if (phy < 0 || phy >= sc->phy_conf->num_phys) 29436dcd6a4SEmmanuel Vadot return (ERANGE); 29536dcd6a4SEmmanuel Vadot 29663dc81d8SJared McNeill /* Configure PHY */ 29763dc81d8SJared McNeill awusbphy_configure(dev, phy); 29863dc81d8SJared McNeill 299627c360fSJared McNeill /* Regulators are optional. If not found, return success. */ 300627c360fSJared McNeill reg = sc->reg[phy]; 301627c360fSJared McNeill if (reg == NULL) 302627c360fSJared McNeill return (0); 303627c360fSJared McNeill 304627c360fSJared McNeill if (enable) { 305627c360fSJared McNeill /* If an external vbus is detected, do not enable phy 0 */ 306627c360fSJared McNeill if (phy == 0) { 307627c360fSJared McNeill error = awusbphy_vbus_detect(dev, &vbus_det); 308de355beaSEmmanuel Vadot if (error) 309de355beaSEmmanuel Vadot goto out; 310de355beaSEmmanuel Vadot 311de355beaSEmmanuel Vadot /* Depending on the PHY we need to route OTG to OHCI/EHCI */ 312de355beaSEmmanuel Vadot if (sc->phy_conf->phy0_route == true) { 313de355beaSEmmanuel Vadot if (vbus_det == 0) 314de355beaSEmmanuel Vadot /* Host mode */ 315de355beaSEmmanuel Vadot CLR4(sc->phy_ctrl, OTG_PHY_CFG, 316de355beaSEmmanuel Vadot OTG_PHY_ROUTE_OTG); 317de355beaSEmmanuel Vadot else 318de355beaSEmmanuel Vadot /* Peripheral mode */ 319de355beaSEmmanuel Vadot SET4(sc->phy_ctrl, OTG_PHY_CFG, 320de355beaSEmmanuel Vadot OTG_PHY_ROUTE_OTG); 321de355beaSEmmanuel Vadot } 322de355beaSEmmanuel Vadot if (vbus_det == 1) 323627c360fSJared McNeill return (0); 324627c360fSJared McNeill } else 325627c360fSJared McNeill error = 0; 326627c360fSJared McNeill if (error == 0) 327627c360fSJared McNeill error = regulator_enable(reg); 328627c360fSJared McNeill } else 329627c360fSJared McNeill error = regulator_disable(reg); 330de355beaSEmmanuel Vadot 331de355beaSEmmanuel Vadot out: 332627c360fSJared McNeill if (error != 0) { 3337dd62272SJared McNeill device_printf(dev, 3347dd62272SJared McNeill "couldn't %s regulator for phy %jd\n", 3357dd62272SJared McNeill enable ? "enable" : "disable", (intmax_t)phy); 336627c360fSJared McNeill return (error); 3376a05f063SJared McNeill } 3381b4bd023SJared McNeill 3391b4bd023SJared McNeill return (0); 3401b4bd023SJared McNeill } 3411b4bd023SJared McNeill 3421b4bd023SJared McNeill static int 3431b4bd023SJared McNeill awusbphy_probe(device_t dev) 3441b4bd023SJared McNeill { 3451b4bd023SJared McNeill if (!ofw_bus_status_okay(dev)) 3461b4bd023SJared McNeill return (ENXIO); 3471b4bd023SJared McNeill 3481b4bd023SJared McNeill if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 3491b4bd023SJared McNeill return (ENXIO); 3501b4bd023SJared McNeill 3511b4bd023SJared McNeill device_set_desc(dev, "Allwinner USB PHY"); 3521b4bd023SJared McNeill return (BUS_PROBE_DEFAULT); 3531b4bd023SJared McNeill } 3541b4bd023SJared McNeill 3551b4bd023SJared McNeill static int 3561b4bd023SJared McNeill awusbphy_attach(device_t dev) 3571b4bd023SJared McNeill { 3581b4bd023SJared McNeill int error; 3591b4bd023SJared McNeill 3601b4bd023SJared McNeill error = awusbphy_init(dev); 361627c360fSJared McNeill if (error) { 3621b4bd023SJared McNeill device_printf(dev, "failed to initialize USB PHY, error %d\n", 3631b4bd023SJared McNeill error); 364627c360fSJared McNeill return (error); 365627c360fSJared McNeill } 366627c360fSJared McNeill 367627c360fSJared McNeill phy_register_provider(dev); 3681b4bd023SJared McNeill 3691b4bd023SJared McNeill return (error); 3701b4bd023SJared McNeill } 3711b4bd023SJared McNeill 3721b4bd023SJared McNeill static device_method_t awusbphy_methods[] = { 3731b4bd023SJared McNeill /* Device interface */ 3741b4bd023SJared McNeill DEVMETHOD(device_probe, awusbphy_probe), 3751b4bd023SJared McNeill DEVMETHOD(device_attach, awusbphy_attach), 3761b4bd023SJared McNeill 377627c360fSJared McNeill /* PHY interface */ 378627c360fSJared McNeill DEVMETHOD(phy_enable, awusbphy_phy_enable), 379627c360fSJared McNeill 3801b4bd023SJared McNeill DEVMETHOD_END 3811b4bd023SJared McNeill }; 3821b4bd023SJared McNeill 3831b4bd023SJared McNeill static driver_t awusbphy_driver = { 3841b4bd023SJared McNeill "awusbphy", 3851b4bd023SJared McNeill awusbphy_methods, 386627c360fSJared McNeill sizeof(struct awusbphy_softc) 3871b4bd023SJared McNeill }; 3881b4bd023SJared McNeill 3891b4bd023SJared McNeill static devclass_t awusbphy_devclass; 3901b4bd023SJared McNeill 391627c360fSJared McNeill EARLY_DRIVER_MODULE(awusbphy, simplebus, awusbphy_driver, awusbphy_devclass, 392627c360fSJared McNeill 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE); 3931b4bd023SJared McNeill MODULE_VERSION(awusbphy, 1); 394