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