aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Shiyan <shc_work@mail.ru>2014-02-01 01:37:23 -0500
committerBryan Wu <cooloney@gmail.com>2014-02-27 12:56:56 -0500
commit25c6579f872d0542809067d56fad22984b8ff565 (patch)
treebfcdc2a70f81c0c435bd5f3172d3b4024f92c171
parent2f18f8d638cc66a5339d901dea2c9d8af72e69c2 (diff)
leds: leds-mc13783: Add devicetree support
This patch adds devicetree support for the MC13XXX LED driver. (cooloney@gmail.com: remove unneeded semicolon) Signed-off-by: Alexander Shiyan <shc_work@mail.ru> Signed-off-by: Bryan Wu <cooloney@gmail.com>
-rw-r--r--Documentation/devicetree/bindings/mfd/mc13xxx.txt47
-rw-r--r--drivers/leds/leds-mc13783.c112
2 files changed, 140 insertions, 19 deletions
diff --git a/Documentation/devicetree/bindings/mfd/mc13xxx.txt b/Documentation/devicetree/bindings/mfd/mc13xxx.txt
index abd9e3cb2db7..1413f39912d3 100644
--- a/Documentation/devicetree/bindings/mfd/mc13xxx.txt
+++ b/Documentation/devicetree/bindings/mfd/mc13xxx.txt
@@ -10,9 +10,44 @@ Optional properties:
10- fsl,mc13xxx-uses-touch : Indicate the touchscreen controller is being used 10- fsl,mc13xxx-uses-touch : Indicate the touchscreen controller is being used
11 11
12Sub-nodes: 12Sub-nodes:
13- leds : Contain the led nodes and initial register values in property
14 "led-control". Number of register depends of used IC, for MC13783 is 6,
15 for MC13892 is 4, for MC34708 is 1. See datasheet for bits definitions of
16 these registers.
17 - #address-cells: Must be 1.
18 - #size-cells: Must be 0.
19 Each led node should contain "reg", which used as LED ID (described below).
20 Optional properties "label" and "linux,default-trigger" is described in
21 Documentation/devicetree/bindings/leds/common.txt.
13- regulators : Contain the regulator nodes. The regulators are bound using 22- regulators : Contain the regulator nodes. The regulators are bound using
14 their names as listed below with their registers and bits for enabling. 23 their names as listed below with their registers and bits for enabling.
15 24
25MC13783 LED IDs:
26 0 : Main display
27 1 : AUX display
28 2 : Keypad
29 3 : Red 1
30 4 : Green 1
31 5 : Blue 1
32 6 : Red 2
33 7 : Green 2
34 8 : Blue 2
35 9 : Red 3
36 10 : Green 3
37 11 : Blue 3
38
39MC13892 LED IDs:
40 0 : Main display
41 1 : AUX display
42 2 : Keypad
43 3 : Red
44 4 : Green
45 5 : Blue
46
47MC34708 LED IDs:
48 0 : Charger Red
49 1 : Charger Green
50
16MC13783 regulators: 51MC13783 regulators:
17 sw1a : regulator SW1A (register 24, bit 0) 52 sw1a : regulator SW1A (register 24, bit 0)
18 sw1b : regulator SW1B (register 25, bit 0) 53 sw1b : regulator SW1B (register 25, bit 0)
@@ -89,6 +124,18 @@ ecspi@70010000 { /* ECSPI1 */
89 interrupt-parent = <&gpio0>; 124 interrupt-parent = <&gpio0>;
90 interrupts = <8>; 125 interrupts = <8>;
91 126
127 leds {
128 #address-cells = <1>;
129 #size-cells = <0>;
130 led-control = <0x000 0x000 0x0e0 0x000>;
131
132 sysled {
133 reg = <3>;
134 label = "system:red:live";
135 linux,default-trigger = "heartbeat";
136 };
137 };
138
92 regulators { 139 regulators {
93 sw1_reg: mc13892__sw1 { 140 sw1_reg: mc13892__sw1 {
94 regulator-min-microvolt = <600000>; 141 regulator-min-microvolt = <600000>;
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index 15fa5e86abcf..021adc11162e 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -20,6 +20,7 @@
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/leds.h> 22#include <linux/leds.h>
23#include <linux/of.h>
23#include <linux/workqueue.h> 24#include <linux/workqueue.h>
24#include <linux/mfd/mc13xxx.h> 25#include <linux/mfd/mc13xxx.h>
25 26
@@ -42,7 +43,7 @@ struct mc13xxx_leds {
42 struct mc13xxx *master; 43 struct mc13xxx *master;
43 struct mc13xxx_led_devtype *devtype; 44 struct mc13xxx_led_devtype *devtype;
44 int num_leds; 45 int num_leds;
45 struct mc13xxx_led led[0]; 46 struct mc13xxx_led *led;
46}; 47};
47 48
48static unsigned int mc13xxx_max_brightness(int id) 49static unsigned int mc13xxx_max_brightness(int id)
@@ -120,6 +121,74 @@ static void mc13xxx_led_set(struct led_classdev *led_cdev,
120 schedule_work(&led->work); 121 schedule_work(&led->work);
121} 122}
122 123
124#ifdef CONFIG_OF
125static struct mc13xxx_leds_platform_data __init *mc13xxx_led_probe_dt(
126 struct platform_device *pdev)
127{
128 struct mc13xxx_leds *leds = platform_get_drvdata(pdev);
129 struct mc13xxx_leds_platform_data *pdata;
130 struct device_node *parent, *child;
131 struct device *dev = &pdev->dev;
132 int i = 0, ret = -ENODATA;
133
134 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
135 if (!pdata)
136 return ERR_PTR(-ENOMEM);
137
138 of_node_get(dev->parent->of_node);
139
140 parent = of_find_node_by_name(dev->parent->of_node, "leds");
141 if (!parent)
142 goto out_node_put;
143
144 ret = of_property_read_u32_array(parent, "led-control",
145 pdata->led_control,
146 leds->devtype->num_regs);
147 if (ret)
148 goto out_node_put;
149
150 pdata->num_leds = of_get_child_count(parent);
151
152 pdata->led = devm_kzalloc(dev, pdata->num_leds * sizeof(*pdata->led),
153 GFP_KERNEL);
154 if (!pdata->led) {
155 ret = -ENOMEM;
156 goto out_node_put;
157 }
158
159 for_each_child_of_node(parent, child) {
160 const char *str;
161 u32 tmp;
162
163 if (of_property_read_u32(child, "reg", &tmp))
164 continue;
165 pdata->led[i].id = leds->devtype->led_min + tmp;
166
167 if (!of_property_read_string(child, "label", &str))
168 pdata->led[i].name = str;
169 if (!of_property_read_string(child, "linux,default-trigger",
170 &str))
171 pdata->led[i].default_trigger = str;
172
173 i++;
174 }
175
176 pdata->num_leds = i;
177 ret = i > 0 ? 0 : -ENODATA;
178
179out_node_put:
180 of_node_put(parent);
181
182 return ret ? ERR_PTR(ret) : pdata;
183}
184#else
185static inline struct mc13xxx_leds_platform_data __init *mc13xxx_led_probe_dt(
186 struct platform_device *pdev)
187{
188 return ERR_PTR(-ENOSYS);
189}
190#endif
191
123static int __init mc13xxx_led_probe(struct platform_device *pdev) 192static int __init mc13xxx_led_probe(struct platform_device *pdev)
124{ 193{
125 struct device *dev = &pdev->dev; 194 struct device *dev = &pdev->dev;
@@ -128,32 +197,37 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
128 struct mc13xxx_led_devtype *devtype = 197 struct mc13xxx_led_devtype *devtype =
129 (struct mc13xxx_led_devtype *)pdev->id_entry->driver_data; 198 (struct mc13xxx_led_devtype *)pdev->id_entry->driver_data;
130 struct mc13xxx_leds *leds; 199 struct mc13xxx_leds *leds;
131 int i, id, num_leds, ret = -ENODATA; 200 int i, id, ret = -ENODATA;
132 u32 init_led = 0; 201 u32 init_led = 0;
133 202
134 if (!pdata) { 203 leds = devm_kzalloc(dev, sizeof(*leds), GFP_KERNEL);
135 dev_err(dev, "Missing platform data\n");
136 return -ENODEV;
137 }
138
139 num_leds = pdata->num_leds;
140
141 if ((num_leds < 1) ||
142 (num_leds > (devtype->led_max - devtype->led_min + 1))) {
143 dev_err(dev, "Invalid LED count %d\n", num_leds);
144 return -EINVAL;
145 }
146
147 leds = devm_kzalloc(dev, num_leds * sizeof(struct mc13xxx_led) +
148 sizeof(struct mc13xxx_leds), GFP_KERNEL);
149 if (!leds) 204 if (!leds)
150 return -ENOMEM; 205 return -ENOMEM;
151 206
152 leds->devtype = devtype; 207 leds->devtype = devtype;
153 leds->num_leds = num_leds;
154 leds->master = mcdev; 208 leds->master = mcdev;
155 platform_set_drvdata(pdev, leds); 209 platform_set_drvdata(pdev, leds);
156 210
211 if (dev->parent->of_node) {
212 pdata = mc13xxx_led_probe_dt(pdev);
213 if (IS_ERR(pdata))
214 return PTR_ERR(pdata);
215 } else if (!pdata)
216 return -ENODATA;
217
218 leds->num_leds = pdata->num_leds;
219
220 if ((leds->num_leds < 1) ||
221 (leds->num_leds > (devtype->led_max - devtype->led_min + 1))) {
222 dev_err(dev, "Invalid LED count %d\n", leds->num_leds);
223 return -EINVAL;
224 }
225
226 leds->led = devm_kzalloc(dev, leds->num_leds * sizeof(*leds->led),
227 GFP_KERNEL);
228 if (!leds->led)
229 return -ENOMEM;
230
157 for (i = 0; i < devtype->num_regs; i++) { 231 for (i = 0; i < devtype->num_regs; i++) {
158 ret = mc13xxx_reg_write(mcdev, leds->devtype->ledctrl_base + i, 232 ret = mc13xxx_reg_write(mcdev, leds->devtype->ledctrl_base + i,
159 pdata->led_control[i]); 233 pdata->led_control[i]);
@@ -161,7 +235,7 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
161 return ret; 235 return ret;
162 } 236 }
163 237
164 for (i = 0; i < num_leds; i++) { 238 for (i = 0; i < leds->num_leds; i++) {
165 const char *name, *trig; 239 const char *name, *trig;
166 240
167 ret = -EINVAL; 241 ret = -EINVAL;