33#include <sys/kernel.h> 34#include <sys/malloc.h> 35#include <sys/module.h> 36 37#include <dev/gpio/gpiobusvar.h> 38 39#include "gpiobus_if.h" 40 41#undef GPIOBUS_DEBUG 42#ifdef GPIOBUS_DEBUG 43#define dprintf printf 44#else 45#define dprintf(x, arg...) 46#endif 47 48static void gpiobus_print_pins(struct gpiobus_ivar *, char *, size_t); 49static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int); 50static int gpiobus_probe(device_t); 51static int gpiobus_attach(device_t); 52static int gpiobus_detach(device_t); 53static int gpiobus_suspend(device_t); 54static int gpiobus_resume(device_t); 55static int gpiobus_print_child(device_t, device_t); 56static int gpiobus_child_location_str(device_t, device_t, char *, size_t); 57static int gpiobus_child_pnpinfo_str(device_t, device_t, char *, size_t); 58static device_t gpiobus_add_child(device_t, u_int, const char *, int); 59static void gpiobus_hinted_child(device_t, const char *, int); 60 61/* 62 * GPIOBUS interface 63 */ 64static int gpiobus_acquire_bus(device_t, device_t, int); 65static void gpiobus_release_bus(device_t, device_t); 66static int gpiobus_pin_setflags(device_t, device_t, uint32_t, uint32_t); 67static int gpiobus_pin_getflags(device_t, device_t, uint32_t, uint32_t*); 68static int gpiobus_pin_getcaps(device_t, device_t, uint32_t, uint32_t*); 69static int gpiobus_pin_set(device_t, device_t, uint32_t, unsigned int); 70static int gpiobus_pin_get(device_t, device_t, uint32_t, unsigned int*); 71static int gpiobus_pin_toggle(device_t, device_t, uint32_t); 72
| 34#include <sys/kernel.h> 35#include <sys/malloc.h> 36#include <sys/module.h> 37 38#include <dev/gpio/gpiobusvar.h> 39 40#include "gpiobus_if.h" 41 42#undef GPIOBUS_DEBUG 43#ifdef GPIOBUS_DEBUG 44#define dprintf printf 45#else 46#define dprintf(x, arg...) 47#endif 48 49static void gpiobus_print_pins(struct gpiobus_ivar *, char *, size_t); 50static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int); 51static int gpiobus_probe(device_t); 52static int gpiobus_attach(device_t); 53static int gpiobus_detach(device_t); 54static int gpiobus_suspend(device_t); 55static int gpiobus_resume(device_t); 56static int gpiobus_print_child(device_t, device_t); 57static int gpiobus_child_location_str(device_t, device_t, char *, size_t); 58static int gpiobus_child_pnpinfo_str(device_t, device_t, char *, size_t); 59static device_t gpiobus_add_child(device_t, u_int, const char *, int); 60static void gpiobus_hinted_child(device_t, const char *, int); 61 62/* 63 * GPIOBUS interface 64 */ 65static int gpiobus_acquire_bus(device_t, device_t, int); 66static void gpiobus_release_bus(device_t, device_t); 67static int gpiobus_pin_setflags(device_t, device_t, uint32_t, uint32_t); 68static int gpiobus_pin_getflags(device_t, device_t, uint32_t, uint32_t*); 69static int gpiobus_pin_getcaps(device_t, device_t, uint32_t, uint32_t*); 70static int gpiobus_pin_set(device_t, device_t, uint32_t, unsigned int); 71static int gpiobus_pin_get(device_t, device_t, uint32_t, unsigned int*); 72static int gpiobus_pin_toggle(device_t, device_t, uint32_t); 73
|
73static void 74gpiobus_print_pins(struct gpiobus_ivar *devi, char *buf, size_t buflen) 75{ 76 char tmp[128]; 77 int i, range_start, range_stop, need_coma; 78 79 if (devi->npins == 0) 80 return; 81 82 need_coma = 0; 83 range_start = range_stop = devi->pins[0]; 84 for (i = 1; i < devi->npins; i++) { 85 if (devi->pins[i] != (range_stop + 1)) { 86 if (need_coma) 87 strlcat(buf, ",", buflen); 88 memset(tmp, 0, sizeof(tmp)); 89 if (range_start != range_stop) 90 snprintf(tmp, sizeof(tmp) - 1, "%d-%d", 91 range_start, range_stop); 92 else 93 snprintf(tmp, sizeof(tmp) - 1, "%d", 94 range_start); 95 strlcat(buf, tmp, buflen); 96 97 range_start = range_stop = devi->pins[i]; 98 need_coma = 1; 99 } 100 else 101 range_stop++; 102 } 103 104 if (need_coma) 105 strlcat(buf, ",", buflen); 106 memset(tmp, 0, sizeof(tmp)); 107 if (range_start != range_stop) 108 snprintf(tmp, sizeof(tmp) - 1, "%d-%d", 109 range_start, range_stop); 110 else 111 snprintf(tmp, sizeof(tmp) - 1, "%d", 112 range_start); 113 strlcat(buf, tmp, buflen); 114} 115 116int 117gpiobus_init_softc(device_t dev) 118{ 119 struct gpiobus_softc *sc; 120 121 sc = GPIOBUS_SOFTC(dev); 122 sc->sc_busdev = dev; 123 sc->sc_dev = device_get_parent(dev); 124 sc->sc_intr_rman.rm_type = RMAN_ARRAY; 125 sc->sc_intr_rman.rm_descr = "GPIO Interrupts"; 126 if (rman_init(&sc->sc_intr_rman) != 0 || 127 rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0) 128 panic("%s: failed to set up rman.", __func__); 129 130 if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0) 131 return (ENXIO); 132 133 KASSERT(sc->sc_npins != 0, ("GPIO device with no pins")); 134 135 /* Pins = GPIO_PIN_MAX() + 1 */ 136 sc->sc_npins++; 137 138 sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF, 139 M_NOWAIT | M_ZERO); 140 if (sc->sc_pins_mapped == NULL) 141 return (ENOMEM); 142 143 /* Initialize the bus lock. */ 144 GPIOBUS_LOCK_INIT(sc); 145 146 return (0); 147} 148 149static int 150gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask) 151{ 152 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 153 int i, npins; 154 155 npins = 0; 156 for (i = 0; i < 32; i++) { 157 if (mask & (1 << i)) 158 npins++; 159 } 160 161 if (npins == 0) { 162 device_printf(child, "empty pin mask\n"); 163 return (EINVAL); 164 } 165 166 devi->npins = npins; 167 devi->pins = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF, 168 M_NOWAIT | M_ZERO); 169 170 if (!devi->pins) 171 return (ENOMEM); 172 173 npins = 0; 174 for (i = 0; i < 32; i++) { 175 176 if ((mask & (1 << i)) == 0) 177 continue; 178 179 if (i >= sc->sc_npins) { 180 device_printf(child, 181 "invalid pin %d, max: %d\n", i, sc->sc_npins - 1); 182 free(devi->pins, M_DEVBUF); 183 return (EINVAL); 184 } 185 186 devi->pins[npins++] = i; 187 /* 188 * Mark pin as mapped and give warning if it's already mapped 189 */ 190 if (sc->sc_pins_mapped[i]) { 191 device_printf(child, 192 "warning: pin %d is already mapped\n", i); 193 free(devi->pins, M_DEVBUF); 194 return (EINVAL); 195 } 196 sc->sc_pins_mapped[i] = 1; 197 } 198 199 return (0); 200} 201 202static int 203gpiobus_probe(device_t dev) 204{ 205 device_set_desc(dev, "GPIO bus"); 206 207 return (BUS_PROBE_GENERIC); 208} 209 210static int 211gpiobus_attach(device_t dev) 212{ 213 int err; 214 215 err = gpiobus_init_softc(dev); 216 if (err != 0) 217 return (err); 218 219 /* 220 * Get parent's pins and mark them as unmapped 221 */ 222 bus_generic_probe(dev); 223 bus_enumerate_hinted_children(dev); 224 225 return (bus_generic_attach(dev)); 226} 227 228/* 229 * Since this is not a self-enumerating bus, and since we always add 230 * children in attach, we have to always delete children here. 231 */ 232static int 233gpiobus_detach(device_t dev) 234{ 235 struct gpiobus_softc *sc; 236 struct gpiobus_ivar *devi; 237 device_t *devlist; 238 int i, err, ndevs; 239 240 sc = GPIOBUS_SOFTC(dev); 241 KASSERT(mtx_initialized(&sc->sc_mtx), 242 ("gpiobus mutex not initialized")); 243 GPIOBUS_LOCK_DESTROY(sc); 244 245 if ((err = bus_generic_detach(dev)) != 0) 246 return (err); 247 248 if ((err = device_get_children(dev, &devlist, &ndevs)) != 0) 249 return (err); 250 for (i = 0; i < ndevs; i++) { 251 device_delete_child(dev, devlist[i]); 252 devi = GPIOBUS_IVAR(devlist[i]); 253 if (devi->pins) { 254 free(devi->pins, M_DEVBUF); 255 devi->pins = NULL; 256 } 257 } 258 free(devlist, M_TEMP); 259 260 if (sc->sc_pins_mapped) { 261 free(sc->sc_pins_mapped, M_DEVBUF); 262 sc->sc_pins_mapped = NULL; 263 } 264 265 return (0); 266} 267 268static int 269gpiobus_suspend(device_t dev) 270{ 271 272 return (bus_generic_suspend(dev)); 273} 274 275static int 276gpiobus_resume(device_t dev) 277{ 278 279 return (bus_generic_resume(dev)); 280} 281 282static int 283gpiobus_print_child(device_t dev, device_t child) 284{ 285 char pins[128]; 286 int retval = 0; 287 struct gpiobus_ivar *devi; 288 289 devi = GPIOBUS_IVAR(child); 290 memset(pins, 0, sizeof(pins)); 291 retval += bus_print_child_header(dev, child); 292 retval += printf(" at pin(s) "); 293 gpiobus_print_pins(devi, pins, sizeof(pins)); 294 retval += printf("%s", pins); 295 resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld"); 296 retval += bus_print_child_footer(dev, child); 297 298 return (retval); 299} 300 301static int 302gpiobus_child_location_str(device_t bus, device_t child, char *buf, 303 size_t buflen) 304{ 305 struct gpiobus_ivar *devi; 306 307 devi = GPIOBUS_IVAR(child); 308 strlcpy(buf, "pin(s)=", buflen); 309 gpiobus_print_pins(devi, buf, buflen); 310 311 return (0); 312} 313 314static int 315gpiobus_child_pnpinfo_str(device_t bus, device_t child, char *buf, 316 size_t buflen) 317{ 318 319 *buf = '\0'; 320 return (0); 321} 322 323static device_t 324gpiobus_add_child(device_t dev, u_int order, const char *name, int unit) 325{ 326 device_t child; 327 struct gpiobus_ivar *devi; 328 329 child = device_add_child_ordered(dev, order, name, unit); 330 if (child == NULL) 331 return (child); 332 devi = malloc(sizeof(struct gpiobus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO); 333 if (devi == NULL) { 334 device_delete_child(dev, child); 335 return (0); 336 } 337 resource_list_init(&devi->rl); 338 device_set_ivars(child, devi); 339 340 return (child); 341} 342 343static void 344gpiobus_hinted_child(device_t bus, const char *dname, int dunit) 345{ 346 struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus); 347 struct gpiobus_ivar *devi; 348 device_t child; 349 int irq, pins; 350 351 child = BUS_ADD_CHILD(bus, 0, dname, dunit); 352 devi = GPIOBUS_IVAR(child); 353 resource_int_value(dname, dunit, "pins", &pins); 354 if (gpiobus_parse_pins(sc, child, pins)) 355 device_delete_child(bus, child); 356 if (resource_int_value(dname, dunit, "irq", &irq) == 0) { 357 if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0) 358 device_printf(bus, 359 "warning: bus_set_resource() failed\n"); 360 } 361} 362 363static int 364gpiobus_set_resource(device_t dev, device_t child, int type, int rid, 365 u_long start, u_long count) 366{ 367 struct gpiobus_ivar *devi; 368 struct resource_list_entry *rle; 369 370 dprintf("%s: entry (%p, %p, %d, %d, %p, %ld)\n", 371 __func__, dev, child, type, rid, (void *)(intptr_t)start, count); 372 devi = GPIOBUS_IVAR(child); 373 rle = resource_list_add(&devi->rl, type, rid, start, 374 start + count - 1, count); 375 if (rle == NULL) 376 return (ENXIO); 377 378 return (0); 379} 380 381static struct resource * 382gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid, 383 u_long start, u_long end, u_long count, u_int flags) 384{ 385 struct gpiobus_softc *sc; 386 struct resource *rv; 387 struct resource_list *rl; 388 struct resource_list_entry *rle; 389 int isdefault; 390 391 if (type != SYS_RES_IRQ) 392 return (NULL); 393 isdefault = (start == 0UL && end == ~0UL && count == 1); 394 rle = NULL; 395 if (isdefault) { 396 rl = BUS_GET_RESOURCE_LIST(bus, child); 397 if (rl == NULL) 398 return (NULL); 399 rle = resource_list_find(rl, type, *rid); 400 if (rle == NULL) 401 return (NULL); 402 if (rle->res != NULL) 403 panic("%s: resource entry is busy", __func__); 404 start = rle->start; 405 count = rle->count; 406 end = rle->end; 407 } 408 sc = device_get_softc(bus); 409 rv = rman_reserve_resource(&sc->sc_intr_rman, start, end, count, flags, 410 child); 411 if (rv == NULL) 412 return (NULL); 413 rman_set_rid(rv, *rid); 414 if ((flags & RF_ACTIVE) != 0 && 415 bus_activate_resource(child, type, *rid, rv) != 0) { 416 rman_release_resource(rv); 417 return (NULL); 418 } 419 420 return (rv); 421} 422 423static int 424gpiobus_release_resource(device_t bus __unused, device_t child, int type, 425 int rid, struct resource *r) 426{ 427 int error; 428 429 if (rman_get_flags(r) & RF_ACTIVE) { 430 error = bus_deactivate_resource(child, type, rid, r); 431 if (error) 432 return (error); 433 } 434 435 return (rman_release_resource(r)); 436} 437 438static struct resource_list * 439gpiobus_get_resource_list(device_t bus __unused, device_t child) 440{ 441 struct gpiobus_ivar *ivar; 442 443 ivar = GPIOBUS_IVAR(child); 444 445 return (&ivar->rl); 446} 447 448static int 449gpiobus_acquire_bus(device_t busdev, device_t child, int how) 450{ 451 struct gpiobus_softc *sc; 452 453 sc = device_get_softc(busdev); 454 GPIOBUS_ASSERT_UNLOCKED(sc); 455 GPIOBUS_LOCK(sc); 456 if (sc->sc_owner != NULL) { 457 if (how == GPIOBUS_DONTWAIT) { 458 GPIOBUS_UNLOCK(sc); 459 return (EWOULDBLOCK); 460 } 461 while (sc->sc_owner != NULL) 462 mtx_sleep(sc, &sc->sc_mtx, 0, "gpiobuswait", 0); 463 } 464 sc->sc_owner = child; 465 GPIOBUS_UNLOCK(sc); 466 467 return (0); 468} 469 470static void 471gpiobus_release_bus(device_t busdev, device_t child) 472{ 473 struct gpiobus_softc *sc; 474 475 sc = device_get_softc(busdev); 476 GPIOBUS_ASSERT_UNLOCKED(sc); 477 GPIOBUS_LOCK(sc); 478 if (sc->sc_owner == NULL) 479 panic("gpiobus: releasing unowned bus."); 480 if (sc->sc_owner != child) 481 panic("gpiobus: you don't own the bus. game over."); 482 sc->sc_owner = NULL; 483 wakeup(sc); 484 GPIOBUS_UNLOCK(sc); 485} 486 487static int 488gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin, 489 uint32_t flags) 490{ 491 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 492 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
| 91static void 92gpiobus_print_pins(struct gpiobus_ivar *devi, char *buf, size_t buflen) 93{ 94 char tmp[128]; 95 int i, range_start, range_stop, need_coma; 96 97 if (devi->npins == 0) 98 return; 99 100 need_coma = 0; 101 range_start = range_stop = devi->pins[0]; 102 for (i = 1; i < devi->npins; i++) { 103 if (devi->pins[i] != (range_stop + 1)) { 104 if (need_coma) 105 strlcat(buf, ",", buflen); 106 memset(tmp, 0, sizeof(tmp)); 107 if (range_start != range_stop) 108 snprintf(tmp, sizeof(tmp) - 1, "%d-%d", 109 range_start, range_stop); 110 else 111 snprintf(tmp, sizeof(tmp) - 1, "%d", 112 range_start); 113 strlcat(buf, tmp, buflen); 114 115 range_start = range_stop = devi->pins[i]; 116 need_coma = 1; 117 } 118 else 119 range_stop++; 120 } 121 122 if (need_coma) 123 strlcat(buf, ",", buflen); 124 memset(tmp, 0, sizeof(tmp)); 125 if (range_start != range_stop) 126 snprintf(tmp, sizeof(tmp) - 1, "%d-%d", 127 range_start, range_stop); 128 else 129 snprintf(tmp, sizeof(tmp) - 1, "%d", 130 range_start); 131 strlcat(buf, tmp, buflen); 132} 133 134int 135gpiobus_init_softc(device_t dev) 136{ 137 struct gpiobus_softc *sc; 138 139 sc = GPIOBUS_SOFTC(dev); 140 sc->sc_busdev = dev; 141 sc->sc_dev = device_get_parent(dev); 142 sc->sc_intr_rman.rm_type = RMAN_ARRAY; 143 sc->sc_intr_rman.rm_descr = "GPIO Interrupts"; 144 if (rman_init(&sc->sc_intr_rman) != 0 || 145 rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0) 146 panic("%s: failed to set up rman.", __func__); 147 148 if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0) 149 return (ENXIO); 150 151 KASSERT(sc->sc_npins != 0, ("GPIO device with no pins")); 152 153 /* Pins = GPIO_PIN_MAX() + 1 */ 154 sc->sc_npins++; 155 156 sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF, 157 M_NOWAIT | M_ZERO); 158 if (sc->sc_pins_mapped == NULL) 159 return (ENOMEM); 160 161 /* Initialize the bus lock. */ 162 GPIOBUS_LOCK_INIT(sc); 163 164 return (0); 165} 166 167static int 168gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask) 169{ 170 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 171 int i, npins; 172 173 npins = 0; 174 for (i = 0; i < 32; i++) { 175 if (mask & (1 << i)) 176 npins++; 177 } 178 179 if (npins == 0) { 180 device_printf(child, "empty pin mask\n"); 181 return (EINVAL); 182 } 183 184 devi->npins = npins; 185 devi->pins = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF, 186 M_NOWAIT | M_ZERO); 187 188 if (!devi->pins) 189 return (ENOMEM); 190 191 npins = 0; 192 for (i = 0; i < 32; i++) { 193 194 if ((mask & (1 << i)) == 0) 195 continue; 196 197 if (i >= sc->sc_npins) { 198 device_printf(child, 199 "invalid pin %d, max: %d\n", i, sc->sc_npins - 1); 200 free(devi->pins, M_DEVBUF); 201 return (EINVAL); 202 } 203 204 devi->pins[npins++] = i; 205 /* 206 * Mark pin as mapped and give warning if it's already mapped 207 */ 208 if (sc->sc_pins_mapped[i]) { 209 device_printf(child, 210 "warning: pin %d is already mapped\n", i); 211 free(devi->pins, M_DEVBUF); 212 return (EINVAL); 213 } 214 sc->sc_pins_mapped[i] = 1; 215 } 216 217 return (0); 218} 219 220static int 221gpiobus_probe(device_t dev) 222{ 223 device_set_desc(dev, "GPIO bus"); 224 225 return (BUS_PROBE_GENERIC); 226} 227 228static int 229gpiobus_attach(device_t dev) 230{ 231 int err; 232 233 err = gpiobus_init_softc(dev); 234 if (err != 0) 235 return (err); 236 237 /* 238 * Get parent's pins and mark them as unmapped 239 */ 240 bus_generic_probe(dev); 241 bus_enumerate_hinted_children(dev); 242 243 return (bus_generic_attach(dev)); 244} 245 246/* 247 * Since this is not a self-enumerating bus, and since we always add 248 * children in attach, we have to always delete children here. 249 */ 250static int 251gpiobus_detach(device_t dev) 252{ 253 struct gpiobus_softc *sc; 254 struct gpiobus_ivar *devi; 255 device_t *devlist; 256 int i, err, ndevs; 257 258 sc = GPIOBUS_SOFTC(dev); 259 KASSERT(mtx_initialized(&sc->sc_mtx), 260 ("gpiobus mutex not initialized")); 261 GPIOBUS_LOCK_DESTROY(sc); 262 263 if ((err = bus_generic_detach(dev)) != 0) 264 return (err); 265 266 if ((err = device_get_children(dev, &devlist, &ndevs)) != 0) 267 return (err); 268 for (i = 0; i < ndevs; i++) { 269 device_delete_child(dev, devlist[i]); 270 devi = GPIOBUS_IVAR(devlist[i]); 271 if (devi->pins) { 272 free(devi->pins, M_DEVBUF); 273 devi->pins = NULL; 274 } 275 } 276 free(devlist, M_TEMP); 277 278 if (sc->sc_pins_mapped) { 279 free(sc->sc_pins_mapped, M_DEVBUF); 280 sc->sc_pins_mapped = NULL; 281 } 282 283 return (0); 284} 285 286static int 287gpiobus_suspend(device_t dev) 288{ 289 290 return (bus_generic_suspend(dev)); 291} 292 293static int 294gpiobus_resume(device_t dev) 295{ 296 297 return (bus_generic_resume(dev)); 298} 299 300static int 301gpiobus_print_child(device_t dev, device_t child) 302{ 303 char pins[128]; 304 int retval = 0; 305 struct gpiobus_ivar *devi; 306 307 devi = GPIOBUS_IVAR(child); 308 memset(pins, 0, sizeof(pins)); 309 retval += bus_print_child_header(dev, child); 310 retval += printf(" at pin(s) "); 311 gpiobus_print_pins(devi, pins, sizeof(pins)); 312 retval += printf("%s", pins); 313 resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld"); 314 retval += bus_print_child_footer(dev, child); 315 316 return (retval); 317} 318 319static int 320gpiobus_child_location_str(device_t bus, device_t child, char *buf, 321 size_t buflen) 322{ 323 struct gpiobus_ivar *devi; 324 325 devi = GPIOBUS_IVAR(child); 326 strlcpy(buf, "pin(s)=", buflen); 327 gpiobus_print_pins(devi, buf, buflen); 328 329 return (0); 330} 331 332static int 333gpiobus_child_pnpinfo_str(device_t bus, device_t child, char *buf, 334 size_t buflen) 335{ 336 337 *buf = '\0'; 338 return (0); 339} 340 341static device_t 342gpiobus_add_child(device_t dev, u_int order, const char *name, int unit) 343{ 344 device_t child; 345 struct gpiobus_ivar *devi; 346 347 child = device_add_child_ordered(dev, order, name, unit); 348 if (child == NULL) 349 return (child); 350 devi = malloc(sizeof(struct gpiobus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO); 351 if (devi == NULL) { 352 device_delete_child(dev, child); 353 return (0); 354 } 355 resource_list_init(&devi->rl); 356 device_set_ivars(child, devi); 357 358 return (child); 359} 360 361static void 362gpiobus_hinted_child(device_t bus, const char *dname, int dunit) 363{ 364 struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus); 365 struct gpiobus_ivar *devi; 366 device_t child; 367 int irq, pins; 368 369 child = BUS_ADD_CHILD(bus, 0, dname, dunit); 370 devi = GPIOBUS_IVAR(child); 371 resource_int_value(dname, dunit, "pins", &pins); 372 if (gpiobus_parse_pins(sc, child, pins)) 373 device_delete_child(bus, child); 374 if (resource_int_value(dname, dunit, "irq", &irq) == 0) { 375 if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0) 376 device_printf(bus, 377 "warning: bus_set_resource() failed\n"); 378 } 379} 380 381static int 382gpiobus_set_resource(device_t dev, device_t child, int type, int rid, 383 u_long start, u_long count) 384{ 385 struct gpiobus_ivar *devi; 386 struct resource_list_entry *rle; 387 388 dprintf("%s: entry (%p, %p, %d, %d, %p, %ld)\n", 389 __func__, dev, child, type, rid, (void *)(intptr_t)start, count); 390 devi = GPIOBUS_IVAR(child); 391 rle = resource_list_add(&devi->rl, type, rid, start, 392 start + count - 1, count); 393 if (rle == NULL) 394 return (ENXIO); 395 396 return (0); 397} 398 399static struct resource * 400gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid, 401 u_long start, u_long end, u_long count, u_int flags) 402{ 403 struct gpiobus_softc *sc; 404 struct resource *rv; 405 struct resource_list *rl; 406 struct resource_list_entry *rle; 407 int isdefault; 408 409 if (type != SYS_RES_IRQ) 410 return (NULL); 411 isdefault = (start == 0UL && end == ~0UL && count == 1); 412 rle = NULL; 413 if (isdefault) { 414 rl = BUS_GET_RESOURCE_LIST(bus, child); 415 if (rl == NULL) 416 return (NULL); 417 rle = resource_list_find(rl, type, *rid); 418 if (rle == NULL) 419 return (NULL); 420 if (rle->res != NULL) 421 panic("%s: resource entry is busy", __func__); 422 start = rle->start; 423 count = rle->count; 424 end = rle->end; 425 } 426 sc = device_get_softc(bus); 427 rv = rman_reserve_resource(&sc->sc_intr_rman, start, end, count, flags, 428 child); 429 if (rv == NULL) 430 return (NULL); 431 rman_set_rid(rv, *rid); 432 if ((flags & RF_ACTIVE) != 0 && 433 bus_activate_resource(child, type, *rid, rv) != 0) { 434 rman_release_resource(rv); 435 return (NULL); 436 } 437 438 return (rv); 439} 440 441static int 442gpiobus_release_resource(device_t bus __unused, device_t child, int type, 443 int rid, struct resource *r) 444{ 445 int error; 446 447 if (rman_get_flags(r) & RF_ACTIVE) { 448 error = bus_deactivate_resource(child, type, rid, r); 449 if (error) 450 return (error); 451 } 452 453 return (rman_release_resource(r)); 454} 455 456static struct resource_list * 457gpiobus_get_resource_list(device_t bus __unused, device_t child) 458{ 459 struct gpiobus_ivar *ivar; 460 461 ivar = GPIOBUS_IVAR(child); 462 463 return (&ivar->rl); 464} 465 466static int 467gpiobus_acquire_bus(device_t busdev, device_t child, int how) 468{ 469 struct gpiobus_softc *sc; 470 471 sc = device_get_softc(busdev); 472 GPIOBUS_ASSERT_UNLOCKED(sc); 473 GPIOBUS_LOCK(sc); 474 if (sc->sc_owner != NULL) { 475 if (how == GPIOBUS_DONTWAIT) { 476 GPIOBUS_UNLOCK(sc); 477 return (EWOULDBLOCK); 478 } 479 while (sc->sc_owner != NULL) 480 mtx_sleep(sc, &sc->sc_mtx, 0, "gpiobuswait", 0); 481 } 482 sc->sc_owner = child; 483 GPIOBUS_UNLOCK(sc); 484 485 return (0); 486} 487 488static void 489gpiobus_release_bus(device_t busdev, device_t child) 490{ 491 struct gpiobus_softc *sc; 492 493 sc = device_get_softc(busdev); 494 GPIOBUS_ASSERT_UNLOCKED(sc); 495 GPIOBUS_LOCK(sc); 496 if (sc->sc_owner == NULL) 497 panic("gpiobus: releasing unowned bus."); 498 if (sc->sc_owner != child) 499 panic("gpiobus: you don't own the bus. game over."); 500 sc->sc_owner = NULL; 501 wakeup(sc); 502 GPIOBUS_UNLOCK(sc); 503} 504 505static int 506gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin, 507 uint32_t flags) 508{ 509 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 510 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
|
498} 499 500static int 501gpiobus_pin_getflags(device_t dev, device_t child, uint32_t pin, 502 uint32_t *flags) 503{ 504 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 505 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 506 507 if (pin >= devi->npins) 508 return (EINVAL); 509 510 return GPIO_PIN_GETFLAGS(sc->sc_dev, devi->pins[pin], flags); 511} 512 513static int 514gpiobus_pin_getcaps(device_t dev, device_t child, uint32_t pin, 515 uint32_t *caps) 516{ 517 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 518 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 519 520 if (pin >= devi->npins) 521 return (EINVAL); 522 523 return GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], caps); 524} 525 526static int 527gpiobus_pin_set(device_t dev, device_t child, uint32_t pin, 528 unsigned int value) 529{ 530 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 531 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 532 533 if (pin >= devi->npins) 534 return (EINVAL); 535 536 return GPIO_PIN_SET(sc->sc_dev, devi->pins[pin], value); 537} 538 539static int 540gpiobus_pin_get(device_t dev, device_t child, uint32_t pin, 541 unsigned int *value) 542{ 543 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 544 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 545 546 if (pin >= devi->npins) 547 return (EINVAL); 548 549 return GPIO_PIN_GET(sc->sc_dev, devi->pins[pin], value); 550} 551 552static int 553gpiobus_pin_toggle(device_t dev, device_t child, uint32_t pin) 554{ 555 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 556 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 557 558 if (pin >= devi->npins) 559 return (EINVAL); 560 561 return GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin]); 562} 563 564static device_method_t gpiobus_methods[] = { 565 /* Device interface */ 566 DEVMETHOD(device_probe, gpiobus_probe), 567 DEVMETHOD(device_attach, gpiobus_attach), 568 DEVMETHOD(device_detach, gpiobus_detach), 569 DEVMETHOD(device_shutdown, bus_generic_shutdown), 570 DEVMETHOD(device_suspend, gpiobus_suspend), 571 DEVMETHOD(device_resume, gpiobus_resume), 572 573 /* Bus interface */ 574 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 575 DEVMETHOD(bus_config_intr, bus_generic_config_intr), 576 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 577 DEVMETHOD(bus_set_resource, gpiobus_set_resource), 578 DEVMETHOD(bus_alloc_resource, gpiobus_alloc_resource), 579 DEVMETHOD(bus_release_resource, gpiobus_release_resource), 580 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 581 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 582 DEVMETHOD(bus_get_resource_list, gpiobus_get_resource_list), 583 DEVMETHOD(bus_add_child, gpiobus_add_child), 584 DEVMETHOD(bus_print_child, gpiobus_print_child), 585 DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str), 586 DEVMETHOD(bus_child_location_str, gpiobus_child_location_str), 587 DEVMETHOD(bus_hinted_child, gpiobus_hinted_child), 588 589 /* GPIO protocol */ 590 DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus), 591 DEVMETHOD(gpiobus_release_bus, gpiobus_release_bus), 592 DEVMETHOD(gpiobus_pin_getflags, gpiobus_pin_getflags), 593 DEVMETHOD(gpiobus_pin_getcaps, gpiobus_pin_getcaps), 594 DEVMETHOD(gpiobus_pin_setflags, gpiobus_pin_setflags), 595 DEVMETHOD(gpiobus_pin_get, gpiobus_pin_get), 596 DEVMETHOD(gpiobus_pin_set, gpiobus_pin_set), 597 DEVMETHOD(gpiobus_pin_toggle, gpiobus_pin_toggle), 598 599 DEVMETHOD_END 600}; 601 602driver_t gpiobus_driver = { 603 "gpiobus", 604 gpiobus_methods, 605 sizeof(struct gpiobus_softc) 606}; 607 608devclass_t gpiobus_devclass; 609 610DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0); 611MODULE_VERSION(gpiobus, 1);
| 521} 522 523static int 524gpiobus_pin_getflags(device_t dev, device_t child, uint32_t pin, 525 uint32_t *flags) 526{ 527 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 528 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 529 530 if (pin >= devi->npins) 531 return (EINVAL); 532 533 return GPIO_PIN_GETFLAGS(sc->sc_dev, devi->pins[pin], flags); 534} 535 536static int 537gpiobus_pin_getcaps(device_t dev, device_t child, uint32_t pin, 538 uint32_t *caps) 539{ 540 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 541 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 542 543 if (pin >= devi->npins) 544 return (EINVAL); 545 546 return GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], caps); 547} 548 549static int 550gpiobus_pin_set(device_t dev, device_t child, uint32_t pin, 551 unsigned int value) 552{ 553 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 554 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 555 556 if (pin >= devi->npins) 557 return (EINVAL); 558 559 return GPIO_PIN_SET(sc->sc_dev, devi->pins[pin], value); 560} 561 562static int 563gpiobus_pin_get(device_t dev, device_t child, uint32_t pin, 564 unsigned int *value) 565{ 566 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 567 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 568 569 if (pin >= devi->npins) 570 return (EINVAL); 571 572 return GPIO_PIN_GET(sc->sc_dev, devi->pins[pin], value); 573} 574 575static int 576gpiobus_pin_toggle(device_t dev, device_t child, uint32_t pin) 577{ 578 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 579 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 580 581 if (pin >= devi->npins) 582 return (EINVAL); 583 584 return GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin]); 585} 586 587static device_method_t gpiobus_methods[] = { 588 /* Device interface */ 589 DEVMETHOD(device_probe, gpiobus_probe), 590 DEVMETHOD(device_attach, gpiobus_attach), 591 DEVMETHOD(device_detach, gpiobus_detach), 592 DEVMETHOD(device_shutdown, bus_generic_shutdown), 593 DEVMETHOD(device_suspend, gpiobus_suspend), 594 DEVMETHOD(device_resume, gpiobus_resume), 595 596 /* Bus interface */ 597 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 598 DEVMETHOD(bus_config_intr, bus_generic_config_intr), 599 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 600 DEVMETHOD(bus_set_resource, gpiobus_set_resource), 601 DEVMETHOD(bus_alloc_resource, gpiobus_alloc_resource), 602 DEVMETHOD(bus_release_resource, gpiobus_release_resource), 603 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 604 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 605 DEVMETHOD(bus_get_resource_list, gpiobus_get_resource_list), 606 DEVMETHOD(bus_add_child, gpiobus_add_child), 607 DEVMETHOD(bus_print_child, gpiobus_print_child), 608 DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str), 609 DEVMETHOD(bus_child_location_str, gpiobus_child_location_str), 610 DEVMETHOD(bus_hinted_child, gpiobus_hinted_child), 611 612 /* GPIO protocol */ 613 DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus), 614 DEVMETHOD(gpiobus_release_bus, gpiobus_release_bus), 615 DEVMETHOD(gpiobus_pin_getflags, gpiobus_pin_getflags), 616 DEVMETHOD(gpiobus_pin_getcaps, gpiobus_pin_getcaps), 617 DEVMETHOD(gpiobus_pin_setflags, gpiobus_pin_setflags), 618 DEVMETHOD(gpiobus_pin_get, gpiobus_pin_get), 619 DEVMETHOD(gpiobus_pin_set, gpiobus_pin_set), 620 DEVMETHOD(gpiobus_pin_toggle, gpiobus_pin_toggle), 621 622 DEVMETHOD_END 623}; 624 625driver_t gpiobus_driver = { 626 "gpiobus", 627 gpiobus_methods, 628 sizeof(struct gpiobus_softc) 629}; 630 631devclass_t gpiobus_devclass; 632 633DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0); 634MODULE_VERSION(gpiobus, 1);
|