1 /*- 2 * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org> 3 * 4 * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 /* Based on sys/arm/ti/ti_sysc.c */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/module.h> 38 #include <sys/bus.h> 39 #include <sys/resource.h> 40 #include <sys/rman.h> 41 #include <sys/lock.h> 42 #include <sys/mutex.h> 43 44 #include <machine/bus.h> 45 #include <machine/resource.h> 46 47 #include <dev/fdt/simplebus.h> 48 49 #include <dev/ofw/openfirm.h> 50 #include <dev/ofw/ofw_bus.h> 51 #include <dev/ofw/ofw_bus_subr.h> 52 53 #include <arm/ti/ti_sysc.h> 54 55 #if 0 56 #define DPRINTF(dev, msg...) device_printf(dev, msg) 57 #else 58 #define DPRINTF(dev, msg...) 59 #endif 60 61 struct ti_am3359_cppi41_softc { 62 device_t dev; 63 struct syscon * syscon; 64 struct resource * res[4]; 65 bus_space_tag_t bst; 66 bus_space_handle_t bsh; 67 struct mtx mtx; 68 }; 69 70 static struct resource_spec ti_am3359_cppi41_res_spec[] = { 71 { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE }, 72 { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_SHAREABLE }, 73 { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_SHAREABLE }, 74 { SYS_RES_MEMORY, 3, RF_ACTIVE | RF_SHAREABLE }, 75 { -1, 0 } 76 }; 77 78 /* Device */ 79 static struct ofw_compat_data compat_data[] = { 80 { "ti,am3359-cppi41", 1 }, 81 { NULL, 0 } 82 }; 83 84 static int 85 ti_am3359_cppi41_write_4(device_t dev, bus_addr_t addr, uint32_t val) 86 { 87 struct ti_am3359_cppi41_softc *sc; 88 89 sc = device_get_softc(dev); 90 DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val); 91 mtx_lock(&sc->mtx); 92 bus_space_write_4(sc->bst, sc->bsh, addr, val); 93 mtx_unlock(&sc->mtx); 94 return (0); 95 } 96 97 static uint32_t 98 ti_am3359_cppi41_read_4(device_t dev, bus_addr_t addr) 99 { 100 struct ti_am3359_cppi41_softc *sc; 101 uint32_t val; 102 103 sc = device_get_softc(dev); 104 105 mtx_lock(&sc->mtx); 106 val = bus_space_read_4(sc->bst, sc->bsh, addr); 107 mtx_unlock(&sc->mtx); 108 DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, val); 109 return (val); 110 } 111 112 /* device interface */ 113 static int 114 ti_am3359_cppi41_probe(device_t dev) 115 { 116 if (!ofw_bus_status_okay(dev)) 117 return (ENXIO); 118 119 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 120 return (ENXIO); 121 122 device_set_desc(dev, "TI AM3359 CPPI 41"); 123 return(BUS_PROBE_DEFAULT); 124 } 125 126 static int 127 ti_am3359_cppi41_attach(device_t dev) 128 { 129 struct ti_am3359_cppi41_softc *sc; 130 uint32_t reg, reset_bit, timeout=10; 131 uint64_t sysc_address; 132 device_t parent; 133 134 sc = device_get_softc(dev); 135 sc->dev = dev; 136 137 if (bus_alloc_resources(dev, ti_am3359_cppi41_res_spec, sc->res)) { 138 device_printf(sc->dev, "Cant allocate resources\n"); 139 return (ENXIO); 140 } 141 142 sc->dev = dev; 143 sc->bst = rman_get_bustag(sc->res[0]); 144 sc->bsh = rman_get_bushandle(sc->res[0]); 145 146 mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF); 147 148 /* variant of am335x_usbss.c */ 149 DPRINTF(dev, "-- RESET USB --\n"); 150 parent = device_get_parent(dev); 151 reset_bit = ti_sysc_get_soft_reset_bit(parent); 152 if (reset_bit == 0) { 153 DPRINTF(dev, "Dont have reset bit\n"); 154 return (0); 155 } 156 sysc_address = ti_sysc_get_sysc_address_offset_host(parent); 157 DPRINTF(dev, "sysc_address %x\n", sysc_address); 158 ti_am3359_cppi41_write_4(dev, sysc_address, reset_bit); 159 DELAY(100); 160 reg = ti_am3359_cppi41_read_4(dev, sysc_address); 161 if ((reg & reset_bit) && timeout--) { 162 DPRINTF(dev, "Reset still ongoing - wait a little bit longer\n"); 163 DELAY(100); 164 reg = ti_am3359_cppi41_read_4(dev, sysc_address); 165 } 166 if (timeout == 0) 167 device_printf(dev, "USB Reset timeout\n"); 168 169 return (0); 170 } 171 172 static device_method_t ti_am3359_cppi41_methods[] = { 173 DEVMETHOD(device_probe, ti_am3359_cppi41_probe), 174 DEVMETHOD(device_attach, ti_am3359_cppi41_attach), 175 176 DEVMETHOD_END 177 }; 178 179 DEFINE_CLASS_1(ti_am3359_cppi41, ti_am3359_cppi41_driver, 180 ti_am3359_cppi41_methods,sizeof(struct ti_am3359_cppi41_softc), 181 simplebus_driver); 182 183 EARLY_DRIVER_MODULE(ti_am3359_cppi41, simplebus, ti_am3359_cppi41_driver, 0, 0, 184 BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); 185 MODULE_VERSION(ti_am3359_cppi41, 1); 186 MODULE_DEPEND(ti_am3359_cppi41, ti_sysc, 1, 1, 1); 187