2 * Copyright (c) 2009, Nathan Whitehorn <nwhitehorn@FreeBSD.org>
3 * Copyright (c) 2013, Luiz Otavio O Souza <loos@FreeBSD.org>
4 * Copyright (c) 2013 The FreeBSD Foundation
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice unmodified, this list of conditions, and the following
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
35 #include <sys/kernel.h>
36 #include <sys/libkern.h>
38 #include <sys/module.h>
39 #include <sys/mutex.h>
41 #include <dev/gpio/gpiobusvar.h>
42 #include <dev/ofw/ofw_bus.h>
43 #include <dev/ofw/openfirm.h>
45 #include <machine/resource.h>
48 #include "gpiobus_if.h"
50 struct ofw_gpiobus_devinfo {
51 struct gpiobus_ivar opd_dinfo;
52 struct ofw_bus_devinfo opd_obdinfo;
55 static int ofw_gpiobus_parse_gpios(struct gpiobus_softc *,
56 struct gpiobus_ivar *, phandle_t);
57 static struct ofw_gpiobus_devinfo *ofw_gpiobus_setup_devinfo(device_t,
59 static void ofw_gpiobus_destroy_devinfo(struct ofw_gpiobus_devinfo *);
62 ofw_gpiobus_add_fdt_child(device_t bus, phandle_t child)
64 struct ofw_gpiobus_devinfo *dinfo;
68 * Set up the GPIO child and OFW bus layer devinfo and add it to bus.
70 dinfo = ofw_gpiobus_setup_devinfo(bus, child);
73 childdev = device_add_child(bus, NULL, -1);
74 if (childdev == NULL) {
75 device_printf(bus, "could not add child: %s\n",
76 dinfo->opd_obdinfo.obd_name);
77 ofw_gpiobus_destroy_devinfo(dinfo);
80 device_set_ivars(childdev, dinfo);
86 ofw_gpiobus_parse_gpios(struct gpiobus_softc *sc, struct gpiobus_ivar *dinfo,
93 /* Retrieve the gpios property. */
94 if ((len = OF_getproplen(child, "gpios")) < 0)
96 gpios = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
99 if (OF_getencprop(child, "gpios", gpios, len) < 0) {
100 free(gpios, M_DEVBUF);
105 * Each 'gpios' entry must contain 4 pcells.
106 * The first one is the GPIO controller phandler.
107 * Then the last three are the GPIO pin, the GPIO pin direction and
108 * the GPIO pin flags.
110 if ((len / sizeof(pcell_t)) % 4) {
111 free(gpios, M_DEVBUF);
114 dinfo->npins = len / (sizeof(pcell_t) * 4);
115 dinfo->pins = malloc(sizeof(uint32_t) * dinfo->npins, M_DEVBUF,
117 if (dinfo->pins == NULL) {
118 free(gpios, M_DEVBUF);
122 for (i = 0; i < dinfo->npins; i++) {
124 /* Verify if we're attaching to the correct gpio controller. */
125 gpio = OF_xref_phandle(gpios[i * 4 + 0]);
126 if (!OF_hasprop(gpio, "gpio-controller") ||
127 gpio != ofw_bus_get_node(sc->sc_dev)) {
128 free(dinfo->pins, M_DEVBUF);
129 free(gpios, M_DEVBUF);
133 /* Get the GPIO pin number. */
134 dinfo->pins[i] = gpios[i * 4 + 1];
135 /* gpios[i * 4 + 2] - GPIO pin direction */
136 /* gpios[i * 4 + 3] - GPIO pin flags */
138 if (dinfo->pins[i] > sc->sc_npins) {
139 device_printf(sc->sc_busdev,
140 "invalid pin %d, max: %d\n",
141 dinfo->pins[i], sc->sc_npins - 1);
142 free(dinfo->pins, M_DEVBUF);
143 free(gpios, M_DEVBUF);
148 * Mark pin as mapped and give warning if it's already mapped.
150 if (sc->sc_pins_mapped[dinfo->pins[i]]) {
151 device_printf(sc->sc_busdev,
152 "warning: pin %d is already mapped\n",
154 free(dinfo->pins, M_DEVBUF);
155 free(gpios, M_DEVBUF);
158 sc->sc_pins_mapped[dinfo->pins[i]] = 1;
161 free(gpios, M_DEVBUF);
166 static struct ofw_gpiobus_devinfo *
167 ofw_gpiobus_setup_devinfo(device_t dev, phandle_t node)
169 struct gpiobus_softc *sc;
170 struct ofw_gpiobus_devinfo *dinfo;
172 sc = device_get_softc(dev);
173 dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_NOWAIT | M_ZERO);
176 if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, node) != 0) {
177 free(dinfo, M_DEVBUF);
181 /* Parse the gpios property for the child. */
182 if (ofw_gpiobus_parse_gpios(sc, &dinfo->opd_dinfo, node) != 0) {
183 ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo);
184 free(dinfo, M_DEVBUF);
192 ofw_gpiobus_destroy_devinfo(struct ofw_gpiobus_devinfo *dinfo)
195 ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo);
196 free(dinfo, M_DEVBUF);
200 ofw_gpiobus_probe(device_t dev)
203 if (ofw_bus_get_node(dev) == -1)
205 device_set_desc(dev, "OFW GPIO bus");
211 ofw_gpiobus_attach(device_t dev)
213 struct gpiobus_softc *sc;
216 sc = GPIOBUS_SOFTC(dev);
218 sc->sc_dev = device_get_parent(dev);
220 /* Read the pin max. value */
221 if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0)
224 KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));
227 * Increase to get number of pins.
231 sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF,
234 if (!sc->sc_pins_mapped)
237 /* Init the bus lock. */
238 GPIOBUS_LOCK_INIT(sc);
240 bus_generic_probe(dev);
241 bus_enumerate_hinted_children(dev);
244 * Attach the children represented in the device tree.
246 for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
247 child = OF_peer(child))
248 if (ofw_gpiobus_add_fdt_child(dev, child) == NULL)
251 return (bus_generic_attach(dev));
255 ofw_gpiobus_add_child(device_t dev, u_int order, const char *name, int unit)
258 struct ofw_gpiobus_devinfo *devi;
260 child = device_add_child_ordered(dev, order, name, unit);
263 devi = malloc(sizeof(struct ofw_gpiobus_devinfo), M_DEVBUF,
266 device_delete_child(dev, child);
271 * NULL all the OFW-related parts of the ivars for non-OFW
274 devi->opd_obdinfo.obd_node = -1;
275 devi->opd_obdinfo.obd_name = NULL;
276 devi->opd_obdinfo.obd_compat = NULL;
277 devi->opd_obdinfo.obd_type = NULL;
278 devi->opd_obdinfo.obd_model = NULL;
280 device_set_ivars(child, devi);
286 ofw_gpiobus_print_child(device_t dev, device_t child)
288 struct ofw_gpiobus_devinfo *devi;
291 devi = device_get_ivars(child);
292 retval += bus_print_child_header(dev, child);
293 retval += printf(" at pin(s) ");
294 gpiobus_print_pins(&devi->opd_dinfo);
295 retval += bus_print_child_footer(dev, child);
300 static const struct ofw_bus_devinfo *
301 ofw_gpiobus_get_devinfo(device_t bus, device_t dev)
303 struct ofw_gpiobus_devinfo *dinfo;
305 dinfo = device_get_ivars(dev);
307 return (&dinfo->opd_obdinfo);
310 static device_method_t ofw_gpiobus_methods[] = {
311 /* Device interface */
312 DEVMETHOD(device_probe, ofw_gpiobus_probe),
313 DEVMETHOD(device_attach, ofw_gpiobus_attach),
316 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
317 DEVMETHOD(bus_print_child, ofw_gpiobus_print_child),
318 DEVMETHOD(bus_add_child, ofw_gpiobus_add_child),
320 /* ofw_bus interface */
321 DEVMETHOD(ofw_bus_get_devinfo, ofw_gpiobus_get_devinfo),
322 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
323 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
324 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
325 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
326 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
331 static devclass_t ofwgpiobus_devclass;
333 DEFINE_CLASS_1(gpiobus, ofw_gpiobus_driver, ofw_gpiobus_methods,
334 sizeof(struct gpiobus_softc), gpiobus_driver);
335 DRIVER_MODULE(ofw_gpiobus, gpio, ofw_gpiobus_driver, ofwgpiobus_devclass, 0, 0);
336 MODULE_VERSION(ofw_gpiobus, 1);
337 MODULE_DEPEND(ofw_gpiobus, gpiobus, 1, 1, 1);