xref: /freebsd/sys/dev/bhnd/nvram/bhnd_sprom.c (revision 1728aef23dac2541a3a7de00393ea3ea39b968d7)
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