From: Rafał Miłecki Date: Wed, 8 Mar 2017 11:38:43 +0000 (+0100) Subject: kernel: fix of_node handling in LEDs core code X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=318f2d61016e69206ab9ec63017eb47e246c0b75;p=openwrt%2Fstaging%2Fkaloz.git kernel: fix of_node handling in LEDs core code This backports fixes for setting of_node and making it possible to read extra info from DT. This was partially fixed by: [PATCH] leds: leds-gpio: Set of_node for created LED devices but it didn't work during initialization. Signed-off-by: Rafał Miłecki --- diff --git a/target/linux/generic/patches-4.4/085-0002-leds-gpio-introduce-gpio_blink_set_t.patch b/target/linux/generic/patches-4.4/085-0002-leds-gpio-introduce-gpio_blink_set_t.patch new file mode 100644 index 0000000000..670d4ba91f --- /dev/null +++ b/target/linux/generic/patches-4.4/085-0002-leds-gpio-introduce-gpio_blink_set_t.patch @@ -0,0 +1,61 @@ +From 68620e594c250ba8c43a78e77f5296cb9952582e Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Wed, 14 Sep 2016 20:54:12 +0200 +Subject: [PATCH] leds: gpio: introduce gpio_blink_set_t + +Introduce a typedef gpio_blink_set_t to improve readability of the code. + +Signed-off-by: Heiner Kallweit +Signed-off-by: Jacek Anaszewski +--- + drivers/leds/leds-gpio.c | 6 ++---- + include/linux/leds.h | 9 ++++++--- + 2 files changed, 8 insertions(+), 7 deletions(-) + +--- a/drivers/leds/leds-gpio.c ++++ b/drivers/leds/leds-gpio.c +@@ -29,8 +29,7 @@ struct gpio_led_data { + u8 new_level; + 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 void gpio_led_work(struct work_struct *work) +@@ -88,8 +87,7 @@ static int gpio_blink_set(struct led_cla + + 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; + +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -330,6 +330,11 @@ struct led_platform_data { + struct led_info *leds; + }; + ++struct gpio_desc; ++typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state, ++ unsigned long *delay_on, ++ unsigned long *delay_off); ++ + /* For the leds-gpio driver */ + struct gpio_led { + const char *name; +@@ -352,9 +357,7 @@ struct gpio_led_platform_data { + #define GPIO_LED_NO_BLINK_LOW 0 /* No blink GPIO state low */ + #define GPIO_LED_NO_BLINK_HIGH 1 /* No blink GPIO state high */ + #define GPIO_LED_BLINK 2 /* Please, blink */ +- int (*gpio_blink_set)(struct gpio_desc *desc, int state, +- unsigned long *delay_on, +- unsigned long *delay_off); ++ gpio_blink_set_t gpio_blink_set; + }; + + struct platform_device *gpio_led_register_device( diff --git a/target/linux/generic/patches-4.4/085-0003-leds-gpio-switch-to-managed-version-of-led_classdev_.patch b/target/linux/generic/patches-4.4/085-0003-leds-gpio-switch-to-managed-version-of-led_classdev_.patch new file mode 100644 index 0000000000..7aa865aa83 --- /dev/null +++ b/target/linux/generic/patches-4.4/085-0003-leds-gpio-switch-to-managed-version-of-led_classdev_.patch @@ -0,0 +1,75 @@ +From bc2c0dd85a0a31505ca2f92bef891ddac9126725 Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Wed, 14 Sep 2016 20:55:27 +0200 +Subject: [PATCH] leds: gpio: switch to managed version of + led_classdev_register + +Using the managed version of led_classdev_register allows to +significantly simplify the code. + +Signed-off-by: Heiner Kallweit +Signed-off-by: Jacek Anaszewski +--- + drivers/leds/leds-gpio.c | 23 ++--------------------- + 1 file changed, 2 insertions(+), 21 deletions(-) + +--- a/drivers/leds/leds-gpio.c ++++ b/drivers/leds/leds-gpio.c +@@ -143,7 +143,7 @@ static int create_gpio_led(const struct + + INIT_WORK(&led_dat->work, gpio_led_work); + +- return led_classdev_register(parent, &led_dat->cdev); ++ return devm_led_classdev_register(parent, &led_dat->cdev); + } + + static void delete_gpio_led(struct gpio_led_data *led) +@@ -231,8 +231,6 @@ static struct gpio_leds_priv *gpio_leds_ + return priv; + + err: +- for (count = priv->num_leds - 1; count >= 0; count--) +- delete_gpio_led(&priv->leds[count]); + return ERR_PTR(ret); + } + +@@ -261,12 +259,8 @@ static int gpio_led_probe(struct platfor + 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--) +- delete_gpio_led(&priv->leds[i]); ++ if (ret < 0) + return ret; +- } + } + } else { + priv = gpio_leds_create(pdev); +@@ -279,17 +273,6 @@ static int gpio_led_probe(struct platfor + 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++) +- delete_gpio_led(&priv->leds[i]); +- +- return 0; +-} +- + static void gpio_led_shutdown(struct platform_device *pdev) + { + struct gpio_leds_priv *priv = platform_get_drvdata(pdev); +@@ -304,7 +287,6 @@ static void gpio_led_shutdown(struct pla + + static struct platform_driver gpio_led_driver = { + .probe = gpio_led_probe, +- .remove = gpio_led_remove, + .shutdown = gpio_led_shutdown, + .driver = { + .name = "leds-gpio", diff --git a/target/linux/generic/patches-4.4/085-0004-leds-core-add-OF-variants-of-LED-registering-functio.patch b/target/linux/generic/patches-4.4/085-0004-leds-core-add-OF-variants-of-LED-registering-functio.patch new file mode 100644 index 0000000000..e02984041a --- /dev/null +++ b/target/linux/generic/patches-4.4/085-0004-leds-core-add-OF-variants-of-LED-registering-functio.patch @@ -0,0 +1,120 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 6 Mar 2017 06:19:44 +0100 +Subject: [PATCH] leds: core: add OF variants of LED registering functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These new functions allow passing an additional device_node argument +that will be internally set for created LED device. Thanks to this LED +core code and triggers will be able to access DT node for reading extra +info. + +The easiest solution for achieving this was reworking old functions to +more generic ones & adding simple defines for API compatibility. + +Signed-off-by: Rafał Miłecki +Acked-by: Pavel Machek +Signed-off-by: Jacek Anaszewski +--- + drivers/leds/led-class.c | 26 ++++++++++++++++---------- + include/linux/leds.h | 14 ++++++++++---- + 2 files changed, 26 insertions(+), 14 deletions(-) + +--- a/drivers/leds/led-class.c ++++ b/drivers/leds/led-class.c +@@ -181,11 +181,14 @@ static int led_classdev_next_name(const + } + + /** +- * led_classdev_register - register a new object of led_classdev class. +- * @parent: The device to register. ++ * of_led_classdev_register - register a new object of led_classdev class. ++ * ++ * @parent: parent of LED device + * @led_cdev: the led_classdev structure for this device. ++ * @np: DT node describing this LED + */ +-int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) ++int of_led_classdev_register(struct device *parent, struct device_node *np, ++ struct led_classdev *led_cdev) + { + char name[64]; + int ret; +@@ -198,6 +201,7 @@ int led_classdev_register(struct device + led_cdev, led_cdev->groups, "%s", name); + if (IS_ERR(led_cdev->dev)) + return PTR_ERR(led_cdev->dev); ++ led_cdev->dev->of_node = np; + + if (ret) + dev_warn(parent, "Led %s renamed to %s due to name collision", +@@ -230,7 +234,7 @@ int led_classdev_register(struct device + + return 0; + } +-EXPORT_SYMBOL_GPL(led_classdev_register); ++EXPORT_SYMBOL_GPL(of_led_classdev_register); + + /** + * led_classdev_unregister - unregisters a object of led_properties class. +@@ -269,12 +273,14 @@ static void devm_led_classdev_release(st + } + + /** +- * devm_led_classdev_register - resource managed led_classdev_register() +- * @parent: The device to register. ++ * devm_of_led_classdev_register - resource managed led_classdev_register() ++ * ++ * @parent: parent of LED device + * @led_cdev: the led_classdev structure for this device. + */ +-int devm_led_classdev_register(struct device *parent, +- struct led_classdev *led_cdev) ++int devm_of_led_classdev_register(struct device *parent, ++ struct device_node *np, ++ struct led_classdev *led_cdev) + { + struct led_classdev **dr; + int rc; +@@ -283,7 +289,7 @@ int devm_led_classdev_register(struct de + if (!dr) + return -ENOMEM; + +- rc = led_classdev_register(parent, led_cdev); ++ rc = of_led_classdev_register(parent, np, led_cdev); + if (rc) { + devres_free(dr); + return rc; +@@ -294,7 +300,7 @@ int devm_led_classdev_register(struct de + + return 0; + } +-EXPORT_SYMBOL_GPL(devm_led_classdev_register); ++EXPORT_SYMBOL_GPL(devm_of_led_classdev_register); + + static int devm_led_classdev_match(struct device *dev, void *res, void *data) + { +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -103,10 +103,16 @@ struct led_classdev { + struct mutex led_access; + }; + +-extern int led_classdev_register(struct device *parent, +- struct led_classdev *led_cdev); +-extern int devm_led_classdev_register(struct device *parent, +- struct led_classdev *led_cdev); ++extern int of_led_classdev_register(struct device *parent, ++ struct device_node *np, ++ struct led_classdev *led_cdev); ++#define led_classdev_register(parent, led_cdev) \ ++ of_led_classdev_register(parent, NULL, led_cdev) ++extern int devm_of_led_classdev_register(struct device *parent, ++ struct device_node *np, ++ struct led_classdev *led_cdev); ++#define devm_led_classdev_register(parent, led_cdev) \ ++ devm_of_led_classdev_register(parent, NULL, led_cdev) + extern void led_classdev_unregister(struct led_classdev *led_cdev); + extern void devm_led_classdev_unregister(struct device *parent, + struct led_classdev *led_cdev); diff --git a/target/linux/generic/patches-4.4/085-0005-leds-gpio-use-OF-variant-of-LED-registering-function.patch b/target/linux/generic/patches-4.4/085-0005-leds-gpio-use-OF-variant-of-LED-registering-function.patch new file mode 100644 index 0000000000..159fae84f4 --- /dev/null +++ b/target/linux/generic/patches-4.4/085-0005-leds-gpio-use-OF-variant-of-LED-registering-function.patch @@ -0,0 +1,60 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 6 Mar 2017 06:19:45 +0100 +Subject: [PATCH] leds: gpio: use OF variant of LED registering function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In leds-gpio we support LEDs specified in DT so we should use +(devm_)of_led_classdev_register. This allows passing DT node as argument +for use by the LED subsystem. + +Signed-off-by: Rafał Miłecki +Acked-by: Pavel Machek +Signed-off-by: Jacek Anaszewski +--- + drivers/leds/leds-gpio.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/leds/leds-gpio.c ++++ b/drivers/leds/leds-gpio.c +@@ -87,7 +87,7 @@ static int gpio_blink_set(struct led_cla + + static int create_gpio_led(const struct gpio_led *template, + struct gpio_led_data *led_dat, struct device *parent, +- gpio_blink_set_t blink_set) ++ struct device_node *np, gpio_blink_set_t blink_set) + { + int ret, state; + +@@ -143,7 +143,7 @@ static int create_gpio_led(const struct + + INIT_WORK(&led_dat->work, gpio_led_work); + +- return devm_led_classdev_register(parent, &led_dat->cdev); ++ return devm_of_led_classdev_register(parent, np, &led_dat->cdev); + } + + static void delete_gpio_led(struct gpio_led_data *led) +@@ -219,7 +219,7 @@ static struct gpio_leds_priv *gpio_leds_ + if (fwnode_property_present(child, "retain-state-suspended")) + led.retain_state_suspended = 1; + +- ret = create_gpio_led(&led, led_dat, dev, NULL); ++ ret = create_gpio_led(&led, led_dat, dev, np, NULL); + if (ret < 0) { + fwnode_handle_put(child); + goto err; +@@ -256,9 +256,9 @@ static int gpio_led_probe(struct platfor + + priv->num_leds = pdata->num_leds; + for (i = 0; i < priv->num_leds; i++) { +- ret = create_gpio_led(&pdata->leds[i], +- &priv->leds[i], +- &pdev->dev, pdata->gpio_blink_set); ++ ret = create_gpio_led(&pdata->leds[i], &priv->leds[i], ++ &pdev->dev, NULL, ++ pdata->gpio_blink_set); + if (ret < 0) + return ret; + } diff --git a/target/linux/generic/patches-4.9/080-0001-leds-core-add-OF-variants-of-LED-registering-functio.patch b/target/linux/generic/patches-4.9/080-0001-leds-core-add-OF-variants-of-LED-registering-functio.patch new file mode 100644 index 0000000000..5b1b307aec --- /dev/null +++ b/target/linux/generic/patches-4.9/080-0001-leds-core-add-OF-variants-of-LED-registering-functio.patch @@ -0,0 +1,120 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 6 Mar 2017 06:19:44 +0100 +Subject: [PATCH] leds: core: add OF variants of LED registering functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These new functions allow passing an additional device_node argument +that will be internally set for created LED device. Thanks to this LED +core code and triggers will be able to access DT node for reading extra +info. + +The easiest solution for achieving this was reworking old functions to +more generic ones & adding simple defines for API compatibility. + +Signed-off-by: Rafał Miłecki +Acked-by: Pavel Machek +Signed-off-by: Jacek Anaszewski +--- + drivers/leds/led-class.c | 26 ++++++++++++++++---------- + include/linux/leds.h | 14 ++++++++++---- + 2 files changed, 26 insertions(+), 14 deletions(-) + +--- a/drivers/leds/led-class.c ++++ b/drivers/leds/led-class.c +@@ -181,11 +181,14 @@ static int led_classdev_next_name(const + } + + /** +- * led_classdev_register - register a new object of led_classdev class. +- * @parent: The device to register. ++ * of_led_classdev_register - register a new object of led_classdev class. ++ * ++ * @parent: parent of LED device + * @led_cdev: the led_classdev structure for this device. ++ * @np: DT node describing this LED + */ +-int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) ++int of_led_classdev_register(struct device *parent, struct device_node *np, ++ struct led_classdev *led_cdev) + { + char name[64]; + int ret; +@@ -198,6 +201,7 @@ int led_classdev_register(struct device + led_cdev, led_cdev->groups, "%s", name); + if (IS_ERR(led_cdev->dev)) + return PTR_ERR(led_cdev->dev); ++ led_cdev->dev->of_node = np; + + if (ret) + dev_warn(parent, "Led %s renamed to %s due to name collision", +@@ -228,7 +232,7 @@ int led_classdev_register(struct device + + return 0; + } +-EXPORT_SYMBOL_GPL(led_classdev_register); ++EXPORT_SYMBOL_GPL(of_led_classdev_register); + + /** + * led_classdev_unregister - unregisters a object of led_properties class. +@@ -270,12 +274,14 @@ static void devm_led_classdev_release(st + } + + /** +- * devm_led_classdev_register - resource managed led_classdev_register() +- * @parent: The device to register. ++ * devm_of_led_classdev_register - resource managed led_classdev_register() ++ * ++ * @parent: parent of LED device + * @led_cdev: the led_classdev structure for this device. + */ +-int devm_led_classdev_register(struct device *parent, +- struct led_classdev *led_cdev) ++int devm_of_led_classdev_register(struct device *parent, ++ struct device_node *np, ++ struct led_classdev *led_cdev) + { + struct led_classdev **dr; + int rc; +@@ -284,7 +290,7 @@ int devm_led_classdev_register(struct de + if (!dr) + return -ENOMEM; + +- rc = led_classdev_register(parent, led_cdev); ++ rc = of_led_classdev_register(parent, np, led_cdev); + if (rc) { + devres_free(dr); + return rc; +@@ -295,7 +301,7 @@ int devm_led_classdev_register(struct de + + return 0; + } +-EXPORT_SYMBOL_GPL(devm_led_classdev_register); ++EXPORT_SYMBOL_GPL(devm_of_led_classdev_register); + + static int devm_led_classdev_match(struct device *dev, void *res, void *data) + { +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -109,10 +109,16 @@ struct led_classdev { + struct mutex led_access; + }; + +-extern int led_classdev_register(struct device *parent, +- struct led_classdev *led_cdev); +-extern int devm_led_classdev_register(struct device *parent, +- struct led_classdev *led_cdev); ++extern int of_led_classdev_register(struct device *parent, ++ struct device_node *np, ++ struct led_classdev *led_cdev); ++#define led_classdev_register(parent, led_cdev) \ ++ of_led_classdev_register(parent, NULL, led_cdev) ++extern int devm_of_led_classdev_register(struct device *parent, ++ struct device_node *np, ++ struct led_classdev *led_cdev); ++#define devm_led_classdev_register(parent, led_cdev) \ ++ devm_of_led_classdev_register(parent, NULL, led_cdev) + extern void led_classdev_unregister(struct led_classdev *led_cdev); + extern void devm_led_classdev_unregister(struct device *parent, + struct led_classdev *led_cdev); diff --git a/target/linux/generic/patches-4.9/080-0002-leds-gpio-use-OF-variant-of-LED-registering-function.patch b/target/linux/generic/patches-4.9/080-0002-leds-gpio-use-OF-variant-of-LED-registering-function.patch new file mode 100644 index 0000000000..0247fffb2a --- /dev/null +++ b/target/linux/generic/patches-4.9/080-0002-leds-gpio-use-OF-variant-of-LED-registering-function.patch @@ -0,0 +1,60 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 6 Mar 2017 06:19:45 +0100 +Subject: [PATCH] leds: gpio: use OF variant of LED registering function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In leds-gpio we support LEDs specified in DT so we should use +(devm_)of_led_classdev_register. This allows passing DT node as argument +for use by the LED subsystem. + +Signed-off-by: Rafał Miłecki +Acked-by: Pavel Machek +Signed-off-by: Jacek Anaszewski +--- + drivers/leds/leds-gpio.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/leds/leds-gpio.c ++++ b/drivers/leds/leds-gpio.c +@@ -77,7 +77,7 @@ static int gpio_blink_set(struct led_cla + + static int create_gpio_led(const struct gpio_led *template, + struct gpio_led_data *led_dat, struct device *parent, +- gpio_blink_set_t blink_set) ++ struct device_node *np, gpio_blink_set_t blink_set) + { + int ret, state; + +@@ -139,7 +139,7 @@ static int create_gpio_led(const struct + if (ret < 0) + return ret; + +- return devm_led_classdev_register(parent, &led_dat->cdev); ++ return devm_of_led_classdev_register(parent, np, &led_dat->cdev); + } + + struct gpio_leds_priv { +@@ -206,7 +206,7 @@ static struct gpio_leds_priv *gpio_leds_ + if (fwnode_property_present(child, "panic-indicator")) + led.panic_indicator = 1; + +- ret = create_gpio_led(&led, led_dat, dev, NULL); ++ ret = create_gpio_led(&led, led_dat, dev, np, NULL); + if (ret < 0) { + fwnode_handle_put(child); + return ERR_PTR(ret); +@@ -240,9 +240,9 @@ static int gpio_led_probe(struct platfor + + priv->num_leds = pdata->num_leds; + for (i = 0; i < priv->num_leds; i++) { +- ret = create_gpio_led(&pdata->leds[i], +- &priv->leds[i], +- &pdev->dev, pdata->gpio_blink_set); ++ ret = create_gpio_led(&pdata->leds[i], &priv->leds[i], ++ &pdev->dev, NULL, ++ pdata->gpio_blink_set); + if (ret < 0) + return ret; + }