xref: /freebsd/sys/dev/bhnd/nvram/bhnd_sprom.c (revision 77cb4d3e5016a2fd090d07ed3e01a199723641d9)
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 
55*77cb4d3eSLandon J. Fuller #include "bhnd_nvram_io.h"
56e83ce340SAdrian Chadd 
57*77cb4d3eSLandon J. Fuller #include "bhnd_spromvar.h"
58e83ce340SAdrian Chadd 
59e83ce340SAdrian Chadd /**
60f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of DEVICE_PROBE().
61e83ce340SAdrian Chadd  */
62e83ce340SAdrian Chadd int
63f4a3eb02SAdrian Chadd bhnd_sprom_probe(device_t dev)
64e83ce340SAdrian Chadd {
6556a4cdd1SLandon J. Fuller 	device_set_desc(dev, "SPROM/OTP");
66f4a3eb02SAdrian Chadd 
67f4a3eb02SAdrian Chadd 	/* Refuse wildcard attachments */
68f4a3eb02SAdrian Chadd 	return (BUS_PROBE_NOWILDCARD);
69f4a3eb02SAdrian Chadd }
70f4a3eb02SAdrian Chadd 
7156a4cdd1SLandon J. Fuller /* Default DEVICE_ATTACH() implementation; assumes a zero offset to the
7256a4cdd1SLandon J. Fuller  * SPROM data */
7356a4cdd1SLandon J. Fuller static int
7456a4cdd1SLandon J. Fuller bhnd_sprom_attach_meth(device_t dev)
7556a4cdd1SLandon J. Fuller {
7656a4cdd1SLandon J. Fuller 	return (bhnd_sprom_attach(dev, 0));
7756a4cdd1SLandon J. Fuller }
7856a4cdd1SLandon J. Fuller 
79f4a3eb02SAdrian Chadd /**
8056a4cdd1SLandon J. Fuller  * BHND SPROM device attach.
81f4a3eb02SAdrian Chadd  *
8256a4cdd1SLandon J. Fuller  * This should be called from DEVICE_ATTACH() with the @p offset to the
8356a4cdd1SLandon J. Fuller  * SPROM data.
8456a4cdd1SLandon J. Fuller  *
8556a4cdd1SLandon J. Fuller  * Assumes SPROM is mapped via SYS_RES_MEMORY resource with RID 0.
8656a4cdd1SLandon J. Fuller  *
8756a4cdd1SLandon J. Fuller  * @param dev BHND SPROM device.
8856a4cdd1SLandon J. Fuller  * @param offset Offset to the SPROM data.
89f4a3eb02SAdrian Chadd  */
90f4a3eb02SAdrian Chadd int
9156a4cdd1SLandon J. Fuller bhnd_sprom_attach(device_t dev, bus_size_t offset)
92f4a3eb02SAdrian Chadd {
93f4a3eb02SAdrian Chadd 	struct bhnd_sprom_softc	*sc;
94*77cb4d3eSLandon J. Fuller 	struct bhnd_nvram_io	*io;
95*77cb4d3eSLandon J. Fuller 	struct bhnd_resource	*r;
96*77cb4d3eSLandon J. Fuller 	bus_size_t		 r_size, sprom_size;
97*77cb4d3eSLandon J. Fuller 	int			 rid;
98e83ce340SAdrian Chadd 	int			 error;
99e83ce340SAdrian Chadd 
100f4a3eb02SAdrian Chadd 	sc = device_get_softc(dev);
101f4a3eb02SAdrian Chadd 	sc->dev = dev;
102e83ce340SAdrian Chadd 
103*77cb4d3eSLandon J. Fuller 	io = NULL;
104*77cb4d3eSLandon J. Fuller 
105f4a3eb02SAdrian Chadd 	/* Allocate SPROM resource */
106*77cb4d3eSLandon J. Fuller 	rid = 0;
107*77cb4d3eSLandon J. Fuller 	r = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
108*77cb4d3eSLandon J. Fuller 	if (r == NULL) {
109f4a3eb02SAdrian Chadd 		device_printf(dev, "failed to allocate resources\n");
110f4a3eb02SAdrian Chadd 		return (ENXIO);
111f4a3eb02SAdrian Chadd 	}
112e83ce340SAdrian Chadd 
113*77cb4d3eSLandon J. Fuller 	/* Determine SPROM size */
114*77cb4d3eSLandon J. Fuller 	r_size = rman_get_size(r->res);
115*77cb4d3eSLandon J. Fuller 	if (r_size <= offset || (r_size - offset) > BUS_SPACE_MAXSIZE) {
116*77cb4d3eSLandon J. Fuller 		device_printf(dev, "invalid sprom offset\n");
117*77cb4d3eSLandon J. Fuller 		error = ENXIO;
118*77cb4d3eSLandon J. Fuller 		goto failed;
119*77cb4d3eSLandon J. Fuller 	}
120*77cb4d3eSLandon J. Fuller 
121*77cb4d3eSLandon J. Fuller 	sprom_size = r_size - offset;
122*77cb4d3eSLandon J. Fuller 
123*77cb4d3eSLandon J. Fuller 	/* Allocate an I/O context for the SPROM parser. All SPROM reads
124*77cb4d3eSLandon J. Fuller 	 * must be 16-bit aligned */
125*77cb4d3eSLandon J. Fuller 	io = bhnd_nvram_iores_new(r, offset, sprom_size, sizeof(uint16_t));
126*77cb4d3eSLandon J. Fuller 	if (io == NULL) {
127*77cb4d3eSLandon J. Fuller 		error = ENXIO;
128*77cb4d3eSLandon J. Fuller 		goto failed;
129*77cb4d3eSLandon J. Fuller 	}
130*77cb4d3eSLandon J. Fuller 
131*77cb4d3eSLandon J. Fuller 	/* Initialize NVRAM data store */
132*77cb4d3eSLandon J. Fuller 	error = bhnd_nvram_store_parse_new(&sc->store, io,
133*77cb4d3eSLandon J. Fuller 	    &bhnd_nvram_sprom_class);
134*77cb4d3eSLandon J. Fuller 	if (error)
135f4a3eb02SAdrian Chadd 		goto failed;
136e83ce340SAdrian Chadd 
137*77cb4d3eSLandon J. Fuller 	/* Clean up our temporary I/O context and its backing resource */
138*77cb4d3eSLandon J. Fuller 	bhnd_nvram_io_free(io);
139*77cb4d3eSLandon J. Fuller 	bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r);
140e83ce340SAdrian Chadd 
141f4a3eb02SAdrian Chadd 	return (0);
142f4a3eb02SAdrian Chadd 
143f4a3eb02SAdrian Chadd failed:
144*77cb4d3eSLandon J. Fuller 	/* Clean up I/O context before releasing its backing resource */
145*77cb4d3eSLandon J. Fuller 	if (io != NULL)
146*77cb4d3eSLandon J. Fuller 		bhnd_nvram_io_free(io);
147*77cb4d3eSLandon J. Fuller 
148*77cb4d3eSLandon J. Fuller 	bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r);
149*77cb4d3eSLandon J. Fuller 
150e83ce340SAdrian Chadd 	return (error);
151f4a3eb02SAdrian Chadd }
152f4a3eb02SAdrian Chadd 
153f4a3eb02SAdrian Chadd /**
15456a4cdd1SLandon J. Fuller  * Default bhnd_sprom implementation of DEVICE_RESUME().
155f4a3eb02SAdrian Chadd  */
156f4a3eb02SAdrian Chadd int
157f4a3eb02SAdrian Chadd bhnd_sprom_resume(device_t dev)
158f4a3eb02SAdrian Chadd {
159f4a3eb02SAdrian Chadd 	return (0);
160f4a3eb02SAdrian Chadd }
161f4a3eb02SAdrian Chadd 
162f4a3eb02SAdrian Chadd /**
16356a4cdd1SLandon J. Fuller  * Default bhnd sprom driver implementation of DEVICE_SUSPEND().
164f4a3eb02SAdrian Chadd  */
165f4a3eb02SAdrian Chadd int
166f4a3eb02SAdrian Chadd bhnd_sprom_suspend(device_t dev)
167f4a3eb02SAdrian Chadd {
168f4a3eb02SAdrian Chadd 	return (0);
169f4a3eb02SAdrian Chadd }
170f4a3eb02SAdrian Chadd 
171f4a3eb02SAdrian Chadd /**
172f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of DEVICE_DETACH().
173f4a3eb02SAdrian Chadd  */
174f4a3eb02SAdrian Chadd int
175f4a3eb02SAdrian Chadd bhnd_sprom_detach(device_t dev)
176f4a3eb02SAdrian Chadd {
177f4a3eb02SAdrian Chadd 	struct bhnd_sprom_softc	*sc;
178f4a3eb02SAdrian Chadd 
179f4a3eb02SAdrian Chadd 	sc = device_get_softc(dev);
180f4a3eb02SAdrian Chadd 
181*77cb4d3eSLandon J. Fuller 	bhnd_nvram_store_free(sc->store);
182e83ce340SAdrian Chadd 
183e83ce340SAdrian Chadd 	return (0);
184e83ce340SAdrian Chadd }
185e83ce340SAdrian Chadd 
186e83ce340SAdrian Chadd /**
187f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of BHND_NVRAM_GETVAR().
188e83ce340SAdrian Chadd  */
189f4a3eb02SAdrian Chadd static int
1901728aef2SLandon J. Fuller bhnd_sprom_getvar_method(device_t dev, const char *name, void *buf, size_t *len,
1911728aef2SLandon J. Fuller     bhnd_nvram_type type)
192e83ce340SAdrian Chadd {
193*77cb4d3eSLandon J. Fuller 	struct bhnd_sprom_softc	*sc = device_get_softc(dev);
194e83ce340SAdrian Chadd 
195*77cb4d3eSLandon J. Fuller 	return (bhnd_nvram_store_getvar(sc->store, name, buf, len, type));
196e83ce340SAdrian Chadd }
197e83ce340SAdrian Chadd 
198e83ce340SAdrian Chadd /**
199f4a3eb02SAdrian Chadd  * Default bhnd sprom driver implementation of BHND_NVRAM_SETVAR().
200e83ce340SAdrian Chadd  */
201f4a3eb02SAdrian Chadd static int
2021728aef2SLandon J. Fuller bhnd_sprom_setvar_method(device_t dev, const char *name, const void *buf,
2031728aef2SLandon J. Fuller     size_t len, bhnd_nvram_type type)
204e83ce340SAdrian Chadd {
205*77cb4d3eSLandon J. Fuller 	struct bhnd_sprom_softc	*sc = device_get_softc(dev);
206e83ce340SAdrian Chadd 
207*77cb4d3eSLandon J. Fuller 	return (bhnd_nvram_store_setvar(sc->store, name, buf, len, type));
208e83ce340SAdrian Chadd }
209e83ce340SAdrian Chadd 
210f4a3eb02SAdrian Chadd static device_method_t bhnd_sprom_methods[] = {
211f4a3eb02SAdrian Chadd 	/* Device interface */
212f4a3eb02SAdrian Chadd 	DEVMETHOD(device_probe,			bhnd_sprom_probe),
21356a4cdd1SLandon J. Fuller 	DEVMETHOD(device_attach,		bhnd_sprom_attach_meth),
214f4a3eb02SAdrian Chadd 	DEVMETHOD(device_resume,		bhnd_sprom_resume),
215f4a3eb02SAdrian Chadd 	DEVMETHOD(device_suspend,		bhnd_sprom_suspend),
216f4a3eb02SAdrian Chadd 	DEVMETHOD(device_detach,		bhnd_sprom_detach),
217e83ce340SAdrian Chadd 
218f4a3eb02SAdrian Chadd 	/* NVRAM interface */
2191728aef2SLandon J. Fuller 	DEVMETHOD(bhnd_nvram_getvar,		bhnd_sprom_getvar_method),
2201728aef2SLandon J. Fuller 	DEVMETHOD(bhnd_nvram_setvar,		bhnd_sprom_setvar_method),
221e83ce340SAdrian Chadd 
222f4a3eb02SAdrian Chadd 	DEVMETHOD_END
223f4a3eb02SAdrian Chadd };
224e83ce340SAdrian Chadd 
225*77cb4d3eSLandon J. Fuller DEFINE_CLASS_0(bhnd_nvram_store, bhnd_sprom_driver, bhnd_sprom_methods, sizeof(struct bhnd_sprom_softc));
226f4a3eb02SAdrian Chadd MODULE_VERSION(bhnd_sprom, 1);
227