ath79: add WLAN, Ethernet-Switch with LAN/WAN and Status LED to Dorin
[oweals/openwrt.git] / target / linux / ath79 / patches-4.14 / 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 @@ -696,6 +696,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,137 @@
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 +               led->cdev.brightness_set = reset_led_set;
116 +               ret = devm_of_led_classdev_register(&pdev->dev, np, &led->cdev);
117 +               if (ret < 0)
118 +                       return ERR_PTR(ret);
119 +               led->cdev.dev->of_node = np;
120 +               priv->num_leds++;
121 +       }
122 +
123 +       return priv;
124 +}
125 +
126 +static const struct of_device_id of_reset_leds_match[] = {
127 +       { .compatible = "reset-leds", },
128 +       {},
129 +};
130 +
131 +MODULE_DEVICE_TABLE(of, of_reset_leds_match);
132 +
133 +static int reset_led_probe(struct platform_device *pdev)
134 +{
135 +       struct reset_leds_priv *priv;
136 +
137 +       priv = reset_leds_create(pdev);
138 +       if (IS_ERR(priv))
139 +               return PTR_ERR(priv);
140 +
141 +       platform_set_drvdata(pdev, priv);
142 +
143 +       return 0;
144 +}
145 +
146 +static void reset_led_shutdown(struct platform_device *pdev)
147 +{
148 +       struct reset_leds_priv *priv = platform_get_drvdata(pdev);
149 +       int i;
150 +
151 +       for (i = 0; i < priv->num_leds; i++) {
152 +               struct reset_led_data *led = &priv->leds[i];
153 +
154 +               if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN))
155 +                       reset_led_set(&led->cdev, LED_OFF);
156 +       }
157 +}
158 +
159 +static struct platform_driver reset_led_driver = {
160 +       .probe          = reset_led_probe,
161 +       .shutdown       = reset_led_shutdown,
162 +       .driver         = {
163 +               .name   = "leds-reset",
164 +               .of_match_table = of_reset_leds_match,
165 +       },
166 +};
167 +
168 +module_platform_driver(reset_led_driver);
169 +
170 +MODULE_AUTHOR("John Crispin <john@phrozen.org>");
171 +MODULE_DESCRIPTION("reset controller LED driver");
172 +MODULE_LICENSE("GPL");
173 +MODULE_ALIAS("platform:leds-reset");
174 --- a/drivers/leds/Makefile
175 +++ b/drivers/leds/Makefile
176 @@ -73,6 +73,7 @@ obj-$(CONFIG_LEDS_PM8058)             += leds-pm805
177  obj-$(CONFIG_LEDS_MLXCPLD)             += leds-mlxcpld.o
178  obj-$(CONFIG_LEDS_NIC78BX)             += leds-nic78bx.o
179  obj-$(CONFIG_LEDS_MT6323)              += leds-mt6323.o
180 +obj-$(CONFIG_LEDS_RESET)               += leds-reset.o
181  
182  # LED SPI Drivers
183  obj-$(CONFIG_LEDS_DAC124S085)          += leds-dac124s085.o