kernel: bump 4.19 to 4.19.35
[openwrt/openwrt.git] / target / linux / ath79 / patches-4.19 / 0003-leds-add-reset-controller-based-driver.patch
1 From ecbd9c87f073f097d9fe56390353e64e963e866a Mon Sep 17 00:00:00 2001
2 From: John Crispin <john@phrozen.org>
3 Date: Tue, 6 Mar 2018 10:03:03 +0100
4 Subject: [PATCH 03/27] leds: add reset-controller based driver
5
6 Signed-off-by: John Crispin <john@phrozen.org>
7 ---
8 drivers/leds/Kconfig | 11 ++++
9 drivers/leds/Makefile | 1 +
10 drivers/leds/leds-reset.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++
11 3 files changed, 149 insertions(+)
12 create mode 100644 drivers/leds/leds-reset.c
13
14 --- a/drivers/leds/Kconfig
15 +++ b/drivers/leds/Kconfig
16 @@ -756,6 +756,17 @@ config LEDS_NIC78BX
17 To compile this driver as a module, choose M here: the module
18 will be called leds-nic78bx.
19
20 +config LEDS_RESET
21 + tristate "LED support for reset-controller API"
22 + depends on LEDS_CLASS
23 + depends on RESET_CONTROLLER
24 + help
25 + This option enables support for LEDs connected to pins driven by reset
26 + controllers. Yes, DNI actual built HW like that.
27 +
28 + To compile this driver as a module, choose M here: the module
29 + will be called leds-reset.
30 +
31 comment "LED Triggers"
32 source "drivers/leds/trigger/Kconfig"
33
34 --- /dev/null
35 +++ b/drivers/leds/leds-reset.c
36 @@ -0,0 +1,140 @@
37 +/*
38 + * Copyright (C) 2018 John Crispin <john@phrozen.org>
39 + *
40 + * This program is free software; you can redistribute it and/or modify
41 + * it under the terms of the GNU General Public License version 2 as
42 + * published by the Free Software Foundation.
43 + *
44 + */
45 +#include <linux/err.h>
46 +#include <linux/reset.h>
47 +#include <linux/kernel.h>
48 +#include <linux/leds.h>
49 +#include <linux/module.h>
50 +#include <linux/of.h>
51 +#include <linux/platform_device.h>
52 +#include <linux/reset.h>
53 +
54 +struct reset_led_data {
55 + struct led_classdev cdev;
56 + struct reset_control *rst;
57 +};
58 +
59 +static inline struct reset_led_data *
60 + cdev_to_reset_led_data(struct led_classdev *led_cdev)
61 +{
62 + return container_of(led_cdev, struct reset_led_data, cdev);
63 +}
64 +
65 +static void reset_led_set(struct led_classdev *led_cdev,
66 + enum led_brightness value)
67 +{
68 + struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev);
69 +
70 + if (value == LED_OFF)
71 + reset_control_assert(led_dat->rst);
72 + else
73 + reset_control_deassert(led_dat->rst);
74 +}
75 +
76 +struct reset_leds_priv {
77 + int num_leds;
78 + struct reset_led_data leds[];
79 +};
80 +
81 +static inline int sizeof_reset_leds_priv(int num_leds)
82 +{
83 + return sizeof(struct reset_leds_priv) +
84 + (sizeof(struct reset_led_data) * num_leds);
85 +}
86 +
87 +static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev)
88 +{
89 + struct device *dev = &pdev->dev;
90 + struct fwnode_handle *child;
91 + struct reset_leds_priv *priv;
92 + int count, ret;
93 +
94 + count = device_get_child_node_count(dev);
95 + if (!count)
96 + return ERR_PTR(-ENODEV);
97 +
98 + priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL);
99 + if (!priv)
100 + return ERR_PTR(-ENOMEM);
101 +
102 + device_for_each_child_node(dev, child) {
103 + struct reset_led_data *led = &priv->leds[priv->num_leds];
104 + struct device_node *np = to_of_node(child);
105 +
106 + ret = fwnode_property_read_string(child, "label", &led->cdev.name);
107 + if (!led->cdev.name) {
108 + fwnode_handle_put(child);
109 + return ERR_PTR(-EINVAL);
110 + }
111 + led->rst = __of_reset_control_get(np, NULL, 0, 0, 0);
112 + if (IS_ERR(led->rst))
113 + return ERR_PTR(-EINVAL);
114 +
115 + fwnode_property_read_string(child, "linux,default-trigger",
116 + &led->cdev.default_trigger);
117 +
118 + led->cdev.brightness_set = reset_led_set;
119 + ret = devm_of_led_classdev_register(&pdev->dev, np, &led->cdev);
120 + if (ret < 0)
121 + return ERR_PTR(ret);
122 + led->cdev.dev->of_node = np;
123 + priv->num_leds++;
124 + }
125 +
126 + return priv;
127 +}
128 +
129 +static const struct of_device_id of_reset_leds_match[] = {
130 + { .compatible = "reset-leds", },
131 + {},
132 +};
133 +
134 +MODULE_DEVICE_TABLE(of, of_reset_leds_match);
135 +
136 +static int reset_led_probe(struct platform_device *pdev)
137 +{
138 + struct reset_leds_priv *priv;
139 +
140 + priv = reset_leds_create(pdev);
141 + if (IS_ERR(priv))
142 + return PTR_ERR(priv);
143 +
144 + platform_set_drvdata(pdev, priv);
145 +
146 + return 0;
147 +}
148 +
149 +static void reset_led_shutdown(struct platform_device *pdev)
150 +{
151 + struct reset_leds_priv *priv = platform_get_drvdata(pdev);
152 + int i;
153 +
154 + for (i = 0; i < priv->num_leds; i++) {
155 + struct reset_led_data *led = &priv->leds[i];
156 +
157 + if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN))
158 + reset_led_set(&led->cdev, LED_OFF);
159 + }
160 +}
161 +
162 +static struct platform_driver reset_led_driver = {
163 + .probe = reset_led_probe,
164 + .shutdown = reset_led_shutdown,
165 + .driver = {
166 + .name = "leds-reset",
167 + .of_match_table = of_reset_leds_match,
168 + },
169 +};
170 +
171 +module_platform_driver(reset_led_driver);
172 +
173 +MODULE_AUTHOR("John Crispin <john@phrozen.org>");
174 +MODULE_DESCRIPTION("reset controller LED driver");
175 +MODULE_LICENSE("GPL");
176 +MODULE_ALIAS("platform:leds-reset");
177 --- a/drivers/leds/Makefile
178 +++ b/drivers/leds/Makefile
179 @@ -78,6 +78,7 @@ obj-$(CONFIG_LEDS_MT6323) += leds-mt632
180 obj-$(CONFIG_LEDS_LM3692X) += leds-lm3692x.o
181 obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o
182 obj-$(CONFIG_LEDS_LM3601X) += leds-lm3601x.o
183 +obj-$(CONFIG_LEDS_RESET) += leds-reset.o
184
185 # LED SPI Drivers
186 obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o