aw_usbphy.c revision 297627
1296284Sjmcneill/*- 2296284Sjmcneill * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca> 3296284Sjmcneill * All rights reserved. 4296284Sjmcneill * 5296284Sjmcneill * Redistribution and use in source and binary forms, with or without 6296284Sjmcneill * modification, are permitted provided that the following conditions 7296284Sjmcneill * are met: 8296284Sjmcneill * 1. Redistributions of source code must retain the above copyright 9296284Sjmcneill * notice, this list of conditions and the following disclaimer. 10296284Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright 11296284Sjmcneill * notice, this list of conditions and the following disclaimer in the 12296284Sjmcneill * documentation and/or other materials provided with the distribution. 13296284Sjmcneill * 14296284Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15296284Sjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16296284Sjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17296284Sjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18296284Sjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19296284Sjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20296284Sjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 21296284Sjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22296284Sjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23296284Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24296284Sjmcneill * SUCH DAMAGE. 25296284Sjmcneill * 26296284Sjmcneill * $FreeBSD: head/sys/arm/allwinner/aw_usbphy.c 297627 2016-04-06 23:11:03Z jmcneill $ 27296284Sjmcneill */ 28296284Sjmcneill 29296284Sjmcneill/* 30296284Sjmcneill * Allwinner USB PHY 31296284Sjmcneill */ 32296284Sjmcneill 33296284Sjmcneill#include <sys/cdefs.h> 34296284Sjmcneill__FBSDID("$FreeBSD: head/sys/arm/allwinner/aw_usbphy.c 297627 2016-04-06 23:11:03Z jmcneill $"); 35296284Sjmcneill 36296284Sjmcneill#include <sys/param.h> 37296284Sjmcneill#include <sys/systm.h> 38296284Sjmcneill#include <sys/bus.h> 39296284Sjmcneill#include <sys/rman.h> 40296284Sjmcneill#include <sys/kernel.h> 41296284Sjmcneill#include <sys/module.h> 42296284Sjmcneill#include <sys/gpio.h> 43296284Sjmcneill 44296284Sjmcneill#include <dev/ofw/ofw_bus.h> 45296284Sjmcneill#include <dev/ofw/ofw_bus_subr.h> 46296284Sjmcneill 47297627Sjmcneill#include <dev/extres/clk/clk.h> 48297627Sjmcneill#include <dev/extres/hwreset/hwreset.h> 49297627Sjmcneill#include <dev/extres/regulator/regulator.h> 50296284Sjmcneill 51296284Sjmcneill#define USBPHY_NUMOFF 3 52296284Sjmcneill 53296284Sjmcneillstatic struct ofw_compat_data compat_data[] = { 54296284Sjmcneill { "allwinner,sun4i-a10-usb-phy", 1 }, 55296284Sjmcneill { "allwinner,sun5i-a13-usb-phy", 1 }, 56296284Sjmcneill { "allwinner,sun6i-a31-usb-phy", 1 }, 57296284Sjmcneill { "allwinner,sun7i-a20-usb-phy", 1 }, 58296284Sjmcneill { NULL, 0 } 59296284Sjmcneill}; 60296284Sjmcneill 61296284Sjmcneillstatic int 62296284Sjmcneillawusbphy_init(device_t dev) 63296284Sjmcneill{ 64296284Sjmcneill char pname[20]; 65296284Sjmcneill int error, off; 66297627Sjmcneill regulator_t reg; 67297627Sjmcneill hwreset_t rst; 68297627Sjmcneill clk_t clk; 69296284Sjmcneill 70297627Sjmcneill /* Enable clocks */ 71297627Sjmcneill for (off = 0; clk_get_by_ofw_index(dev, off, &clk) == 0; off++) { 72297627Sjmcneill error = clk_enable(clk); 73297627Sjmcneill if (error != 0) { 74297627Sjmcneill device_printf(dev, "couldn't enable clock %s\n", 75297627Sjmcneill clk_get_name(clk)); 76296284Sjmcneill return (error); 77297627Sjmcneill } 78297627Sjmcneill } 79296284Sjmcneill 80297627Sjmcneill /* De-assert resets */ 81297627Sjmcneill for (off = 0; hwreset_get_by_ofw_idx(dev, off, &rst) == 0; off++) { 82297627Sjmcneill error = hwreset_deassert(rst); 83297627Sjmcneill if (error != 0) { 84297627Sjmcneill device_printf(dev, "couldn't de-assert reset %d\n", 85297627Sjmcneill off); 86296284Sjmcneill return (error); 87297627Sjmcneill } 88297627Sjmcneill } 89296284Sjmcneill 90297627Sjmcneill /* Enable regulator(s) */ 91297627Sjmcneill for (off = 0; off < USBPHY_NUMOFF; off++) { 92296284Sjmcneill snprintf(pname, sizeof(pname), "usb%d_vbus-supply", off); 93297627Sjmcneill if (regulator_get_by_ofw_property(dev, pname, ®) != 0) 94297627Sjmcneill continue; 95297627Sjmcneill error = regulator_enable(reg); 96297627Sjmcneill if (error != 0) { 97297627Sjmcneill device_printf(dev, "couldn't enable regulator %s\n", 98297627Sjmcneill pname); 99296284Sjmcneill return (error); 100297627Sjmcneill } 101296284Sjmcneill } 102296284Sjmcneill 103296284Sjmcneill return (0); 104296284Sjmcneill} 105296284Sjmcneill 106296284Sjmcneillstatic int 107296284Sjmcneillawusbphy_probe(device_t dev) 108296284Sjmcneill{ 109296284Sjmcneill if (!ofw_bus_status_okay(dev)) 110296284Sjmcneill return (ENXIO); 111296284Sjmcneill 112296284Sjmcneill if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 113296284Sjmcneill return (ENXIO); 114296284Sjmcneill 115296284Sjmcneill device_set_desc(dev, "Allwinner USB PHY"); 116296284Sjmcneill return (BUS_PROBE_DEFAULT); 117296284Sjmcneill} 118296284Sjmcneill 119296284Sjmcneillstatic int 120296284Sjmcneillawusbphy_attach(device_t dev) 121296284Sjmcneill{ 122296284Sjmcneill int error; 123296284Sjmcneill 124296284Sjmcneill error = awusbphy_init(dev); 125296284Sjmcneill if (error) 126296284Sjmcneill device_printf(dev, "failed to initialize USB PHY, error %d\n", 127296284Sjmcneill error); 128296284Sjmcneill 129296284Sjmcneill return (error); 130296284Sjmcneill} 131296284Sjmcneill 132296284Sjmcneillstatic device_method_t awusbphy_methods[] = { 133296284Sjmcneill /* Device interface */ 134296284Sjmcneill DEVMETHOD(device_probe, awusbphy_probe), 135296284Sjmcneill DEVMETHOD(device_attach, awusbphy_attach), 136296284Sjmcneill 137296284Sjmcneill DEVMETHOD_END 138296284Sjmcneill}; 139296284Sjmcneill 140296284Sjmcneillstatic driver_t awusbphy_driver = { 141296284Sjmcneill "awusbphy", 142296284Sjmcneill awusbphy_methods, 143296284Sjmcneill 0, 144296284Sjmcneill}; 145296284Sjmcneill 146296284Sjmcneillstatic devclass_t awusbphy_devclass; 147296284Sjmcneill 148296284SjmcneillDRIVER_MODULE(awusbphy, simplebus, awusbphy_driver, awusbphy_devclass, 0, 0); 149296284SjmcneillMODULE_VERSION(awusbphy, 1); 150