1e83ce340SAdrian Chadd /*- 2*f4a3eb02SAdrian Chadd * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org> 3e83ce340SAdrian Chadd * All rights reserved. 4e83ce340SAdrian Chadd * 5e83ce340SAdrian Chadd * Redistribution and use in source and binary forms, with or without 6e83ce340SAdrian Chadd * modification, are permitted provided that the following conditions 7e83ce340SAdrian Chadd * are met: 8e83ce340SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 9e83ce340SAdrian Chadd * notice, this list of conditions and the following disclaimer, 10e83ce340SAdrian Chadd * without modification. 11e83ce340SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12e83ce340SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13e83ce340SAdrian Chadd * redistribution must be conditioned upon including a substantially 14e83ce340SAdrian Chadd * similar Disclaimer requirement for further binary redistribution. 15e83ce340SAdrian Chadd * 16e83ce340SAdrian Chadd * NO WARRANTY 17e83ce340SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18e83ce340SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19e83ce340SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20e83ce340SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21e83ce340SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22e83ce340SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23e83ce340SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24e83ce340SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25e83ce340SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26e83ce340SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27e83ce340SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES. 28e83ce340SAdrian Chadd */ 29e83ce340SAdrian Chadd 30e83ce340SAdrian Chadd #include <sys/cdefs.h> 31e83ce340SAdrian Chadd __FBSDID("$FreeBSD$"); 32e83ce340SAdrian Chadd 33*f4a3eb02SAdrian Chadd /* 34*f4a3eb02SAdrian Chadd * BHND SPROM driver. 35*f4a3eb02SAdrian Chadd * 36*f4a3eb02SAdrian Chadd * Abstract driver for memory-mapped SPROM devices. 37*f4a3eb02SAdrian Chadd */ 38*f4a3eb02SAdrian Chadd 39e83ce340SAdrian Chadd #include <sys/param.h> 40*f4a3eb02SAdrian Chadd #include <sys/kernel.h> 41e83ce340SAdrian Chadd #include <sys/bus.h> 42*f4a3eb02SAdrian Chadd #include <sys/limits.h> 43*f4a3eb02SAdrian Chadd #include <sys/malloc.h> 44*f4a3eb02SAdrian Chadd #include <sys/module.h> 45e83ce340SAdrian Chadd #include <sys/systm.h> 46e83ce340SAdrian Chadd 47e83ce340SAdrian Chadd #include <machine/bus.h> 48*f4a3eb02SAdrian Chadd #include <sys/rman.h> 49e83ce340SAdrian Chadd #include <machine/resource.h> 50e83ce340SAdrian Chadd 51*f4a3eb02SAdrian Chadd #include <dev/bhnd/bhnd.h> 52e83ce340SAdrian Chadd 53*f4a3eb02SAdrian Chadd #include "bhnd_nvram_if.h" 54e83ce340SAdrian Chadd 55e83ce340SAdrian Chadd #include "bhnd_spromvar.h" 56e83ce340SAdrian Chadd 57*f4a3eb02SAdrian Chadd #define SPROM_LOCK_INIT(sc) \ 58*f4a3eb02SAdrian Chadd mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ 59*f4a3eb02SAdrian Chadd "BHND SPROM lock", MTX_DEF) 60*f4a3eb02SAdrian Chadd #define SPROM_LOCK(sc) mtx_lock(&(sc)->mtx) 61*f4a3eb02SAdrian Chadd #define SPROM_UNLOCK(sc) mtx_unlock(&(sc)->mtx) 62*f4a3eb02SAdrian Chadd #define SPROM_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what) 63*f4a3eb02SAdrian Chadd #define SPROM_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx) 64e83ce340SAdrian Chadd 65e83ce340SAdrian Chadd /** 66*f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of DEVICE_PROBE(). 67e83ce340SAdrian Chadd */ 68e83ce340SAdrian Chadd int 69*f4a3eb02SAdrian Chadd bhnd_sprom_probe(device_t dev) 70e83ce340SAdrian Chadd { 71*f4a3eb02SAdrian Chadd /* Quiet by default */ 72*f4a3eb02SAdrian Chadd if (!bootverbose) 73*f4a3eb02SAdrian Chadd device_quiet(dev); 74*f4a3eb02SAdrian Chadd device_set_desc(dev, "Broadcom SPROM/OTP"); 75*f4a3eb02SAdrian Chadd 76*f4a3eb02SAdrian Chadd /* Refuse wildcard attachments */ 77*f4a3eb02SAdrian Chadd return (BUS_PROBE_NOWILDCARD); 78*f4a3eb02SAdrian Chadd } 79*f4a3eb02SAdrian Chadd 80*f4a3eb02SAdrian Chadd /** 81*f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of DEVICE_ATTACH(). 82*f4a3eb02SAdrian Chadd * 83*f4a3eb02SAdrian Chadd * Assumes sprom is mapped via YS_RES_MEMORY resource with RID 0. 84*f4a3eb02SAdrian Chadd */ 85*f4a3eb02SAdrian Chadd int 86*f4a3eb02SAdrian Chadd bhnd_sprom_attach(device_t dev) 87*f4a3eb02SAdrian Chadd { 88*f4a3eb02SAdrian Chadd struct bhnd_sprom_softc *sc; 89e83ce340SAdrian Chadd int error; 90e83ce340SAdrian Chadd 91*f4a3eb02SAdrian Chadd sc = device_get_softc(dev); 92*f4a3eb02SAdrian Chadd sc->dev = dev; 93e83ce340SAdrian Chadd 94*f4a3eb02SAdrian Chadd /* Allocate SPROM resource */ 95*f4a3eb02SAdrian Chadd sc->sprom_rid = 0; 96*f4a3eb02SAdrian Chadd sc->sprom_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, 97*f4a3eb02SAdrian Chadd &sc->sprom_rid, RF_ACTIVE); 98*f4a3eb02SAdrian Chadd if (sc->sprom_res == NULL) { 99*f4a3eb02SAdrian Chadd device_printf(dev, "failed to allocate resources\n"); 100*f4a3eb02SAdrian Chadd return (ENXIO); 101*f4a3eb02SAdrian Chadd } 102e83ce340SAdrian Chadd 103*f4a3eb02SAdrian Chadd /* Initialize SPROM shadow */ 104*f4a3eb02SAdrian Chadd if ((error = bhnd_sprom_init(&sc->shadow, sc->sprom_res, 0))) { 105*f4a3eb02SAdrian Chadd device_printf(dev, "unrecognized SPROM format\n"); 106*f4a3eb02SAdrian Chadd goto failed; 107*f4a3eb02SAdrian Chadd } 108e83ce340SAdrian Chadd 109*f4a3eb02SAdrian Chadd /* Initialize mutex */ 110*f4a3eb02SAdrian Chadd SPROM_LOCK_INIT(sc); 111e83ce340SAdrian Chadd 112*f4a3eb02SAdrian Chadd return (0); 113*f4a3eb02SAdrian Chadd 114*f4a3eb02SAdrian Chadd failed: 115*f4a3eb02SAdrian Chadd bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid, 116*f4a3eb02SAdrian Chadd sc->sprom_res); 117e83ce340SAdrian Chadd return (error); 118*f4a3eb02SAdrian Chadd } 119*f4a3eb02SAdrian Chadd 120*f4a3eb02SAdrian Chadd /** 121*f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of DEVICE_DETACH(). 122*f4a3eb02SAdrian Chadd */ 123*f4a3eb02SAdrian Chadd int 124*f4a3eb02SAdrian Chadd bhnd_sprom_resume(device_t dev) 125*f4a3eb02SAdrian Chadd { 126*f4a3eb02SAdrian Chadd return (0); 127*f4a3eb02SAdrian Chadd } 128*f4a3eb02SAdrian Chadd 129*f4a3eb02SAdrian Chadd /** 130*f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of DEVICE_DETACH(). 131*f4a3eb02SAdrian Chadd */ 132*f4a3eb02SAdrian Chadd int 133*f4a3eb02SAdrian Chadd bhnd_sprom_suspend(device_t dev) 134*f4a3eb02SAdrian Chadd { 135*f4a3eb02SAdrian Chadd return (0); 136*f4a3eb02SAdrian Chadd } 137*f4a3eb02SAdrian Chadd 138*f4a3eb02SAdrian Chadd /** 139*f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of DEVICE_DETACH(). 140*f4a3eb02SAdrian Chadd */ 141*f4a3eb02SAdrian Chadd int 142*f4a3eb02SAdrian Chadd bhnd_sprom_detach(device_t dev) 143*f4a3eb02SAdrian Chadd { 144*f4a3eb02SAdrian Chadd struct bhnd_sprom_softc *sc; 145*f4a3eb02SAdrian Chadd 146*f4a3eb02SAdrian Chadd sc = device_get_softc(dev); 147*f4a3eb02SAdrian Chadd 148*f4a3eb02SAdrian Chadd bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid, 149*f4a3eb02SAdrian Chadd sc->sprom_res); 150*f4a3eb02SAdrian Chadd bhnd_sprom_fini(&sc->shadow); 151*f4a3eb02SAdrian Chadd SPROM_LOCK_DESTROY(sc); 152e83ce340SAdrian Chadd 153e83ce340SAdrian Chadd return (0); 154e83ce340SAdrian Chadd } 155e83ce340SAdrian Chadd 156e83ce340SAdrian Chadd /** 157*f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of BHND_NVRAM_GETVAR(). 158e83ce340SAdrian Chadd */ 159*f4a3eb02SAdrian Chadd static int 160*f4a3eb02SAdrian Chadd bhnd_sprom_getvar_meth(device_t dev, const char *name, void *buf, size_t *len) 161e83ce340SAdrian Chadd { 162*f4a3eb02SAdrian Chadd struct bhnd_sprom_softc *sc; 163e83ce340SAdrian Chadd int error; 164e83ce340SAdrian Chadd 165*f4a3eb02SAdrian Chadd sc = device_get_softc(dev); 166*f4a3eb02SAdrian Chadd 167*f4a3eb02SAdrian Chadd SPROM_LOCK(sc); 168*f4a3eb02SAdrian Chadd error = bhnd_sprom_getvar(&sc->shadow, name, buf, len); 169*f4a3eb02SAdrian Chadd SPROM_UNLOCK(sc); 170*f4a3eb02SAdrian Chadd 171e83ce340SAdrian Chadd return (error); 172e83ce340SAdrian Chadd } 173e83ce340SAdrian Chadd 174e83ce340SAdrian Chadd /** 175*f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of BHND_NVRAM_SETVAR(). 176e83ce340SAdrian Chadd */ 177*f4a3eb02SAdrian Chadd static int 178*f4a3eb02SAdrian Chadd bhnd_sprom_setvar_meth(device_t dev, const char *name, const void *buf, 179e83ce340SAdrian Chadd size_t len) 180e83ce340SAdrian Chadd { 181*f4a3eb02SAdrian Chadd struct bhnd_sprom_softc *sc; 182e83ce340SAdrian Chadd int error; 183e83ce340SAdrian Chadd 184*f4a3eb02SAdrian Chadd sc = device_get_softc(dev); 185e83ce340SAdrian Chadd 186*f4a3eb02SAdrian Chadd SPROM_LOCK(sc); 187*f4a3eb02SAdrian Chadd error = bhnd_sprom_setvar(&sc->shadow, name, buf, len); 188*f4a3eb02SAdrian Chadd SPROM_UNLOCK(sc); 189e83ce340SAdrian Chadd 190e83ce340SAdrian Chadd return (error); 191e83ce340SAdrian Chadd } 192e83ce340SAdrian Chadd 193*f4a3eb02SAdrian Chadd static device_method_t bhnd_sprom_methods[] = { 194*f4a3eb02SAdrian Chadd /* Device interface */ 195*f4a3eb02SAdrian Chadd DEVMETHOD(device_probe, bhnd_sprom_probe), 196*f4a3eb02SAdrian Chadd DEVMETHOD(device_attach, bhnd_sprom_attach), 197*f4a3eb02SAdrian Chadd DEVMETHOD(device_resume, bhnd_sprom_resume), 198*f4a3eb02SAdrian Chadd DEVMETHOD(device_suspend, bhnd_sprom_suspend), 199*f4a3eb02SAdrian Chadd DEVMETHOD(device_detach, bhnd_sprom_detach), 200e83ce340SAdrian Chadd 201*f4a3eb02SAdrian Chadd /* NVRAM interface */ 202*f4a3eb02SAdrian Chadd DEVMETHOD(bhnd_nvram_getvar, bhnd_sprom_getvar_meth), 203*f4a3eb02SAdrian Chadd DEVMETHOD(bhnd_nvram_setvar, bhnd_sprom_setvar_meth), 204e83ce340SAdrian Chadd 205*f4a3eb02SAdrian Chadd DEVMETHOD_END 206*f4a3eb02SAdrian Chadd }; 207e83ce340SAdrian Chadd 208*f4a3eb02SAdrian Chadd DEFINE_CLASS_0(bhnd_nvram, bhnd_sprom_driver, bhnd_sprom_methods, sizeof(struct bhnd_sprom_softc)); 209*f4a3eb02SAdrian Chadd MODULE_VERSION(bhnd_sprom, 1); 210