Merge tag 'rpmsg-v4.9' of git://github.com/andersson/remoteproc
[cascardo/linux.git] / drivers / leds / leds-gpio.c
index 9b991d4..d400dca 100644 (file)
@@ -26,15 +26,19 @@ struct gpio_led_data {
        struct gpio_desc *gpiod;
        u8 can_sleep;
        u8 blinking;
-       int (*platform_gpio_blink_set)(struct gpio_desc *desc, int state,
-                       unsigned long *delay_on, unsigned long *delay_off);
+       gpio_blink_set_t platform_gpio_blink_set;
 };
 
+static inline struct gpio_led_data *
+                       cdev_to_gpio_led_data(struct led_classdev *led_cdev)
+{
+       return container_of(led_cdev, struct gpio_led_data, cdev);
+}
+
 static void gpio_led_set(struct led_classdev *led_cdev,
        enum led_brightness value)
 {
-       struct gpio_led_data *led_dat =
-               container_of(led_cdev, struct gpio_led_data, cdev);
+       struct gpio_led_data *led_dat = cdev_to_gpio_led_data(led_cdev);
        int level;
 
        if (value == LED_OFF)
@@ -64,8 +68,7 @@ static int gpio_led_set_blocking(struct led_classdev *led_cdev,
 static int gpio_blink_set(struct led_classdev *led_cdev,
        unsigned long *delay_on, unsigned long *delay_off)
 {
-       struct gpio_led_data *led_dat =
-               container_of(led_cdev, struct gpio_led_data, cdev);
+       struct gpio_led_data *led_dat = cdev_to_gpio_led_data(led_cdev);
 
        led_dat->blinking = 1;
        return led_dat->platform_gpio_blink_set(led_dat->gpiod, GPIO_LED_BLINK,
@@ -74,8 +77,7 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
 
 static int create_gpio_led(const struct gpio_led *template,
        struct gpio_led_data *led_dat, struct device *parent,
-       int (*blink_set)(struct gpio_desc *, int, unsigned long *,
-                        unsigned long *))
+       gpio_blink_set_t blink_set)
 {
        int ret, state;
 
@@ -120,10 +122,13 @@ static int create_gpio_led(const struct gpio_led *template,
                led_dat->platform_gpio_blink_set = blink_set;
                led_dat->cdev.blink_set = gpio_blink_set;
        }
-       if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
-               state = !!gpiod_get_value_cansleep(led_dat->gpiod);
-       else
+       if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) {
+               state = gpiod_get_value_cansleep(led_dat->gpiod);
+               if (state < 0)
+                       return state;
+       } else {
                state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
+       }
        led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
        if (!template->retain_state_suspended)
                led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
@@ -134,7 +139,7 @@ static int create_gpio_led(const struct gpio_led *template,
        if (ret < 0)
                return ret;
 
-       return led_classdev_register(parent, &led_dat->cdev);
+       return devm_led_classdev_register(parent, &led_dat->cdev);
 }
 
 struct gpio_leds_priv {
@@ -154,7 +159,6 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
        struct fwnode_handle *child;
        struct gpio_leds_priv *priv;
        int count, ret;
-       struct device_node *np;
 
        count = device_get_child_node_count(dev);
        if (!count)
@@ -168,26 +172,22 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
                struct gpio_led_data *led_dat = &priv->leds[priv->num_leds];
                struct gpio_led led = {};
                const char *state = NULL;
+               struct device_node *np = to_of_node(child);
 
                led.gpiod = devm_get_gpiod_from_child(dev, NULL, child);
                if (IS_ERR(led.gpiod)) {
                        fwnode_handle_put(child);
-                       ret = PTR_ERR(led.gpiod);
-                       goto err;
+                       return ERR_CAST(led.gpiod);
                }
 
-               np = to_of_node(child);
-
-               if (fwnode_property_present(child, "label")) {
-                       fwnode_property_read_string(child, "label", &led.name);
-               } else {
-                       if (IS_ENABLED(CONFIG_OF) && !led.name && np)
-                               led.name = np->name;
-                       if (!led.name) {
-                               ret = -EINVAL;
-                               goto err;
-                       }
+               ret = fwnode_property_read_string(child, "label", &led.name);
+               if (ret && IS_ENABLED(CONFIG_OF) && np)
+                       led.name = np->name;
+               if (!led.name) {
+                       fwnode_handle_put(child);
+                       return ERR_PTR(-EINVAL);
                }
+
                fwnode_property_read_string(child, "linux,default-trigger",
                                            &led.default_trigger);
 
@@ -209,18 +209,13 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
                ret = create_gpio_led(&led, led_dat, dev, NULL);
                if (ret < 0) {
                        fwnode_handle_put(child);
-                       goto err;
+                       return ERR_PTR(ret);
                }
                led_dat->cdev.dev->of_node = np;
                priv->num_leds++;
        }
 
        return priv;
-
-err:
-       for (count = priv->num_leds - 1; count >= 0; count--)
-               led_classdev_unregister(&priv->leds[count].cdev);
-       return ERR_PTR(ret);
 }
 
 static const struct of_device_id of_gpio_leds_match[] = {
@@ -248,13 +243,8 @@ static int gpio_led_probe(struct platform_device *pdev)
                        ret = create_gpio_led(&pdata->leds[i],
                                              &priv->leds[i],
                                              &pdev->dev, pdata->gpio_blink_set);
-                       if (ret < 0) {
-                               /* On failure: unwind the led creations */
-                               for (i = i - 1; i >= 0; i--)
-                                       led_classdev_unregister(
-                                                       &priv->leds[i].cdev);
+                       if (ret < 0)
                                return ret;
-                       }
                }
        } else {
                priv = gpio_leds_create(pdev);
@@ -267,17 +257,6 @@ static int gpio_led_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int gpio_led_remove(struct platform_device *pdev)
-{
-       struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < priv->num_leds; i++)
-               led_classdev_unregister(&priv->leds[i].cdev);
-
-       return 0;
-}
-
 static void gpio_led_shutdown(struct platform_device *pdev)
 {
        struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
@@ -292,7 +271,6 @@ static void gpio_led_shutdown(struct platform_device *pdev)
 
 static struct platform_driver gpio_led_driver = {
        .probe          = gpio_led_probe,
-       .remove         = gpio_led_remove,
        .shutdown       = gpio_led_shutdown,
        .driver         = {
                .name   = "leds-gpio",