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, "Broadcom SPROM/OTP"); 75 76 /* Refuse wildcard attachments */ 77 return (BUS_PROBE_NOWILDCARD); 78 } 79 80 /** 81 * Default bhnd sprom driver implementation of DEVICE_ATTACH(). 82 * 83 * Assumes sprom is mapped via YS_RES_MEMORY resource with RID 0. 84 */ 85 int 86 bhnd_sprom_attach(device_t dev) 87 { 88 struct bhnd_sprom_softc *sc; 89 int error; 90 91 sc = device_get_softc(dev); 92 sc->dev = dev; 93 94 /* Allocate SPROM resource */ 95 sc->sprom_rid = 0; 96 sc->sprom_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, 97 &sc->sprom_rid, RF_ACTIVE); 98 if (sc->sprom_res == NULL) { 99 device_printf(dev, "failed to allocate resources\n"); 100 return (ENXIO); 101 } 102 103 /* Initialize SPROM shadow */ 104 if ((error = bhnd_sprom_init(&sc->shadow, sc->sprom_res, 0))) { 105 device_printf(dev, "unrecognized SPROM format\n"); 106 goto failed; 107 } 108 109 /* Initialize mutex */ 110 SPROM_LOCK_INIT(sc); 111 112 return (0); 113 114 failed: 115 bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid, 116 sc->sprom_res); 117 return (error); 118 } 119 120 /** 121 * Default bhnd sprom driver implementation of DEVICE_DETACH(). 122 */ 123 int 124 bhnd_sprom_resume(device_t dev) 125 { 126 return (0); 127 } 128 129 /** 130 * Default bhnd sprom driver implementation of DEVICE_DETACH(). 131 */ 132 int 133 bhnd_sprom_suspend(device_t dev) 134 { 135 return (0); 136 } 137 138 /** 139 * Default bhnd sprom driver implementation of DEVICE_DETACH(). 140 */ 141 int 142 bhnd_sprom_detach(device_t dev) 143 { 144 struct bhnd_sprom_softc *sc; 145 146 sc = device_get_softc(dev); 147 148 bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid, 149 sc->sprom_res); 150 bhnd_sprom_fini(&sc->shadow); 151 SPROM_LOCK_DESTROY(sc); 152 153 return (0); 154 } 155 156 /** 157 * Default bhnd sprom driver implementation of BHND_NVRAM_GETVAR(). 158 */ 159 static int 160 bhnd_sprom_getvar_meth(device_t dev, const char *name, void *buf, size_t *len) 161 { 162 struct bhnd_sprom_softc *sc; 163 int error; 164 165 sc = device_get_softc(dev); 166 167 SPROM_LOCK(sc); 168 error = bhnd_sprom_getvar(&sc->shadow, name, buf, len); 169 SPROM_UNLOCK(sc); 170 171 return (error); 172 } 173 174 /** 175 * Default bhnd sprom driver implementation of BHND_NVRAM_SETVAR(). 176 */ 177 static int 178 bhnd_sprom_setvar_meth(device_t dev, const char *name, const void *buf, 179 size_t len) 180 { 181 struct bhnd_sprom_softc *sc; 182 int error; 183 184 sc = device_get_softc(dev); 185 186 SPROM_LOCK(sc); 187 error = bhnd_sprom_setvar(&sc->shadow, name, buf, len); 188 SPROM_UNLOCK(sc); 189 190 return (error); 191 } 192 193 static device_method_t bhnd_sprom_methods[] = { 194 /* Device interface */ 195 DEVMETHOD(device_probe, bhnd_sprom_probe), 196 DEVMETHOD(device_attach, bhnd_sprom_attach), 197 DEVMETHOD(device_resume, bhnd_sprom_resume), 198 DEVMETHOD(device_suspend, bhnd_sprom_suspend), 199 DEVMETHOD(device_detach, bhnd_sprom_detach), 200 201 /* NVRAM interface */ 202 DEVMETHOD(bhnd_nvram_getvar, bhnd_sprom_getvar_meth), 203 DEVMETHOD(bhnd_nvram_setvar, bhnd_sprom_setvar_meth), 204 205 DEVMETHOD_END 206 }; 207 208 DEFINE_CLASS_0(bhnd_nvram, bhnd_sprom_driver, bhnd_sprom_methods, sizeof(struct bhnd_sprom_softc)); 209 MODULE_VERSION(bhnd_sprom, 1); 210