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); 7456a4cdd1SLandon 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 8056a4cdd1SLandon J. Fuller /* Default DEVICE_ATTACH() implementation; assumes a zero offset to the 8156a4cdd1SLandon J. Fuller * SPROM data */ 8256a4cdd1SLandon J. Fuller static int 8356a4cdd1SLandon J. Fuller bhnd_sprom_attach_meth(device_t dev) 8456a4cdd1SLandon J. Fuller { 8556a4cdd1SLandon J. Fuller return (bhnd_sprom_attach(dev, 0)); 8656a4cdd1SLandon J. Fuller } 8756a4cdd1SLandon J. Fuller 88f4a3eb02SAdrian Chadd /** 8956a4cdd1SLandon J. Fuller * BHND SPROM device attach. 90f4a3eb02SAdrian Chadd * 9156a4cdd1SLandon J. Fuller * This should be called from DEVICE_ATTACH() with the @p offset to the 9256a4cdd1SLandon J. Fuller * SPROM data. 9356a4cdd1SLandon J. Fuller * 9456a4cdd1SLandon J. Fuller * Assumes SPROM is mapped via SYS_RES_MEMORY resource with RID 0. 9556a4cdd1SLandon J. Fuller * 9656a4cdd1SLandon J. Fuller * @param dev BHND SPROM device. 9756a4cdd1SLandon J. Fuller * @param offset Offset to the SPROM data. 98f4a3eb02SAdrian Chadd */ 99f4a3eb02SAdrian Chadd int 10056a4cdd1SLandon 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 */ 11856a4cdd1SLandon 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 /** 13356a4cdd1SLandon 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 /** 14256a4cdd1SLandon 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 172*1728aef2SLandon J. Fuller bhnd_sprom_getvar_method(device_t dev, const char *name, void *buf, size_t *len, 173*1728aef2SLandon J. Fuller bhnd_nvram_type type) 174e83ce340SAdrian Chadd { 175f4a3eb02SAdrian Chadd struct bhnd_sprom_softc *sc; 176e83ce340SAdrian Chadd int error; 177e83ce340SAdrian Chadd 178f4a3eb02SAdrian Chadd sc = device_get_softc(dev); 179f4a3eb02SAdrian Chadd 180f4a3eb02SAdrian Chadd SPROM_LOCK(sc); 181*1728aef2SLandon J. Fuller error = bhnd_sprom_getvar(&sc->shadow, name, buf, len, type); 182f4a3eb02SAdrian Chadd SPROM_UNLOCK(sc); 183f4a3eb02SAdrian Chadd 184e83ce340SAdrian Chadd return (error); 185e83ce340SAdrian Chadd } 186e83ce340SAdrian Chadd 187e83ce340SAdrian Chadd /** 188f4a3eb02SAdrian Chadd * Default bhnd sprom driver implementation of BHND_NVRAM_SETVAR(). 189e83ce340SAdrian Chadd */ 190f4a3eb02SAdrian Chadd static int 191*1728aef2SLandon J. Fuller bhnd_sprom_setvar_method(device_t dev, const char *name, const void *buf, 192*1728aef2SLandon J. Fuller size_t len, bhnd_nvram_type type) 193e83ce340SAdrian Chadd { 194f4a3eb02SAdrian Chadd struct bhnd_sprom_softc *sc; 195e83ce340SAdrian Chadd int error; 196e83ce340SAdrian Chadd 197f4a3eb02SAdrian Chadd sc = device_get_softc(dev); 198e83ce340SAdrian Chadd 199f4a3eb02SAdrian Chadd SPROM_LOCK(sc); 200*1728aef2SLandon J. Fuller error = bhnd_sprom_setvar(&sc->shadow, name, buf, len, type); 201f4a3eb02SAdrian Chadd SPROM_UNLOCK(sc); 202e83ce340SAdrian Chadd 203e83ce340SAdrian Chadd return (error); 204e83ce340SAdrian Chadd } 205e83ce340SAdrian Chadd 206f4a3eb02SAdrian Chadd static device_method_t bhnd_sprom_methods[] = { 207f4a3eb02SAdrian Chadd /* Device interface */ 208f4a3eb02SAdrian Chadd DEVMETHOD(device_probe, bhnd_sprom_probe), 20956a4cdd1SLandon J. Fuller DEVMETHOD(device_attach, bhnd_sprom_attach_meth), 210f4a3eb02SAdrian Chadd DEVMETHOD(device_resume, bhnd_sprom_resume), 211f4a3eb02SAdrian Chadd DEVMETHOD(device_suspend, bhnd_sprom_suspend), 212f4a3eb02SAdrian Chadd DEVMETHOD(device_detach, bhnd_sprom_detach), 213e83ce340SAdrian Chadd 214f4a3eb02SAdrian Chadd /* NVRAM interface */ 215*1728aef2SLandon J. Fuller DEVMETHOD(bhnd_nvram_getvar, bhnd_sprom_getvar_method), 216*1728aef2SLandon J. Fuller DEVMETHOD(bhnd_nvram_setvar, bhnd_sprom_setvar_method), 217e83ce340SAdrian Chadd 218f4a3eb02SAdrian Chadd DEVMETHOD_END 219f4a3eb02SAdrian Chadd }; 220e83ce340SAdrian Chadd 221f4a3eb02SAdrian Chadd DEFINE_CLASS_0(bhnd_nvram, bhnd_sprom_driver, bhnd_sprom_methods, sizeof(struct bhnd_sprom_softc)); 222f4a3eb02SAdrian Chadd MODULE_VERSION(bhnd_sprom, 1); 223