xref: /freebsd/sys/dev/bhnd/nvram/bhnd_sprom.c (revision f4a3eb02973afb7e2c2d1a116dbcb331f91ae022)
1e83ce340SAdrian Chadd /*-
2*f4a3eb02SAdrian 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 
33*f4a3eb02SAdrian Chadd /*
34*f4a3eb02SAdrian Chadd  * BHND SPROM driver.
35*f4a3eb02SAdrian Chadd  *
36*f4a3eb02SAdrian Chadd  * Abstract driver for memory-mapped SPROM devices.
37*f4a3eb02SAdrian Chadd  */
38*f4a3eb02SAdrian Chadd 
39e83ce340SAdrian Chadd #include <sys/param.h>
40*f4a3eb02SAdrian Chadd #include <sys/kernel.h>
41e83ce340SAdrian Chadd #include <sys/bus.h>
42*f4a3eb02SAdrian Chadd #include <sys/limits.h>
43*f4a3eb02SAdrian Chadd #include <sys/malloc.h>
44*f4a3eb02SAdrian Chadd #include <sys/module.h>
45e83ce340SAdrian Chadd #include <sys/systm.h>
46e83ce340SAdrian Chadd 
47e83ce340SAdrian Chadd #include <machine/bus.h>
48*f4a3eb02SAdrian Chadd #include <sys/rman.h>
49e83ce340SAdrian Chadd #include <machine/resource.h>
50e83ce340SAdrian Chadd 
51*f4a3eb02SAdrian Chadd #include <dev/bhnd/bhnd.h>
52e83ce340SAdrian Chadd 
53*f4a3eb02SAdrian Chadd #include "bhnd_nvram_if.h"
54e83ce340SAdrian Chadd 
55e83ce340SAdrian Chadd #include "bhnd_spromvar.h"
56e83ce340SAdrian Chadd 
57*f4a3eb02SAdrian Chadd #define	SPROM_LOCK_INIT(sc) \
58*f4a3eb02SAdrian Chadd 	mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
59*f4a3eb02SAdrian Chadd 	    "BHND SPROM lock", MTX_DEF)
60*f4a3eb02SAdrian Chadd #define	SPROM_LOCK(sc)			mtx_lock(&(sc)->mtx)
61*f4a3eb02SAdrian Chadd #define	SPROM_UNLOCK(sc)			mtx_unlock(&(sc)->mtx)
62*f4a3eb02SAdrian Chadd #define	SPROM_LOCK_ASSERT(sc, what)	mtx_assert(&(sc)->mtx, what)
63*f4a3eb02SAdrian Chadd #define	SPROM_LOCK_DESTROY(sc)		mtx_destroy(&(sc)->mtx)
64e83ce340SAdrian Chadd 
65e83ce340SAdrian Chadd /**
66*f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of DEVICE_PROBE().
67e83ce340SAdrian Chadd  */
68e83ce340SAdrian Chadd int
69*f4a3eb02SAdrian Chadd bhnd_sprom_probe(device_t dev)
70e83ce340SAdrian Chadd {
71*f4a3eb02SAdrian Chadd 	/* Quiet by default */
72*f4a3eb02SAdrian Chadd 	if (!bootverbose)
73*f4a3eb02SAdrian Chadd 		device_quiet(dev);
74*f4a3eb02SAdrian Chadd 	device_set_desc(dev, "Broadcom SPROM/OTP");
75*f4a3eb02SAdrian Chadd 
76*f4a3eb02SAdrian Chadd 	/* Refuse wildcard attachments */
77*f4a3eb02SAdrian Chadd 	return (BUS_PROBE_NOWILDCARD);
78*f4a3eb02SAdrian Chadd }
79*f4a3eb02SAdrian Chadd 
80*f4a3eb02SAdrian Chadd /**
81*f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of DEVICE_ATTACH().
82*f4a3eb02SAdrian Chadd  *
83*f4a3eb02SAdrian Chadd  * Assumes sprom is mapped via YS_RES_MEMORY resource with RID 0.
84*f4a3eb02SAdrian Chadd  */
85*f4a3eb02SAdrian Chadd int
86*f4a3eb02SAdrian Chadd bhnd_sprom_attach(device_t dev)
87*f4a3eb02SAdrian Chadd {
88*f4a3eb02SAdrian Chadd 	struct bhnd_sprom_softc	*sc;
89e83ce340SAdrian Chadd 	int				 error;
90e83ce340SAdrian Chadd 
91*f4a3eb02SAdrian Chadd 	sc = device_get_softc(dev);
92*f4a3eb02SAdrian Chadd 	sc->dev = dev;
93e83ce340SAdrian Chadd 
94*f4a3eb02SAdrian Chadd 	/* Allocate SPROM resource */
95*f4a3eb02SAdrian Chadd 	sc->sprom_rid = 0;
96*f4a3eb02SAdrian Chadd 	sc->sprom_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY,
97*f4a3eb02SAdrian Chadd 	    &sc->sprom_rid, RF_ACTIVE);
98*f4a3eb02SAdrian Chadd 	if (sc->sprom_res == NULL) {
99*f4a3eb02SAdrian Chadd 		device_printf(dev, "failed to allocate resources\n");
100*f4a3eb02SAdrian Chadd 		return (ENXIO);
101*f4a3eb02SAdrian Chadd 	}
102e83ce340SAdrian Chadd 
103*f4a3eb02SAdrian Chadd 	/* Initialize SPROM shadow */
104*f4a3eb02SAdrian Chadd 	if ((error = bhnd_sprom_init(&sc->shadow, sc->sprom_res, 0))) {
105*f4a3eb02SAdrian Chadd 		device_printf(dev, "unrecognized SPROM format\n");
106*f4a3eb02SAdrian Chadd 		goto failed;
107*f4a3eb02SAdrian Chadd 	}
108e83ce340SAdrian Chadd 
109*f4a3eb02SAdrian Chadd 	/* Initialize mutex */
110*f4a3eb02SAdrian Chadd 	SPROM_LOCK_INIT(sc);
111e83ce340SAdrian Chadd 
112*f4a3eb02SAdrian Chadd 	return (0);
113*f4a3eb02SAdrian Chadd 
114*f4a3eb02SAdrian Chadd failed:
115*f4a3eb02SAdrian Chadd 	bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid,
116*f4a3eb02SAdrian Chadd 	    sc->sprom_res);
117e83ce340SAdrian Chadd 	return (error);
118*f4a3eb02SAdrian Chadd }
119*f4a3eb02SAdrian Chadd 
120*f4a3eb02SAdrian Chadd /**
121*f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of DEVICE_DETACH().
122*f4a3eb02SAdrian Chadd  */
123*f4a3eb02SAdrian Chadd int
124*f4a3eb02SAdrian Chadd bhnd_sprom_resume(device_t dev)
125*f4a3eb02SAdrian Chadd {
126*f4a3eb02SAdrian Chadd 	return (0);
127*f4a3eb02SAdrian Chadd }
128*f4a3eb02SAdrian Chadd 
129*f4a3eb02SAdrian Chadd /**
130*f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of DEVICE_DETACH().
131*f4a3eb02SAdrian Chadd  */
132*f4a3eb02SAdrian Chadd int
133*f4a3eb02SAdrian Chadd bhnd_sprom_suspend(device_t dev)
134*f4a3eb02SAdrian Chadd {
135*f4a3eb02SAdrian Chadd 	return (0);
136*f4a3eb02SAdrian Chadd }
137*f4a3eb02SAdrian Chadd 
138*f4a3eb02SAdrian Chadd /**
139*f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of DEVICE_DETACH().
140*f4a3eb02SAdrian Chadd  */
141*f4a3eb02SAdrian Chadd int
142*f4a3eb02SAdrian Chadd bhnd_sprom_detach(device_t dev)
143*f4a3eb02SAdrian Chadd {
144*f4a3eb02SAdrian Chadd 	struct bhnd_sprom_softc	*sc;
145*f4a3eb02SAdrian Chadd 
146*f4a3eb02SAdrian Chadd 	sc = device_get_softc(dev);
147*f4a3eb02SAdrian Chadd 
148*f4a3eb02SAdrian Chadd 	bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid,
149*f4a3eb02SAdrian Chadd 	    sc->sprom_res);
150*f4a3eb02SAdrian Chadd 	bhnd_sprom_fini(&sc->shadow);
151*f4a3eb02SAdrian Chadd 	SPROM_LOCK_DESTROY(sc);
152e83ce340SAdrian Chadd 
153e83ce340SAdrian Chadd 	return (0);
154e83ce340SAdrian Chadd }
155e83ce340SAdrian Chadd 
156e83ce340SAdrian Chadd /**
157*f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of BHND_NVRAM_GETVAR().
158e83ce340SAdrian Chadd  */
159*f4a3eb02SAdrian Chadd static int
160*f4a3eb02SAdrian Chadd bhnd_sprom_getvar_meth(device_t dev, const char *name, void *buf, size_t *len)
161e83ce340SAdrian Chadd {
162*f4a3eb02SAdrian Chadd 	struct bhnd_sprom_softc	*sc;
163e83ce340SAdrian Chadd 	int				 error;
164e83ce340SAdrian Chadd 
165*f4a3eb02SAdrian Chadd 	sc = device_get_softc(dev);
166*f4a3eb02SAdrian Chadd 
167*f4a3eb02SAdrian Chadd 	SPROM_LOCK(sc);
168*f4a3eb02SAdrian Chadd 	error = bhnd_sprom_getvar(&sc->shadow, name, buf, len);
169*f4a3eb02SAdrian Chadd 	SPROM_UNLOCK(sc);
170*f4a3eb02SAdrian Chadd 
171e83ce340SAdrian Chadd 	return (error);
172e83ce340SAdrian Chadd }
173e83ce340SAdrian Chadd 
174e83ce340SAdrian Chadd /**
175*f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of BHND_NVRAM_SETVAR().
176e83ce340SAdrian Chadd  */
177*f4a3eb02SAdrian Chadd static int
178*f4a3eb02SAdrian Chadd bhnd_sprom_setvar_meth(device_t dev, const char *name, const void *buf,
179e83ce340SAdrian Chadd     size_t len)
180e83ce340SAdrian Chadd {
181*f4a3eb02SAdrian Chadd 	struct bhnd_sprom_softc	*sc;
182e83ce340SAdrian Chadd 	int				 error;
183e83ce340SAdrian Chadd 
184*f4a3eb02SAdrian Chadd 	sc = device_get_softc(dev);
185e83ce340SAdrian Chadd 
186*f4a3eb02SAdrian Chadd 	SPROM_LOCK(sc);
187*f4a3eb02SAdrian Chadd 	error = bhnd_sprom_setvar(&sc->shadow, name, buf, len);
188*f4a3eb02SAdrian Chadd 	SPROM_UNLOCK(sc);
189e83ce340SAdrian Chadd 
190e83ce340SAdrian Chadd 	return (error);
191e83ce340SAdrian Chadd }
192e83ce340SAdrian Chadd 
193*f4a3eb02SAdrian Chadd static device_method_t bhnd_sprom_methods[] = {
194*f4a3eb02SAdrian Chadd 	/* Device interface */
195*f4a3eb02SAdrian Chadd 	DEVMETHOD(device_probe,			bhnd_sprom_probe),
196*f4a3eb02SAdrian Chadd 	DEVMETHOD(device_attach,		bhnd_sprom_attach),
197*f4a3eb02SAdrian Chadd 	DEVMETHOD(device_resume,		bhnd_sprom_resume),
198*f4a3eb02SAdrian Chadd 	DEVMETHOD(device_suspend,		bhnd_sprom_suspend),
199*f4a3eb02SAdrian Chadd 	DEVMETHOD(device_detach,		bhnd_sprom_detach),
200e83ce340SAdrian Chadd 
201*f4a3eb02SAdrian Chadd 	/* NVRAM interface */
202*f4a3eb02SAdrian Chadd 	DEVMETHOD(bhnd_nvram_getvar,		bhnd_sprom_getvar_meth),
203*f4a3eb02SAdrian Chadd 	DEVMETHOD(bhnd_nvram_setvar,		bhnd_sprom_setvar_meth),
204e83ce340SAdrian Chadd 
205*f4a3eb02SAdrian Chadd 	DEVMETHOD_END
206*f4a3eb02SAdrian Chadd };
207e83ce340SAdrian Chadd 
208*f4a3eb02SAdrian Chadd DEFINE_CLASS_0(bhnd_nvram, bhnd_sprom_driver, bhnd_sprom_methods, sizeof(struct bhnd_sprom_softc));
209*f4a3eb02SAdrian Chadd MODULE_VERSION(bhnd_sprom, 1);
210