1e83ce340SAdrian Chadd /*- 2f4a3eb02SAdrian 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 33f4a3eb02SAdrian Chadd /* 34f4a3eb02SAdrian Chadd * BHND SPROM driver. 35f4a3eb02SAdrian Chadd * 36f4a3eb02SAdrian Chadd * Abstract driver for memory-mapped SPROM devices. 37f4a3eb02SAdrian Chadd */ 38f4a3eb02SAdrian Chadd 39e83ce340SAdrian Chadd #include <sys/param.h> 40f4a3eb02SAdrian Chadd #include <sys/kernel.h> 41e83ce340SAdrian Chadd #include <sys/bus.h> 42f4a3eb02SAdrian Chadd #include <sys/limits.h> 43f4a3eb02SAdrian Chadd #include <sys/malloc.h> 44f4a3eb02SAdrian Chadd #include <sys/module.h> 45e83ce340SAdrian Chadd #include <sys/systm.h> 46e83ce340SAdrian Chadd 47e83ce340SAdrian Chadd #include <machine/bus.h> 48f4a3eb02SAdrian Chadd #include <sys/rman.h> 49e83ce340SAdrian Chadd #include <machine/resource.h> 50e83ce340SAdrian Chadd 51f4a3eb02SAdrian Chadd #include <dev/bhnd/bhnd.h> 52e83ce340SAdrian Chadd 53f4a3eb02SAdrian Chadd #include "bhnd_nvram_if.h" 54e83ce340SAdrian Chadd 55e83ce340SAdrian Chadd #include "bhnd_spromvar.h" 56e83ce340SAdrian Chadd 57f4a3eb02SAdrian Chadd #define SPROM_LOCK_INIT(sc) \ 58f4a3eb02SAdrian Chadd mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ 59f4a3eb02SAdrian Chadd "BHND SPROM lock", MTX_DEF) 60f4a3eb02SAdrian Chadd #define SPROM_LOCK(sc) mtx_lock(&(sc)->mtx) 61f4a3eb02SAdrian Chadd #define SPROM_UNLOCK(sc) mtx_unlock(&(sc)->mtx) 62f4a3eb02SAdrian Chadd #define SPROM_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what) 63f4a3eb02SAdrian Chadd #define SPROM_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx) 64e83ce340SAdrian Chadd 65e83ce340SAdrian Chadd /** 66f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of DEVICE_PROBE(). 67e83ce340SAdrian Chadd */ 68e83ce340SAdrian Chadd int 69f4a3eb02SAdrian Chadd bhnd_sprom_probe(device_t dev) 70e83ce340SAdrian Chadd { 71f4a3eb02SAdrian Chadd /* Quiet by default */ 72f4a3eb02SAdrian Chadd if (!bootverbose) 73f4a3eb02SAdrian Chadd device_quiet(dev); 74*56a4cdd1SLandon J. Fuller device_set_desc(dev, "SPROM/OTP"); 75f4a3eb02SAdrian Chadd 76f4a3eb02SAdrian Chadd /* Refuse wildcard attachments */ 77f4a3eb02SAdrian Chadd return (BUS_PROBE_NOWILDCARD); 78f4a3eb02SAdrian Chadd } 79f4a3eb02SAdrian Chadd 80*56a4cdd1SLandon J. Fuller /* Default DEVICE_ATTACH() implementation; assumes a zero offset to the 81*56a4cdd1SLandon J. Fuller * SPROM data */ 82*56a4cdd1SLandon J. Fuller static int 83*56a4cdd1SLandon J. Fuller bhnd_sprom_attach_meth(device_t dev) 84*56a4cdd1SLandon J. Fuller { 85*56a4cdd1SLandon J. Fuller return (bhnd_sprom_attach(dev, 0)); 86*56a4cdd1SLandon J. Fuller } 87*56a4cdd1SLandon J. Fuller 88f4a3eb02SAdrian Chadd /** 89*56a4cdd1SLandon J. Fuller * BHND SPROM device attach. 90f4a3eb02SAdrian Chadd * 91*56a4cdd1SLandon J. Fuller * This should be called from DEVICE_ATTACH() with the @p offset to the 92*56a4cdd1SLandon J. Fuller * SPROM data. 93*56a4cdd1SLandon J. Fuller * 94*56a4cdd1SLandon J. Fuller * Assumes SPROM is mapped via SYS_RES_MEMORY resource with RID 0. 95*56a4cdd1SLandon J. Fuller * 96*56a4cdd1SLandon J. Fuller * @param dev BHND SPROM device. 97*56a4cdd1SLandon J. Fuller * @param offset Offset to the SPROM data. 98f4a3eb02SAdrian Chadd */ 99f4a3eb02SAdrian Chadd int 100*56a4cdd1SLandon J. Fuller bhnd_sprom_attach(device_t dev, bus_size_t offset) 101f4a3eb02SAdrian Chadd { 102f4a3eb02SAdrian Chadd struct bhnd_sprom_softc *sc; 103e83ce340SAdrian Chadd int error; 104e83ce340SAdrian Chadd 105f4a3eb02SAdrian Chadd sc = device_get_softc(dev); 106f4a3eb02SAdrian Chadd sc->dev = dev; 107e83ce340SAdrian Chadd 108f4a3eb02SAdrian Chadd /* Allocate SPROM resource */ 109f4a3eb02SAdrian Chadd sc->sprom_rid = 0; 110f4a3eb02SAdrian Chadd sc->sprom_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, 111f4a3eb02SAdrian Chadd &sc->sprom_rid, RF_ACTIVE); 112f4a3eb02SAdrian Chadd if (sc->sprom_res == NULL) { 113f4a3eb02SAdrian Chadd device_printf(dev, "failed to allocate resources\n"); 114f4a3eb02SAdrian Chadd return (ENXIO); 115f4a3eb02SAdrian Chadd } 116e83ce340SAdrian Chadd 117f4a3eb02SAdrian Chadd /* Initialize SPROM shadow */ 118*56a4cdd1SLandon J. Fuller if ((error = bhnd_sprom_init(&sc->shadow, sc->sprom_res, offset))) 119f4a3eb02SAdrian Chadd goto failed; 120e83ce340SAdrian Chadd 121f4a3eb02SAdrian Chadd /* Initialize mutex */ 122f4a3eb02SAdrian Chadd SPROM_LOCK_INIT(sc); 123e83ce340SAdrian Chadd 124f4a3eb02SAdrian Chadd return (0); 125f4a3eb02SAdrian Chadd 126f4a3eb02SAdrian Chadd failed: 127f4a3eb02SAdrian Chadd bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid, 128f4a3eb02SAdrian Chadd sc->sprom_res); 129e83ce340SAdrian Chadd return (error); 130f4a3eb02SAdrian Chadd } 131f4a3eb02SAdrian Chadd 132f4a3eb02SAdrian Chadd /** 133*56a4cdd1SLandon J. Fuller * Default bhnd_sprom implementation of DEVICE_RESUME(). 134f4a3eb02SAdrian Chadd */ 135f4a3eb02SAdrian Chadd int 136f4a3eb02SAdrian Chadd bhnd_sprom_resume(device_t dev) 137f4a3eb02SAdrian Chadd { 138f4a3eb02SAdrian Chadd return (0); 139f4a3eb02SAdrian Chadd } 140f4a3eb02SAdrian Chadd 141f4a3eb02SAdrian Chadd /** 142*56a4cdd1SLandon J. Fuller * Default bhnd sprom driver implementation of DEVICE_SUSPEND(). 143f4a3eb02SAdrian Chadd */ 144f4a3eb02SAdrian Chadd int 145f4a3eb02SAdrian Chadd bhnd_sprom_suspend(device_t dev) 146f4a3eb02SAdrian Chadd { 147f4a3eb02SAdrian Chadd return (0); 148f4a3eb02SAdrian Chadd } 149f4a3eb02SAdrian Chadd 150f4a3eb02SAdrian Chadd /** 151f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of DEVICE_DETACH(). 152f4a3eb02SAdrian Chadd */ 153f4a3eb02SAdrian Chadd int 154f4a3eb02SAdrian Chadd bhnd_sprom_detach(device_t dev) 155f4a3eb02SAdrian Chadd { 156f4a3eb02SAdrian Chadd struct bhnd_sprom_softc *sc; 157f4a3eb02SAdrian Chadd 158f4a3eb02SAdrian Chadd sc = device_get_softc(dev); 159f4a3eb02SAdrian Chadd 160f4a3eb02SAdrian Chadd bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid, 161f4a3eb02SAdrian Chadd sc->sprom_res); 162f4a3eb02SAdrian Chadd bhnd_sprom_fini(&sc->shadow); 163f4a3eb02SAdrian Chadd SPROM_LOCK_DESTROY(sc); 164e83ce340SAdrian Chadd 165e83ce340SAdrian Chadd return (0); 166e83ce340SAdrian Chadd } 167e83ce340SAdrian Chadd 168e83ce340SAdrian Chadd /** 169f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of BHND_NVRAM_GETVAR(). 170e83ce340SAdrian Chadd */ 171f4a3eb02SAdrian Chadd static int 172f4a3eb02SAdrian Chadd bhnd_sprom_getvar_meth(device_t dev, const char *name, void *buf, size_t *len) 173e83ce340SAdrian Chadd { 174f4a3eb02SAdrian Chadd struct bhnd_sprom_softc *sc; 175e83ce340SAdrian Chadd int error; 176e83ce340SAdrian Chadd 177f4a3eb02SAdrian Chadd sc = device_get_softc(dev); 178f4a3eb02SAdrian Chadd 179f4a3eb02SAdrian Chadd SPROM_LOCK(sc); 180f4a3eb02SAdrian Chadd error = bhnd_sprom_getvar(&sc->shadow, name, buf, len); 181f4a3eb02SAdrian Chadd SPROM_UNLOCK(sc); 182f4a3eb02SAdrian Chadd 183e83ce340SAdrian Chadd return (error); 184e83ce340SAdrian Chadd } 185e83ce340SAdrian Chadd 186e83ce340SAdrian Chadd /** 187f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of BHND_NVRAM_SETVAR(). 188e83ce340SAdrian Chadd */ 189f4a3eb02SAdrian Chadd static int 190f4a3eb02SAdrian Chadd bhnd_sprom_setvar_meth(device_t dev, const char *name, const void *buf, 191e83ce340SAdrian Chadd size_t len) 192e83ce340SAdrian Chadd { 193f4a3eb02SAdrian Chadd struct bhnd_sprom_softc *sc; 194e83ce340SAdrian Chadd int error; 195e83ce340SAdrian Chadd 196f4a3eb02SAdrian Chadd sc = device_get_softc(dev); 197e83ce340SAdrian Chadd 198f4a3eb02SAdrian Chadd SPROM_LOCK(sc); 199f4a3eb02SAdrian Chadd error = bhnd_sprom_setvar(&sc->shadow, name, buf, len); 200f4a3eb02SAdrian Chadd SPROM_UNLOCK(sc); 201e83ce340SAdrian Chadd 202e83ce340SAdrian Chadd return (error); 203e83ce340SAdrian Chadd } 204e83ce340SAdrian Chadd 205f4a3eb02SAdrian Chadd static device_method_t bhnd_sprom_methods[] = { 206f4a3eb02SAdrian Chadd /* Device interface */ 207f4a3eb02SAdrian Chadd DEVMETHOD(device_probe, bhnd_sprom_probe), 208*56a4cdd1SLandon J. Fuller DEVMETHOD(device_attach, bhnd_sprom_attach_meth), 209f4a3eb02SAdrian Chadd DEVMETHOD(device_resume, bhnd_sprom_resume), 210f4a3eb02SAdrian Chadd DEVMETHOD(device_suspend, bhnd_sprom_suspend), 211f4a3eb02SAdrian Chadd DEVMETHOD(device_detach, bhnd_sprom_detach), 212e83ce340SAdrian Chadd 213f4a3eb02SAdrian Chadd /* NVRAM interface */ 214f4a3eb02SAdrian Chadd DEVMETHOD(bhnd_nvram_getvar, bhnd_sprom_getvar_meth), 215f4a3eb02SAdrian Chadd DEVMETHOD(bhnd_nvram_setvar, bhnd_sprom_setvar_meth), 216e83ce340SAdrian Chadd 217f4a3eb02SAdrian Chadd DEVMETHOD_END 218f4a3eb02SAdrian Chadd }; 219e83ce340SAdrian Chadd 220f4a3eb02SAdrian Chadd DEFINE_CLASS_0(bhnd_nvram, bhnd_sprom_driver, bhnd_sprom_methods, sizeof(struct bhnd_sprom_softc)); 221f4a3eb02SAdrian Chadd MODULE_VERSION(bhnd_sprom, 1); 222