diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpiolib.c | 98 |
1 files changed, 67 insertions, 31 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5ca7c9aa4fab..b747c76fd2b1 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -68,6 +68,7 @@ LIST_HEAD(gpio_devices); | |||
68 | static void gpiochip_free_hogs(struct gpio_chip *chip); | 68 | static void gpiochip_free_hogs(struct gpio_chip *chip); |
69 | static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); | 69 | static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); |
70 | 70 | ||
71 | static bool gpiolib_initialized; | ||
71 | 72 | ||
72 | static inline void desc_set_label(struct gpio_desc *d, const char *label) | 73 | static inline void desc_set_label(struct gpio_desc *d, const char *label) |
73 | { | 74 | { |
@@ -445,6 +446,58 @@ static void gpiodevice_release(struct device *dev) | |||
445 | kfree(gdev); | 446 | kfree(gdev); |
446 | } | 447 | } |
447 | 448 | ||
449 | static int gpiochip_setup_dev(struct gpio_device *gdev) | ||
450 | { | ||
451 | int status; | ||
452 | |||
453 | cdev_init(&gdev->chrdev, &gpio_fileops); | ||
454 | gdev->chrdev.owner = THIS_MODULE; | ||
455 | gdev->chrdev.kobj.parent = &gdev->dev.kobj; | ||
456 | gdev->dev.devt = MKDEV(MAJOR(gpio_devt), gdev->id); | ||
457 | status = cdev_add(&gdev->chrdev, gdev->dev.devt, 1); | ||
458 | if (status < 0) | ||
459 | chip_warn(gdev->chip, "failed to add char device %d:%d\n", | ||
460 | MAJOR(gpio_devt), gdev->id); | ||
461 | else | ||
462 | chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n", | ||
463 | MAJOR(gpio_devt), gdev->id); | ||
464 | status = device_add(&gdev->dev); | ||
465 | if (status) | ||
466 | goto err_remove_chardev; | ||
467 | |||
468 | status = gpiochip_sysfs_register(gdev); | ||
469 | if (status) | ||
470 | goto err_remove_device; | ||
471 | |||
472 | /* From this point, the .release() function cleans up gpio_device */ | ||
473 | gdev->dev.release = gpiodevice_release; | ||
474 | get_device(&gdev->dev); | ||
475 | pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n", | ||
476 | __func__, gdev->base, gdev->base + gdev->ngpio - 1, | ||
477 | dev_name(&gdev->dev), gdev->chip->label ? : "generic"); | ||
478 | |||
479 | return 0; | ||
480 | |||
481 | err_remove_device: | ||
482 | device_del(&gdev->dev); | ||
483 | err_remove_chardev: | ||
484 | cdev_del(&gdev->chrdev); | ||
485 | return status; | ||
486 | } | ||
487 | |||
488 | static void gpiochip_setup_devs(void) | ||
489 | { | ||
490 | struct gpio_device *gdev; | ||
491 | int err; | ||
492 | |||
493 | list_for_each_entry(gdev, &gpio_devices, list) { | ||
494 | err = gpiochip_setup_dev(gdev); | ||
495 | if (err) | ||
496 | pr_err("%s: Failed to initialize gpio device (%d)\n", | ||
497 | dev_name(&gdev->dev), err); | ||
498 | } | ||
499 | } | ||
500 | |||
448 | /** | 501 | /** |
449 | * gpiochip_add_data() - register a gpio_chip | 502 | * gpiochip_add_data() - register a gpio_chip |
450 | * @chip: the chip to register, with chip->base initialized | 503 | * @chip: the chip to register, with chip->base initialized |
@@ -459,6 +512,9 @@ static void gpiodevice_release(struct device *dev) | |||
459 | * the gpio framework's arch_initcall(). Otherwise sysfs initialization | 512 | * the gpio framework's arch_initcall(). Otherwise sysfs initialization |
460 | * for GPIOs will fail rudely. | 513 | * for GPIOs will fail rudely. |
461 | * | 514 | * |
515 | * gpiochip_add_data() must only be called after gpiolib initialization, | ||
516 | * ie after core_initcall(). | ||
517 | * | ||
462 | * If chip->base is negative, this requests dynamic assignment of | 518 | * If chip->base is negative, this requests dynamic assignment of |
463 | * a range of valid GPIOs. | 519 | * a range of valid GPIOs. |
464 | */ | 520 | */ |
@@ -515,7 +571,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) | |||
515 | if (chip->ngpio == 0) { | 571 | if (chip->ngpio == 0) { |
516 | chip_err(chip, "tried to insert a GPIO chip with zero lines\n"); | 572 | chip_err(chip, "tried to insert a GPIO chip with zero lines\n"); |
517 | status = -EINVAL; | 573 | status = -EINVAL; |
518 | goto err_free_gdev; | 574 | goto err_free_descs; |
519 | } | 575 | } |
520 | 576 | ||
521 | if (chip->label) | 577 | if (chip->label) |
@@ -597,39 +653,16 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) | |||
597 | * we get a device node entry in sysfs under | 653 | * we get a device node entry in sysfs under |
598 | * /sys/bus/gpio/devices/gpiochipN/dev that can be used for | 654 | * /sys/bus/gpio/devices/gpiochipN/dev that can be used for |
599 | * coldplug of device nodes and other udev business. | 655 | * coldplug of device nodes and other udev business. |
656 | * We can do this only if gpiolib has been initialized. | ||
657 | * Otherwise, defer until later. | ||
600 | */ | 658 | */ |
601 | cdev_init(&gdev->chrdev, &gpio_fileops); | 659 | if (gpiolib_initialized) { |
602 | gdev->chrdev.owner = THIS_MODULE; | 660 | status = gpiochip_setup_dev(gdev); |
603 | gdev->chrdev.kobj.parent = &gdev->dev.kobj; | 661 | if (status) |
604 | gdev->dev.devt = MKDEV(MAJOR(gpio_devt), gdev->id); | 662 | goto err_remove_chip; |
605 | status = cdev_add(&gdev->chrdev, gdev->dev.devt, 1); | 663 | } |
606 | if (status < 0) | ||
607 | chip_warn(chip, "failed to add char device %d:%d\n", | ||
608 | MAJOR(gpio_devt), gdev->id); | ||
609 | else | ||
610 | chip_dbg(chip, "added GPIO chardev (%d:%d)\n", | ||
611 | MAJOR(gpio_devt), gdev->id); | ||
612 | status = device_add(&gdev->dev); | ||
613 | if (status) | ||
614 | goto err_remove_chardev; | ||
615 | |||
616 | status = gpiochip_sysfs_register(gdev); | ||
617 | if (status) | ||
618 | goto err_remove_device; | ||
619 | |||
620 | /* From this point, the .release() function cleans up gpio_device */ | ||
621 | gdev->dev.release = gpiodevice_release; | ||
622 | get_device(&gdev->dev); | ||
623 | pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n", | ||
624 | __func__, gdev->base, gdev->base + gdev->ngpio - 1, | ||
625 | dev_name(&gdev->dev), chip->label ? : "generic"); | ||
626 | |||
627 | return 0; | 664 | return 0; |
628 | 665 | ||
629 | err_remove_device: | ||
630 | device_del(&gdev->dev); | ||
631 | err_remove_chardev: | ||
632 | cdev_del(&gdev->chrdev); | ||
633 | err_remove_chip: | 666 | err_remove_chip: |
634 | acpi_gpiochip_remove(chip); | 667 | acpi_gpiochip_remove(chip); |
635 | gpiochip_free_hogs(chip); | 668 | gpiochip_free_hogs(chip); |
@@ -2842,6 +2875,9 @@ static int __init gpiolib_dev_init(void) | |||
2842 | if (ret < 0) { | 2875 | if (ret < 0) { |
2843 | pr_err("gpiolib: failed to allocate char dev region\n"); | 2876 | pr_err("gpiolib: failed to allocate char dev region\n"); |
2844 | bus_unregister(&gpio_bus_type); | 2877 | bus_unregister(&gpio_bus_type); |
2878 | } else { | ||
2879 | gpiolib_initialized = true; | ||
2880 | gpiochip_setup_devs(); | ||
2845 | } | 2881 | } |
2846 | return ret; | 2882 | return ret; |
2847 | } | 2883 | } |