kernel: properly insert local mtd partition parsers
[oweals/openwrt.git] / target / linux / ath79 / patches-5.4 / 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 @@ -823,6 +823,17 @@ config LEDS_LM36274
17           Say Y to enable the LM36274 LED driver for TI LMU devices.
18           This supports the LED device LM36274.
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, true);
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_led_classdev_register(&pdev->dev, &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 @@ -85,6 +85,7 @@ obj-$(CONFIG_LEDS_LM3601X)            += leds-lm36
180  obj-$(CONFIG_LEDS_TI_LMU_COMMON)       += leds-ti-lmu-common.o
181  obj-$(CONFIG_LEDS_LM3697)              += leds-lm3697.o
182  obj-$(CONFIG_LEDS_LM36274)             += leds-lm36274.o
183 +obj-$(CONFIG_LEDS_RESET)               += leds-reset.o
184  
185  # LED SPI Drivers
186  obj-$(CONFIG_LEDS_CR0014114)           += leds-cr0014114.o