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