1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2009, Nathan Whitehorn <nwhitehorn@FreeBSD.org> 5 * Copyright (c) 2013, Luiz Otavio O Souza <loos@FreeBSD.org> 6 * Copyright (c) 2013 The FreeBSD Foundation 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice unmodified, this list of conditions, and the following 14 * disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/bus.h> 34 #include <sys/kernel.h> 35 #include <sys/malloc.h> 36 #include <sys/module.h> 37 38 #include <dev/gpio/gpiobusvar.h> 39 #include <dev/ofw/ofw_bus.h> 40 41 #include "gpiobus_if.h" 42 43 static struct ofw_gpiobus_devinfo *ofw_gpiobus_setup_devinfo(device_t, 44 device_t, phandle_t); 45 static void ofw_gpiobus_destroy_devinfo(device_t, struct ofw_gpiobus_devinfo *); 46 static int ofw_gpiobus_parse_gpios_impl(device_t, phandle_t, char *, 47 struct gpiobus_softc *, struct gpiobus_pin **); 48 49 /* 50 * Utility functions for easier handling of OFW GPIO pins. 51 * 52 * !!! BEWARE !!! 53 * GPIOBUS uses children's IVARs, so we cannot use this interface for cross 54 * tree consumers. 55 * 56 */ 57 int 58 gpio_pin_get_by_ofw_propidx(device_t consumer, phandle_t cnode, 59 char *prop_name, int idx, gpio_pin_t *out_pin) 60 { 61 phandle_t xref; 62 pcell_t *cells; 63 device_t busdev; 64 struct gpiobus_pin pin; 65 int ncells, rv; 66 67 KASSERT(consumer != NULL && cnode > 0, 68 ("both consumer and cnode required")); 69 70 rv = ofw_bus_parse_xref_list_alloc(cnode, prop_name, "#gpio-cells", 71 idx, &xref, &ncells, &cells); 72 if (rv != 0) 73 return (rv); 74 75 /* Translate provider to device. */ 76 pin.dev = OF_device_from_xref(xref); 77 if (pin.dev == NULL) { 78 OF_prop_free(cells); 79 return (ENODEV); 80 } 81 82 /* Test if GPIO bus already exist. */ 83 busdev = GPIO_GET_BUS(pin.dev); 84 if (busdev == NULL) { 85 OF_prop_free(cells); 86 return (ENODEV); 87 } 88 89 /* Map GPIO pin. */ 90 rv = gpio_map_gpios(pin.dev, cnode, OF_node_from_xref(xref), ncells, 91 cells, &pin.pin, &pin.flags); 92 OF_prop_free(cells); 93 if (rv != 0) 94 return (ENXIO); 95 96 /* Reserve GPIO pin. */ 97 rv = gpiobus_acquire_pin(busdev, pin.pin); 98 if (rv != 0) 99 return (EBUSY); 100 101 *out_pin = malloc(sizeof(struct gpiobus_pin), M_DEVBUF, 102 M_WAITOK | M_ZERO); 103 **out_pin = pin; 104 return (0); 105 } 106 107 int 108 gpio_pin_get_by_ofw_idx(device_t consumer, phandle_t node, 109 int idx, gpio_pin_t *pin) 110 { 111 112 return (gpio_pin_get_by_ofw_propidx(consumer, node, "gpios", idx, pin)); 113 } 114 115 int 116 gpio_pin_get_by_ofw_property(device_t consumer, phandle_t node, 117 char *name, gpio_pin_t *pin) 118 { 119 120 return (gpio_pin_get_by_ofw_propidx(consumer, node, name, 0, pin)); 121 } 122 123 int 124 gpio_pin_get_by_ofw_name(device_t consumer, phandle_t node, 125 char *name, gpio_pin_t *pin) 126 { 127 int rv, idx; 128 129 KASSERT(consumer != NULL && node > 0, 130 ("both consumer and node required")); 131 132 rv = ofw_bus_find_string_index(node, "gpio-names", name, &idx); 133 if (rv != 0) 134 return (rv); 135 return (gpio_pin_get_by_ofw_idx(consumer, node, idx, pin)); 136 } 137 138 /* 139 * OFW_GPIOBUS driver. 140 */ 141 device_t 142 ofw_gpiobus_add_fdt_child(device_t bus, const char *drvname, phandle_t child) 143 { 144 device_t childdev; 145 int i; 146 struct gpiobus_ivar *devi; 147 struct ofw_gpiobus_devinfo *dinfo; 148 149 /* 150 * Check to see if we already have a child for @p child, and if so 151 * return it. 152 */ 153 childdev = ofw_bus_find_child_device_by_phandle(bus, child); 154 if (childdev != NULL) 155 return (childdev); 156 157 /* 158 * Set up the GPIO child and OFW bus layer devinfo and add it to bus. 159 */ 160 childdev = device_add_child(bus, drvname, DEVICE_UNIT_ANY); 161 if (childdev == NULL) 162 return (NULL); 163 dinfo = ofw_gpiobus_setup_devinfo(bus, childdev, child); 164 if (dinfo == NULL) { 165 device_delete_child(bus, childdev); 166 return (NULL); 167 } 168 if (device_probe_and_attach(childdev) != 0) { 169 ofw_gpiobus_destroy_devinfo(bus, dinfo); 170 device_delete_child(bus, childdev); 171 return (NULL); 172 } 173 /* Use the child name as pin name. */ 174 devi = &dinfo->opd_dinfo; 175 for (i = 0; i < devi->npins; i++) 176 GPIOBUS_PIN_SETNAME(bus, devi->pins[i], 177 device_get_nameunit(childdev)); 178 179 return (childdev); 180 } 181 182 int 183 ofw_gpiobus_parse_gpios(device_t consumer, char *pname, 184 struct gpiobus_pin **pins) 185 { 186 187 return (ofw_gpiobus_parse_gpios_impl(consumer, 188 ofw_bus_get_node(consumer), pname, NULL, pins)); 189 } 190 191 void 192 ofw_gpiobus_register_provider(device_t provider) 193 { 194 phandle_t node; 195 196 node = ofw_bus_get_node(provider); 197 if (node != -1) 198 OF_device_register_xref(OF_xref_from_node(node), provider); 199 } 200 201 void 202 ofw_gpiobus_unregister_provider(device_t provider) 203 { 204 phandle_t node; 205 206 node = ofw_bus_get_node(provider); 207 if (node != -1) 208 OF_device_register_xref(OF_xref_from_node(node), NULL); 209 } 210 211 static struct ofw_gpiobus_devinfo * 212 ofw_gpiobus_setup_devinfo(device_t bus, device_t child, phandle_t node) 213 { 214 int i, npins; 215 struct gpiobus_ivar *devi; 216 struct gpiobus_pin *pins; 217 struct gpiobus_softc *sc; 218 struct ofw_gpiobus_devinfo *dinfo; 219 220 sc = device_get_softc(bus); 221 dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_NOWAIT | M_ZERO); 222 if (dinfo == NULL) 223 return (NULL); 224 if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, node) != 0) { 225 free(dinfo, M_DEVBUF); 226 return (NULL); 227 } 228 /* Parse the gpios property for the child. */ 229 npins = ofw_gpiobus_parse_gpios_impl(child, node, "gpios", sc, &pins); 230 if (npins <= 0) { 231 ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); 232 free(dinfo, M_DEVBUF); 233 return (NULL); 234 } 235 /* Initialize the irq resource list. */ 236 resource_list_init(&dinfo->opd_dinfo.rl); 237 /* Allocate the child ivars and copy the parsed pin data. */ 238 devi = &dinfo->opd_dinfo; 239 devi->npins = (uint32_t)npins; 240 if (gpiobus_alloc_ivars(devi) != 0) { 241 free(pins, M_DEVBUF); 242 ofw_gpiobus_destroy_devinfo(bus, dinfo); 243 return (NULL); 244 } 245 for (i = 0; i < devi->npins; i++) 246 devi->pins[i] = pins[i].pin; 247 free(pins, M_DEVBUF); 248 /* Parse the interrupt resources. */ 249 if (ofw_bus_intr_to_rl(bus, node, &dinfo->opd_dinfo.rl, NULL) != 0) { 250 ofw_gpiobus_destroy_devinfo(bus, dinfo); 251 return (NULL); 252 } 253 device_set_ivars(child, dinfo); 254 255 return (dinfo); 256 } 257 258 static void 259 ofw_gpiobus_destroy_devinfo(device_t bus, struct ofw_gpiobus_devinfo *dinfo) 260 { 261 int i; 262 struct gpiobus_ivar *devi; 263 struct gpiobus_softc *sc; 264 265 sc = device_get_softc(bus); 266 devi = &dinfo->opd_dinfo; 267 for (i = 0; i < devi->npins; i++) { 268 if (devi->pins[i] > sc->sc_npins) 269 continue; 270 sc->sc_pins[devi->pins[i]].mapped = 0; 271 } 272 gpiobus_free_ivars(devi); 273 resource_list_free(&dinfo->opd_dinfo.rl); 274 ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); 275 free(dinfo, M_DEVBUF); 276 } 277 278 static int 279 ofw_gpiobus_parse_gpios_impl(device_t consumer, phandle_t cnode, char *pname, 280 struct gpiobus_softc *bussc, struct gpiobus_pin **pins) 281 { 282 int gpiocells, i, j, ncells, npins; 283 pcell_t *gpios; 284 phandle_t gpio; 285 286 ncells = OF_getencprop_alloc_multi(cnode, pname, sizeof(*gpios), 287 (void **)&gpios); 288 if (ncells == -1) { 289 device_printf(consumer, 290 "Warning: No %s specified in fdt data; " 291 "device may not function.\n", pname); 292 return (-1); 293 } 294 /* 295 * The gpio-specifier is controller independent, the first pcell has 296 * the reference to the GPIO controller phandler. 297 * Count the number of encoded gpio-specifiers on the first pass. 298 */ 299 i = 0; 300 npins = 0; 301 while (i < ncells) { 302 /* Allow NULL specifiers. */ 303 if (gpios[i] == 0) { 304 npins++; 305 i++; 306 continue; 307 } 308 gpio = OF_node_from_xref(gpios[i]); 309 /* If we have bussc, ignore devices from other gpios. */ 310 if (bussc != NULL) 311 if (ofw_bus_get_node(bussc->sc_dev) != gpio) 312 return (0); 313 /* 314 * Check for gpio-controller property and read the #gpio-cells 315 * for this GPIO controller. 316 */ 317 if (!OF_hasprop(gpio, "gpio-controller") || 318 OF_getencprop(gpio, "#gpio-cells", &gpiocells, 319 sizeof(gpiocells)) < 0) { 320 device_printf(consumer, 321 "gpio reference is not a gpio-controller.\n"); 322 OF_prop_free(gpios); 323 return (-1); 324 } 325 if (ncells - i < gpiocells + 1) { 326 device_printf(consumer, 327 "%s cells doesn't match #gpio-cells.\n", pname); 328 return (-1); 329 } 330 npins++; 331 i += gpiocells + 1; 332 } 333 if (npins == 0 || pins == NULL) { 334 if (npins == 0) 335 device_printf(consumer, "no pin specified in %s.\n", 336 pname); 337 OF_prop_free(gpios); 338 return (npins); 339 } 340 *pins = malloc(sizeof(struct gpiobus_pin) * npins, M_DEVBUF, 341 M_NOWAIT | M_ZERO); 342 if (*pins == NULL) { 343 OF_prop_free(gpios); 344 return (-1); 345 } 346 /* Decode the gpio specifier on the second pass. */ 347 i = 0; 348 j = 0; 349 while (i < ncells) { 350 /* Allow NULL specifiers. */ 351 if (gpios[i] == 0) { 352 j++; 353 i++; 354 continue; 355 } 356 gpio = OF_node_from_xref(gpios[i]); 357 /* Read gpio-cells property for this GPIO controller. */ 358 if (OF_getencprop(gpio, "#gpio-cells", &gpiocells, 359 sizeof(gpiocells)) < 0) { 360 device_printf(consumer, 361 "gpio does not have the #gpio-cells property.\n"); 362 goto fail; 363 } 364 /* Return the device reference for the GPIO controller. */ 365 (*pins)[j].dev = OF_device_from_xref(gpios[i]); 366 if ((*pins)[j].dev == NULL) { 367 device_printf(consumer, 368 "no device registered for the gpio controller.\n"); 369 goto fail; 370 } 371 /* 372 * If the gpiobus softc is NULL we use the GPIO_GET_BUS() to 373 * retrieve it. The GPIO_GET_BUS() method is only valid after 374 * the child is probed and attached. 375 */ 376 if (bussc == NULL) { 377 if (GPIO_GET_BUS((*pins)[j].dev) == NULL) { 378 device_printf(consumer, 379 "no gpiobus reference for %s.\n", 380 device_get_nameunit((*pins)[j].dev)); 381 goto fail; 382 } 383 bussc = device_get_softc(GPIO_GET_BUS((*pins)[j].dev)); 384 } 385 /* Get the GPIO pin number and flags. */ 386 if (gpio_map_gpios((*pins)[j].dev, cnode, gpio, gpiocells, 387 &gpios[i + 1], &(*pins)[j].pin, &(*pins)[j].flags) != 0) { 388 device_printf(consumer, 389 "cannot map the gpios specifier.\n"); 390 goto fail; 391 } 392 /* Reserve the GPIO pin. */ 393 if (gpiobus_acquire_pin(bussc->sc_busdev, (*pins)[j].pin) != 0) 394 goto fail; 395 j++; 396 i += gpiocells + 1; 397 } 398 OF_prop_free(gpios); 399 400 return (npins); 401 402 fail: 403 OF_prop_free(gpios); 404 free(*pins, M_DEVBUF); 405 return (-1); 406 } 407 408 static int 409 ofw_gpiobus_probe(device_t dev) 410 { 411 412 if (ofw_bus_get_node(dev) == -1) 413 return (ENXIO); 414 device_set_desc(dev, "OFW GPIO bus"); 415 416 return (BUS_PROBE_DEFAULT); 417 } 418 419 static int 420 ofw_gpiobus_attach(device_t dev) 421 { 422 int err; 423 phandle_t child; 424 425 err = gpiobus_init_softc(dev); 426 if (err != 0) 427 return (err); 428 bus_identify_children(dev); 429 bus_enumerate_hinted_children(dev); 430 /* 431 * Attach the children represented in the device tree. 432 */ 433 for (child = OF_child(ofw_bus_get_node(dev)); child != 0; 434 child = OF_peer(child)) { 435 if (OF_hasprop(child, "gpio-hog")) 436 continue; 437 if (!OF_hasprop(child, "gpios")) 438 continue; 439 if (ofw_gpiobus_add_fdt_child(dev, NULL, child) == NULL) 440 continue; 441 } 442 443 bus_attach_children(dev); 444 return (0); 445 } 446 447 static device_t 448 ofw_gpiobus_add_child(device_t dev, u_int order, const char *name, int unit) 449 { 450 device_t child; 451 struct ofw_gpiobus_devinfo *devi; 452 453 child = device_add_child_ordered(dev, order, name, unit); 454 if (child == NULL) 455 return (child); 456 devi = malloc(sizeof(struct ofw_gpiobus_devinfo), M_DEVBUF, 457 M_NOWAIT | M_ZERO); 458 if (devi == NULL) { 459 device_delete_child(dev, child); 460 return (0); 461 } 462 463 /* 464 * NULL all the OFW-related parts of the ivars for non-OFW 465 * children. 466 */ 467 devi->opd_obdinfo.obd_node = -1; 468 devi->opd_obdinfo.obd_name = NULL; 469 devi->opd_obdinfo.obd_compat = NULL; 470 devi->opd_obdinfo.obd_type = NULL; 471 devi->opd_obdinfo.obd_model = NULL; 472 473 device_set_ivars(child, devi); 474 475 return (child); 476 } 477 478 static const struct ofw_bus_devinfo * 479 ofw_gpiobus_get_devinfo(device_t bus, device_t dev) 480 { 481 struct ofw_gpiobus_devinfo *dinfo; 482 483 dinfo = device_get_ivars(dev); 484 485 return (&dinfo->opd_obdinfo); 486 } 487 488 static device_method_t ofw_gpiobus_methods[] = { 489 /* Device interface */ 490 DEVMETHOD(device_probe, ofw_gpiobus_probe), 491 DEVMETHOD(device_attach, ofw_gpiobus_attach), 492 493 /* Bus interface */ 494 DEVMETHOD(bus_child_pnpinfo, ofw_bus_gen_child_pnpinfo), 495 DEVMETHOD(bus_add_child, ofw_gpiobus_add_child), 496 497 /* ofw_bus interface */ 498 DEVMETHOD(ofw_bus_get_devinfo, ofw_gpiobus_get_devinfo), 499 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 500 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 501 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 502 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 503 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 504 505 DEVMETHOD_END 506 }; 507 508 DEFINE_CLASS_1(gpiobus, ofw_gpiobus_driver, ofw_gpiobus_methods, 509 sizeof(struct gpiobus_softc), gpiobus_driver); 510 EARLY_DRIVER_MODULE(ofw_gpiobus, gpio, ofw_gpiobus_driver, 0, 0, BUS_PASS_BUS); 511 MODULE_VERSION(ofw_gpiobus, 1); 512 MODULE_DEPEND(ofw_gpiobus, gpiobus, 1, 1, 1); 513