1*6a05f063SJared McNeill /*- 2*6a05f063SJared McNeill * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca> 3*6a05f063SJared McNeill * All rights reserved. 4*6a05f063SJared McNeill * 5*6a05f063SJared McNeill * Redistribution and use in source and binary forms, with or without 6*6a05f063SJared McNeill * modification, are permitted provided that the following conditions 7*6a05f063SJared McNeill * are met: 8*6a05f063SJared McNeill * 1. Redistributions of source code must retain the above copyright 9*6a05f063SJared McNeill * notice, this list of conditions and the following disclaimer. 10*6a05f063SJared McNeill * 2. Redistributions in binary form must reproduce the above copyright 11*6a05f063SJared McNeill * notice, this list of conditions and the following disclaimer in the 12*6a05f063SJared McNeill * documentation and/or other materials provided with the distribution. 13*6a05f063SJared McNeill * 14*6a05f063SJared McNeill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15*6a05f063SJared McNeill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16*6a05f063SJared McNeill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17*6a05f063SJared McNeill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18*6a05f063SJared McNeill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19*6a05f063SJared McNeill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20*6a05f063SJared McNeill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 21*6a05f063SJared McNeill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22*6a05f063SJared McNeill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*6a05f063SJared McNeill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*6a05f063SJared McNeill * SUCH DAMAGE. 25*6a05f063SJared McNeill * 26*6a05f063SJared McNeill * $FreeBSD$ 27*6a05f063SJared McNeill */ 28*6a05f063SJared McNeill 29*6a05f063SJared McNeill /* 30*6a05f063SJared McNeill * Allwinner module software reset registers 31*6a05f063SJared McNeill */ 32*6a05f063SJared McNeill 33*6a05f063SJared McNeill #include <sys/cdefs.h> 34*6a05f063SJared McNeill __FBSDID("$FreeBSD$"); 35*6a05f063SJared McNeill 36*6a05f063SJared McNeill #include <sys/param.h> 37*6a05f063SJared McNeill #include <sys/systm.h> 38*6a05f063SJared McNeill #include <sys/bus.h> 39*6a05f063SJared McNeill #include <sys/rman.h> 40*6a05f063SJared McNeill #include <sys/kernel.h> 41*6a05f063SJared McNeill #include <sys/module.h> 42*6a05f063SJared McNeill #include <machine/bus.h> 43*6a05f063SJared McNeill 44*6a05f063SJared McNeill #include <dev/ofw/ofw_bus.h> 45*6a05f063SJared McNeill #include <dev/ofw/ofw_bus_subr.h> 46*6a05f063SJared McNeill 47*6a05f063SJared McNeill #include <dev/extres/hwreset/hwreset.h> 48*6a05f063SJared McNeill 49*6a05f063SJared McNeill #include "hwreset_if.h" 50*6a05f063SJared McNeill 51*6a05f063SJared McNeill #define RESET_OFFSET(index) ((index / 32) * 4) 52*6a05f063SJared McNeill #define RESET_SHIFT(index) (index % 32) 53*6a05f063SJared McNeill 54*6a05f063SJared McNeill static struct ofw_compat_data compat_data[] = { 55*6a05f063SJared McNeill { "allwinner,sun6i-a31-ahb1-reset", 1 }, 56*6a05f063SJared McNeill { "allwinner,sun6i-a31-clock-reset", 1 }, 57*6a05f063SJared McNeill { NULL, 0 } 58*6a05f063SJared McNeill }; 59*6a05f063SJared McNeill 60*6a05f063SJared McNeill struct aw_reset_softc { 61*6a05f063SJared McNeill struct resource *res; 62*6a05f063SJared McNeill struct mtx mtx; 63*6a05f063SJared McNeill }; 64*6a05f063SJared McNeill 65*6a05f063SJared McNeill static struct resource_spec aw_reset_spec[] = { 66*6a05f063SJared McNeill { SYS_RES_MEMORY, 0, RF_ACTIVE }, 67*6a05f063SJared McNeill { -1, 0 } 68*6a05f063SJared McNeill }; 69*6a05f063SJared McNeill 70*6a05f063SJared McNeill #define RESET_READ(sc, reg) bus_read_4((sc)->res, (reg)) 71*6a05f063SJared McNeill #define RESET_WRITE(sc, reg, val) bus_write_4((sc)->res, (reg), (val)) 72*6a05f063SJared McNeill 73*6a05f063SJared McNeill static int 74*6a05f063SJared McNeill aw_reset_assert(device_t dev, intptr_t id, bool reset) 75*6a05f063SJared McNeill { 76*6a05f063SJared McNeill struct aw_reset_softc *sc; 77*6a05f063SJared McNeill uint32_t reg_value; 78*6a05f063SJared McNeill 79*6a05f063SJared McNeill sc = device_get_softc(dev); 80*6a05f063SJared McNeill 81*6a05f063SJared McNeill mtx_lock(&sc->mtx); 82*6a05f063SJared McNeill reg_value = RESET_READ(sc, RESET_OFFSET(id)); 83*6a05f063SJared McNeill if (reset) 84*6a05f063SJared McNeill reg_value &= ~(1 << RESET_SHIFT(id)); 85*6a05f063SJared McNeill else 86*6a05f063SJared McNeill reg_value |= (1 << RESET_SHIFT(id)); 87*6a05f063SJared McNeill RESET_WRITE(sc, RESET_OFFSET(id), reg_value); 88*6a05f063SJared McNeill mtx_unlock(&sc->mtx); 89*6a05f063SJared McNeill 90*6a05f063SJared McNeill return (0); 91*6a05f063SJared McNeill } 92*6a05f063SJared McNeill 93*6a05f063SJared McNeill static int 94*6a05f063SJared McNeill aw_reset_is_asserted(device_t dev, intptr_t id, bool *reset) 95*6a05f063SJared McNeill { 96*6a05f063SJared McNeill struct aw_reset_softc *sc; 97*6a05f063SJared McNeill uint32_t reg_value; 98*6a05f063SJared McNeill 99*6a05f063SJared McNeill sc = device_get_softc(dev); 100*6a05f063SJared McNeill 101*6a05f063SJared McNeill mtx_lock(&sc->mtx); 102*6a05f063SJared McNeill reg_value = RESET_READ(sc, RESET_OFFSET(id)); 103*6a05f063SJared McNeill mtx_unlock(&sc->mtx); 104*6a05f063SJared McNeill 105*6a05f063SJared McNeill *reset = (reg_value & (1 << RESET_SHIFT(id))) != 0 ? false : true; 106*6a05f063SJared McNeill 107*6a05f063SJared McNeill return (0); 108*6a05f063SJared McNeill } 109*6a05f063SJared McNeill 110*6a05f063SJared McNeill static int 111*6a05f063SJared McNeill aw_reset_probe(device_t dev) 112*6a05f063SJared McNeill { 113*6a05f063SJared McNeill if (!ofw_bus_status_okay(dev)) 114*6a05f063SJared McNeill return (ENXIO); 115*6a05f063SJared McNeill 116*6a05f063SJared McNeill if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 117*6a05f063SJared McNeill return (ENXIO); 118*6a05f063SJared McNeill 119*6a05f063SJared McNeill device_set_desc(dev, "Allwinner Module Resets"); 120*6a05f063SJared McNeill return (BUS_PROBE_DEFAULT); 121*6a05f063SJared McNeill } 122*6a05f063SJared McNeill 123*6a05f063SJared McNeill static int 124*6a05f063SJared McNeill aw_reset_attach(device_t dev) 125*6a05f063SJared McNeill { 126*6a05f063SJared McNeill struct aw_reset_softc *sc; 127*6a05f063SJared McNeill 128*6a05f063SJared McNeill sc = device_get_softc(dev); 129*6a05f063SJared McNeill 130*6a05f063SJared McNeill if (bus_alloc_resources(dev, aw_reset_spec, &sc->res) != 0) { 131*6a05f063SJared McNeill device_printf(dev, "cannot allocate resources for device\n"); 132*6a05f063SJared McNeill return (ENXIO); 133*6a05f063SJared McNeill } 134*6a05f063SJared McNeill 135*6a05f063SJared McNeill mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); 136*6a05f063SJared McNeill 137*6a05f063SJared McNeill hwreset_register_ofw_provider(dev); 138*6a05f063SJared McNeill 139*6a05f063SJared McNeill return (0); 140*6a05f063SJared McNeill } 141*6a05f063SJared McNeill 142*6a05f063SJared McNeill static device_method_t aw_reset_methods[] = { 143*6a05f063SJared McNeill /* Device interface */ 144*6a05f063SJared McNeill DEVMETHOD(device_probe, aw_reset_probe), 145*6a05f063SJared McNeill DEVMETHOD(device_attach, aw_reset_attach), 146*6a05f063SJared McNeill 147*6a05f063SJared McNeill /* Reset interface */ 148*6a05f063SJared McNeill DEVMETHOD(hwreset_assert, aw_reset_assert), 149*6a05f063SJared McNeill DEVMETHOD(hwreset_is_asserted, aw_reset_is_asserted), 150*6a05f063SJared McNeill 151*6a05f063SJared McNeill DEVMETHOD_END 152*6a05f063SJared McNeill }; 153*6a05f063SJared McNeill 154*6a05f063SJared McNeill static driver_t aw_reset_driver = { 155*6a05f063SJared McNeill "aw_reset", 156*6a05f063SJared McNeill aw_reset_methods, 157*6a05f063SJared McNeill sizeof(struct aw_reset_softc), 158*6a05f063SJared McNeill }; 159*6a05f063SJared McNeill 160*6a05f063SJared McNeill static devclass_t aw_reset_devclass; 161*6a05f063SJared McNeill 162*6a05f063SJared McNeill DRIVER_MODULE(aw_reset, simplebus, aw_reset_driver, aw_reset_devclass, 0, 0); 163*6a05f063SJared McNeill MODULE_VERSION(aw_reset, 1); 164