1/*- 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 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 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. 16 * 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. 27 */ 28 29#include <sys/cdefs.h>
| 1/*- 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 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 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. 16 * 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. 27 */ 28 29#include <sys/cdefs.h>
|
45 46static int ofw_gpiobus_parse_gpios(struct gpiobus_softc *, 47 struct gpiobus_ivar *, phandle_t); 48static struct ofw_gpiobus_devinfo *ofw_gpiobus_setup_devinfo(device_t, 49 phandle_t); 50static void ofw_gpiobus_destroy_devinfo(struct ofw_gpiobus_devinfo *); 51 52device_t 53ofw_gpiobus_add_fdt_child(device_t bus, phandle_t child) 54{ 55 struct ofw_gpiobus_devinfo *dinfo; 56 device_t childdev; 57 58 /* 59 * Set up the GPIO child and OFW bus layer devinfo and add it to bus. 60 */ 61 dinfo = ofw_gpiobus_setup_devinfo(bus, child); 62 if (dinfo == NULL) 63 return (NULL); 64 childdev = device_add_child(bus, NULL, -1); 65 if (childdev == NULL) { 66 device_printf(bus, "could not add child: %s\n", 67 dinfo->opd_obdinfo.obd_name); 68 ofw_gpiobus_destroy_devinfo(dinfo); 69 return (NULL); 70 } 71 device_set_ivars(childdev, dinfo); 72 73 return (childdev); 74} 75 76static int 77ofw_gpiobus_alloc_ivars(struct gpiobus_ivar *dinfo) 78{ 79 80 /* Allocate pins and flags memory. */ 81 dinfo->pins = malloc(sizeof(uint32_t) * dinfo->npins, M_DEVBUF, 82 M_NOWAIT | M_ZERO); 83 if (dinfo->pins == NULL) 84 return (ENOMEM); 85 dinfo->flags = malloc(sizeof(uint32_t) * dinfo->npins, M_DEVBUF, 86 M_NOWAIT | M_ZERO); 87 if (dinfo->flags == NULL) { 88 free(dinfo->pins, M_DEVBUF); 89 return (ENOMEM); 90 } 91 92 return (0); 93} 94 95static void 96ofw_gpiobus_free_ivars(struct gpiobus_ivar *dinfo) 97{ 98 99 free(dinfo->flags, M_DEVBUF); 100 free(dinfo->pins, M_DEVBUF); 101} 102 103static int 104ofw_gpiobus_parse_gpios(struct gpiobus_softc *sc, struct gpiobus_ivar *dinfo, 105 phandle_t child) 106{ 107 int cells, i, j, len; 108 pcell_t *gpios; 109 phandle_t gpio; 110 111 /* Retrieve the gpios property. */ 112 if ((len = OF_getproplen(child, "gpios")) < 0) 113 return (EINVAL); 114 gpios = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); 115 if (gpios == NULL) 116 return (ENOMEM); 117 if (OF_getencprop(child, "gpios", gpios, len) < 0) { 118 free(gpios, M_DEVBUF); 119 return (EINVAL); 120 } 121 122 /* 123 * The gpio-specifier is controller independent, but the first pcell 124 * has the reference to the GPIO controller phandler. 125 * One the first pass we count the number of encoded gpio-specifiers. 126 */ 127 i = 0; 128 len /= sizeof(pcell_t); 129 while (i < len) { 130 /* Allow NULL specifiers. */ 131 if (gpios[i] == 0) { 132 dinfo->npins++; 133 i++; 134 continue; 135 } 136 gpio = OF_xref_phandle(gpios[i]); 137 /* Verify if we're attaching to the correct GPIO controller. */ 138 if (!OF_hasprop(gpio, "gpio-controller") || 139 gpio != ofw_bus_get_node(sc->sc_dev)) { 140 free(gpios, M_DEVBUF); 141 return (EINVAL); 142 } 143 /* Read gpio-cells property for this GPIO controller. */ 144 if (OF_getencprop(gpio, "#gpio-cells", &cells, 145 sizeof(cells)) < 0) { 146 free(gpios, M_DEVBUF); 147 return (EINVAL); 148 } 149 dinfo->npins++; 150 i += cells + 1; 151 } 152 153 if (dinfo->npins == 0) { 154 free(gpios, M_DEVBUF); 155 return (EINVAL); 156 } 157 158 /* Allocate the child resources. */ 159 if (ofw_gpiobus_alloc_ivars(dinfo) != 0) { 160 free(gpios, M_DEVBUF); 161 return (ENOMEM); 162 } 163 164 /* Decode the gpio specifier on the second pass. */ 165 i = 0; 166 j = 0; 167 while (i < len) { 168 /* Allow NULL specifiers. */ 169 if (gpios[i] == 0) { 170 i++; 171 j++; 172 continue; 173 } 174 175 gpio = OF_xref_phandle(gpios[i]); 176 /* Read gpio-cells property for this GPIO controller. */ 177 if (OF_getencprop(gpio, "#gpio-cells", &cells, 178 sizeof(cells)) < 0) { 179 ofw_gpiobus_free_ivars(dinfo); 180 free(gpios, M_DEVBUF); 181 return (EINVAL); 182 } 183 184 /* Get the GPIO pin number and flags. */ 185 if (ofw_bus_map_gpios(sc->sc_dev, child, gpio, cells, 186 &gpios[i + 1], &dinfo->pins[j], &dinfo->flags[j]) != 0) { 187 ofw_gpiobus_free_ivars(dinfo); 188 free(gpios, M_DEVBUF); 189 return (EINVAL); 190 } 191 192 /* Consistency check. */ 193 if (dinfo->pins[j] > sc->sc_npins) { 194 device_printf(sc->sc_busdev, 195 "invalid pin %d, max: %d\n", 196 dinfo->pins[j], sc->sc_npins - 1); 197 ofw_gpiobus_free_ivars(dinfo); 198 free(gpios, M_DEVBUF); 199 return (EINVAL); 200 } 201 202 /* 203 * Mark pin as mapped and give warning if it's already mapped. 204 */ 205 if (sc->sc_pins_mapped[dinfo->pins[j]]) { 206 device_printf(sc->sc_busdev, 207 "warning: pin %d is already mapped\n", 208 dinfo->pins[j]); 209 ofw_gpiobus_free_ivars(dinfo); 210 free(gpios, M_DEVBUF); 211 return (EINVAL); 212 } 213 sc->sc_pins_mapped[dinfo->pins[j]] = 1; 214 215 i += cells + 1; 216 j++; 217 } 218 219 free(gpios, M_DEVBUF); 220 221 return (0); 222} 223 224static struct ofw_gpiobus_devinfo * 225ofw_gpiobus_setup_devinfo(device_t dev, phandle_t node) 226{ 227 struct gpiobus_softc *sc; 228 struct ofw_gpiobus_devinfo *dinfo; 229 230 sc = device_get_softc(dev); 231 dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_NOWAIT | M_ZERO); 232 if (dinfo == NULL) 233 return (NULL); 234 if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, node) != 0) { 235 free(dinfo, M_DEVBUF); 236 return (NULL); 237 } 238 239 /* Parse the gpios property for the child. */ 240 if (ofw_gpiobus_parse_gpios(sc, &dinfo->opd_dinfo, node) != 0) { 241 ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); 242 free(dinfo, M_DEVBUF); 243 return (NULL); 244 } 245 246 return (dinfo); 247} 248 249static void 250ofw_gpiobus_destroy_devinfo(struct ofw_gpiobus_devinfo *dinfo) 251{ 252 253 ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); 254 free(dinfo, M_DEVBUF); 255} 256 257static int 258ofw_gpiobus_probe(device_t dev) 259{ 260 261 if (ofw_bus_get_node(dev) == -1) 262 return (ENXIO); 263 device_set_desc(dev, "OFW GPIO bus"); 264 265 return (0); 266} 267 268static int 269ofw_gpiobus_attach(device_t dev) 270{ 271 struct gpiobus_softc *sc; 272 phandle_t child; 273 274 sc = GPIOBUS_SOFTC(dev); 275 sc->sc_busdev = dev; 276 sc->sc_dev = device_get_parent(dev); 277 278 /* Read the pin max. value */ 279 if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0) 280 return (ENXIO); 281 282 KASSERT(sc->sc_npins != 0, ("GPIO device with no pins")); 283 284 /* 285 * Increase to get number of pins. 286 */ 287 sc->sc_npins++; 288 289 sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF, 290 M_NOWAIT | M_ZERO); 291 292 if (!sc->sc_pins_mapped) 293 return (ENOMEM); 294 295 /* Init the bus lock. */ 296 GPIOBUS_LOCK_INIT(sc); 297 298 bus_generic_probe(dev); 299 bus_enumerate_hinted_children(dev); 300 301 /* 302 * Attach the children represented in the device tree. 303 */ 304 for (child = OF_child(ofw_bus_get_node(dev)); child != 0; 305 child = OF_peer(child)) 306 if (ofw_gpiobus_add_fdt_child(dev, child) == NULL) 307 continue; 308 309 return (bus_generic_attach(dev)); 310} 311 312static device_t 313ofw_gpiobus_add_child(device_t dev, u_int order, const char *name, int unit) 314{ 315 device_t child; 316 struct ofw_gpiobus_devinfo *devi; 317 318 child = device_add_child_ordered(dev, order, name, unit); 319 if (child == NULL) 320 return (child); 321 devi = malloc(sizeof(struct ofw_gpiobus_devinfo), M_DEVBUF, 322 M_NOWAIT | M_ZERO); 323 if (devi == NULL) { 324 device_delete_child(dev, child); 325 return (0); 326 } 327 328 /* 329 * NULL all the OFW-related parts of the ivars for non-OFW 330 * children. 331 */ 332 devi->opd_obdinfo.obd_node = -1; 333 devi->opd_obdinfo.obd_name = NULL; 334 devi->opd_obdinfo.obd_compat = NULL; 335 devi->opd_obdinfo.obd_type = NULL; 336 devi->opd_obdinfo.obd_model = NULL; 337 338 device_set_ivars(child, devi); 339 340 return (child); 341} 342 343static int 344ofw_gpiobus_print_child(device_t dev, device_t child) 345{ 346 struct ofw_gpiobus_devinfo *devi; 347 int retval = 0; 348 349 devi = device_get_ivars(child); 350 retval += bus_print_child_header(dev, child); 351 retval += printf(" at pin(s) "); 352 gpiobus_print_pins(&devi->opd_dinfo); 353 retval += bus_print_child_footer(dev, child); 354 355 return (retval); 356} 357 358static const struct ofw_bus_devinfo * 359ofw_gpiobus_get_devinfo(device_t bus, device_t dev) 360{ 361 struct ofw_gpiobus_devinfo *dinfo; 362 363 dinfo = device_get_ivars(dev); 364 365 return (&dinfo->opd_obdinfo); 366} 367 368static device_method_t ofw_gpiobus_methods[] = { 369 /* Device interface */ 370 DEVMETHOD(device_probe, ofw_gpiobus_probe), 371 DEVMETHOD(device_attach, ofw_gpiobus_attach), 372 373 /* Bus interface */ 374 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), 375 DEVMETHOD(bus_print_child, ofw_gpiobus_print_child), 376 DEVMETHOD(bus_add_child, ofw_gpiobus_add_child), 377 378 /* ofw_bus interface */ 379 DEVMETHOD(ofw_bus_get_devinfo, ofw_gpiobus_get_devinfo), 380 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 381 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 382 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 383 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 384 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 385 386 DEVMETHOD_END 387}; 388 389static devclass_t ofwgpiobus_devclass; 390 391DEFINE_CLASS_1(gpiobus, ofw_gpiobus_driver, ofw_gpiobus_methods, 392 sizeof(struct gpiobus_softc), gpiobus_driver); 393DRIVER_MODULE(ofw_gpiobus, gpio, ofw_gpiobus_driver, ofwgpiobus_devclass, 0, 0); 394MODULE_VERSION(ofw_gpiobus, 1); 395MODULE_DEPEND(ofw_gpiobus, gpiobus, 1, 1, 1);
| 43 44static int ofw_gpiobus_parse_gpios(struct gpiobus_softc *, 45 struct gpiobus_ivar *, phandle_t); 46static struct ofw_gpiobus_devinfo *ofw_gpiobus_setup_devinfo(device_t, 47 phandle_t); 48static void ofw_gpiobus_destroy_devinfo(struct ofw_gpiobus_devinfo *); 49 50device_t 51ofw_gpiobus_add_fdt_child(device_t bus, phandle_t child) 52{ 53 struct ofw_gpiobus_devinfo *dinfo; 54 device_t childdev; 55 56 /* 57 * Set up the GPIO child and OFW bus layer devinfo and add it to bus. 58 */ 59 dinfo = ofw_gpiobus_setup_devinfo(bus, child); 60 if (dinfo == NULL) 61 return (NULL); 62 childdev = device_add_child(bus, NULL, -1); 63 if (childdev == NULL) { 64 device_printf(bus, "could not add child: %s\n", 65 dinfo->opd_obdinfo.obd_name); 66 ofw_gpiobus_destroy_devinfo(dinfo); 67 return (NULL); 68 } 69 device_set_ivars(childdev, dinfo); 70 71 return (childdev); 72} 73 74static int 75ofw_gpiobus_alloc_ivars(struct gpiobus_ivar *dinfo) 76{ 77 78 /* Allocate pins and flags memory. */ 79 dinfo->pins = malloc(sizeof(uint32_t) * dinfo->npins, M_DEVBUF, 80 M_NOWAIT | M_ZERO); 81 if (dinfo->pins == NULL) 82 return (ENOMEM); 83 dinfo->flags = malloc(sizeof(uint32_t) * dinfo->npins, M_DEVBUF, 84 M_NOWAIT | M_ZERO); 85 if (dinfo->flags == NULL) { 86 free(dinfo->pins, M_DEVBUF); 87 return (ENOMEM); 88 } 89 90 return (0); 91} 92 93static void 94ofw_gpiobus_free_ivars(struct gpiobus_ivar *dinfo) 95{ 96 97 free(dinfo->flags, M_DEVBUF); 98 free(dinfo->pins, M_DEVBUF); 99} 100 101static int 102ofw_gpiobus_parse_gpios(struct gpiobus_softc *sc, struct gpiobus_ivar *dinfo, 103 phandle_t child) 104{ 105 int cells, i, j, len; 106 pcell_t *gpios; 107 phandle_t gpio; 108 109 /* Retrieve the gpios property. */ 110 if ((len = OF_getproplen(child, "gpios")) < 0) 111 return (EINVAL); 112 gpios = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); 113 if (gpios == NULL) 114 return (ENOMEM); 115 if (OF_getencprop(child, "gpios", gpios, len) < 0) { 116 free(gpios, M_DEVBUF); 117 return (EINVAL); 118 } 119 120 /* 121 * The gpio-specifier is controller independent, but the first pcell 122 * has the reference to the GPIO controller phandler. 123 * One the first pass we count the number of encoded gpio-specifiers. 124 */ 125 i = 0; 126 len /= sizeof(pcell_t); 127 while (i < len) { 128 /* Allow NULL specifiers. */ 129 if (gpios[i] == 0) { 130 dinfo->npins++; 131 i++; 132 continue; 133 } 134 gpio = OF_xref_phandle(gpios[i]); 135 /* Verify if we're attaching to the correct GPIO controller. */ 136 if (!OF_hasprop(gpio, "gpio-controller") || 137 gpio != ofw_bus_get_node(sc->sc_dev)) { 138 free(gpios, M_DEVBUF); 139 return (EINVAL); 140 } 141 /* Read gpio-cells property for this GPIO controller. */ 142 if (OF_getencprop(gpio, "#gpio-cells", &cells, 143 sizeof(cells)) < 0) { 144 free(gpios, M_DEVBUF); 145 return (EINVAL); 146 } 147 dinfo->npins++; 148 i += cells + 1; 149 } 150 151 if (dinfo->npins == 0) { 152 free(gpios, M_DEVBUF); 153 return (EINVAL); 154 } 155 156 /* Allocate the child resources. */ 157 if (ofw_gpiobus_alloc_ivars(dinfo) != 0) { 158 free(gpios, M_DEVBUF); 159 return (ENOMEM); 160 } 161 162 /* Decode the gpio specifier on the second pass. */ 163 i = 0; 164 j = 0; 165 while (i < len) { 166 /* Allow NULL specifiers. */ 167 if (gpios[i] == 0) { 168 i++; 169 j++; 170 continue; 171 } 172 173 gpio = OF_xref_phandle(gpios[i]); 174 /* Read gpio-cells property for this GPIO controller. */ 175 if (OF_getencprop(gpio, "#gpio-cells", &cells, 176 sizeof(cells)) < 0) { 177 ofw_gpiobus_free_ivars(dinfo); 178 free(gpios, M_DEVBUF); 179 return (EINVAL); 180 } 181 182 /* Get the GPIO pin number and flags. */ 183 if (ofw_bus_map_gpios(sc->sc_dev, child, gpio, cells, 184 &gpios[i + 1], &dinfo->pins[j], &dinfo->flags[j]) != 0) { 185 ofw_gpiobus_free_ivars(dinfo); 186 free(gpios, M_DEVBUF); 187 return (EINVAL); 188 } 189 190 /* Consistency check. */ 191 if (dinfo->pins[j] > sc->sc_npins) { 192 device_printf(sc->sc_busdev, 193 "invalid pin %d, max: %d\n", 194 dinfo->pins[j], sc->sc_npins - 1); 195 ofw_gpiobus_free_ivars(dinfo); 196 free(gpios, M_DEVBUF); 197 return (EINVAL); 198 } 199 200 /* 201 * Mark pin as mapped and give warning if it's already mapped. 202 */ 203 if (sc->sc_pins_mapped[dinfo->pins[j]]) { 204 device_printf(sc->sc_busdev, 205 "warning: pin %d is already mapped\n", 206 dinfo->pins[j]); 207 ofw_gpiobus_free_ivars(dinfo); 208 free(gpios, M_DEVBUF); 209 return (EINVAL); 210 } 211 sc->sc_pins_mapped[dinfo->pins[j]] = 1; 212 213 i += cells + 1; 214 j++; 215 } 216 217 free(gpios, M_DEVBUF); 218 219 return (0); 220} 221 222static struct ofw_gpiobus_devinfo * 223ofw_gpiobus_setup_devinfo(device_t dev, phandle_t node) 224{ 225 struct gpiobus_softc *sc; 226 struct ofw_gpiobus_devinfo *dinfo; 227 228 sc = device_get_softc(dev); 229 dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_NOWAIT | M_ZERO); 230 if (dinfo == NULL) 231 return (NULL); 232 if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, node) != 0) { 233 free(dinfo, M_DEVBUF); 234 return (NULL); 235 } 236 237 /* Parse the gpios property for the child. */ 238 if (ofw_gpiobus_parse_gpios(sc, &dinfo->opd_dinfo, node) != 0) { 239 ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); 240 free(dinfo, M_DEVBUF); 241 return (NULL); 242 } 243 244 return (dinfo); 245} 246 247static void 248ofw_gpiobus_destroy_devinfo(struct ofw_gpiobus_devinfo *dinfo) 249{ 250 251 ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); 252 free(dinfo, M_DEVBUF); 253} 254 255static int 256ofw_gpiobus_probe(device_t dev) 257{ 258 259 if (ofw_bus_get_node(dev) == -1) 260 return (ENXIO); 261 device_set_desc(dev, "OFW GPIO bus"); 262 263 return (0); 264} 265 266static int 267ofw_gpiobus_attach(device_t dev) 268{ 269 struct gpiobus_softc *sc; 270 phandle_t child; 271 272 sc = GPIOBUS_SOFTC(dev); 273 sc->sc_busdev = dev; 274 sc->sc_dev = device_get_parent(dev); 275 276 /* Read the pin max. value */ 277 if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0) 278 return (ENXIO); 279 280 KASSERT(sc->sc_npins != 0, ("GPIO device with no pins")); 281 282 /* 283 * Increase to get number of pins. 284 */ 285 sc->sc_npins++; 286 287 sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF, 288 M_NOWAIT | M_ZERO); 289 290 if (!sc->sc_pins_mapped) 291 return (ENOMEM); 292 293 /* Init the bus lock. */ 294 GPIOBUS_LOCK_INIT(sc); 295 296 bus_generic_probe(dev); 297 bus_enumerate_hinted_children(dev); 298 299 /* 300 * Attach the children represented in the device tree. 301 */ 302 for (child = OF_child(ofw_bus_get_node(dev)); child != 0; 303 child = OF_peer(child)) 304 if (ofw_gpiobus_add_fdt_child(dev, child) == NULL) 305 continue; 306 307 return (bus_generic_attach(dev)); 308} 309 310static device_t 311ofw_gpiobus_add_child(device_t dev, u_int order, const char *name, int unit) 312{ 313 device_t child; 314 struct ofw_gpiobus_devinfo *devi; 315 316 child = device_add_child_ordered(dev, order, name, unit); 317 if (child == NULL) 318 return (child); 319 devi = malloc(sizeof(struct ofw_gpiobus_devinfo), M_DEVBUF, 320 M_NOWAIT | M_ZERO); 321 if (devi == NULL) { 322 device_delete_child(dev, child); 323 return (0); 324 } 325 326 /* 327 * NULL all the OFW-related parts of the ivars for non-OFW 328 * children. 329 */ 330 devi->opd_obdinfo.obd_node = -1; 331 devi->opd_obdinfo.obd_name = NULL; 332 devi->opd_obdinfo.obd_compat = NULL; 333 devi->opd_obdinfo.obd_type = NULL; 334 devi->opd_obdinfo.obd_model = NULL; 335 336 device_set_ivars(child, devi); 337 338 return (child); 339} 340 341static int 342ofw_gpiobus_print_child(device_t dev, device_t child) 343{ 344 struct ofw_gpiobus_devinfo *devi; 345 int retval = 0; 346 347 devi = device_get_ivars(child); 348 retval += bus_print_child_header(dev, child); 349 retval += printf(" at pin(s) "); 350 gpiobus_print_pins(&devi->opd_dinfo); 351 retval += bus_print_child_footer(dev, child); 352 353 return (retval); 354} 355 356static const struct ofw_bus_devinfo * 357ofw_gpiobus_get_devinfo(device_t bus, device_t dev) 358{ 359 struct ofw_gpiobus_devinfo *dinfo; 360 361 dinfo = device_get_ivars(dev); 362 363 return (&dinfo->opd_obdinfo); 364} 365 366static device_method_t ofw_gpiobus_methods[] = { 367 /* Device interface */ 368 DEVMETHOD(device_probe, ofw_gpiobus_probe), 369 DEVMETHOD(device_attach, ofw_gpiobus_attach), 370 371 /* Bus interface */ 372 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), 373 DEVMETHOD(bus_print_child, ofw_gpiobus_print_child), 374 DEVMETHOD(bus_add_child, ofw_gpiobus_add_child), 375 376 /* ofw_bus interface */ 377 DEVMETHOD(ofw_bus_get_devinfo, ofw_gpiobus_get_devinfo), 378 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 379 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 380 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 381 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 382 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 383 384 DEVMETHOD_END 385}; 386 387static devclass_t ofwgpiobus_devclass; 388 389DEFINE_CLASS_1(gpiobus, ofw_gpiobus_driver, ofw_gpiobus_methods, 390 sizeof(struct gpiobus_softc), gpiobus_driver); 391DRIVER_MODULE(ofw_gpiobus, gpio, ofw_gpiobus_driver, ofwgpiobus_devclass, 0, 0); 392MODULE_VERSION(ofw_gpiobus, 1); 393MODULE_DEPEND(ofw_gpiobus, gpiobus, 1, 1, 1);
|