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