aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/leds/leds-lp55xx.txt147
-rw-r--r--arch/arm/mach-imx/mach-mx31moboard.c9
-rw-r--r--drivers/leds/Kconfig6
-rw-r--r--drivers/leds/led-class.c10
-rw-r--r--drivers/leds/leds-88pm860x.c2
-rw-r--r--drivers/leds/leds-atmel-pwm.c1
-rw-r--r--drivers/leds/leds-gpio.c8
-rw-r--r--drivers/leds/leds-lp5521.c28
-rw-r--r--drivers/leds/leds-lp5523.c28
-rw-r--r--drivers/leds/leds-lp5562.c28
-rw-r--r--drivers/leds/leds-lp55xx-common.c45
-rw-r--r--drivers/leds/leds-lp55xx-common.h4
-rw-r--r--drivers/leds/leds-mc13783.c467
-rw-r--r--drivers/leds/leds-ns2.c2
-rw-r--r--drivers/leds/leds-renesas-tpu.c8
-rw-r--r--drivers/leds/leds-sunfire.c4
-rw-r--r--drivers/leds/leds-wm831x-status.c2
-rw-r--r--include/linux/mfd/mc13xxx.h100
18 files changed, 553 insertions, 346 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
new file mode 100644
index 000000000000..d5176882d8b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
@@ -0,0 +1,147 @@
1Binding for TI/National Semiconductor LP55xx Led Drivers
2
3Required properties:
4- compatible: "national,lp5521" or "national,lp5523" or "ti,lp5562"
5- reg: I2C slave address
6- clock-mode: Input clock mode, (0: automode, 1: internal, 2: external)
7
8Each child has own specific current settings
9- led-cur: Current setting at each led channel (mA x10, 0 if led is not connected)
10- max-cur: Maximun current at each led channel.
11
12Optional properties:
13- label: Used for naming LEDs
14
15Alternatively, each child can have specific channel name
16- chan-name: Name of each channel name
17
18example 1) LP5521
193 LED channels, external clock used. Channel names are 'lp5521_pri:channel0',
20'lp5521_pri:channel1' and 'lp5521_pri:channel2'
21
22lp5521@32 {
23 compatible = "national,lp5521";
24 reg = <0x32>;
25 label = "lp5521_pri";
26 clock-mode = /bits/ 8 <2>;
27
28 chan0 {
29 led-cur = /bits/ 8 <0x2f>;
30 max-cur = /bits/ 8 <0x5f>;
31 };
32
33 chan1 {
34 led-cur = /bits/ 8 <0x2f>;
35 max-cur = /bits/ 8 <0x5f>;
36 };
37
38 chan2 {
39 led-cur = /bits/ 8 <0x2f>;
40 max-cur = /bits/ 8 <0x5f>;
41 };
42};
43
44example 2) LP5523
459 LED channels with specific name. Internal clock used.
46The I2C slave address is configurable with ASEL1 and ASEL0 pins.
47Available addresses are 32/33/34/35h.
48
49ASEL1 ASEL0 Address
50-------------------------
51 GND GND 32h
52 GND VEN 33h
53 VEN GND 34h
54 VEN VEN 35h
55
56lp5523@32 {
57 compatible = "national,lp5523";
58 reg = <0x32>;
59 clock-mode = /bits/ 8 <1>;
60
61 chan0 {
62 chan-name = "d1";
63 led-cur = /bits/ 8 <0x14>;
64 max-cur = /bits/ 8 <0x20>;
65 };
66
67 chan1 {
68 chan-name = "d2";
69 led-cur = /bits/ 8 <0x14>;
70 max-cur = /bits/ 8 <0x20>;
71 };
72
73 chan2 {
74 chan-name = "d3";
75 led-cur = /bits/ 8 <0x14>;
76 max-cur = /bits/ 8 <0x20>;
77 };
78
79 chan3 {
80 chan-name = "d4";
81 led-cur = /bits/ 8 <0x14>;
82 max-cur = /bits/ 8 <0x20>;
83 };
84
85 chan4 {
86 chan-name = "d5";
87 led-cur = /bits/ 8 <0x14>;
88 max-cur = /bits/ 8 <0x20>;
89 };
90
91 chan5 {
92 chan-name = "d6";
93 led-cur = /bits/ 8 <0x14>;
94 max-cur = /bits/ 8 <0x20>;
95 };
96
97 chan6 {
98 chan-name = "d7";
99 led-cur = /bits/ 8 <0x14>;
100 max-cur = /bits/ 8 <0x20>;
101 };
102
103 chan7 {
104 chan-name = "d8";
105 led-cur = /bits/ 8 <0x14>;
106 max-cur = /bits/ 8 <0x20>;
107 };
108
109 chan8 {
110 chan-name = "d9";
111 led-cur = /bits/ 8 <0x14>;
112 max-cur = /bits/ 8 <0x20>;
113 };
114};
115
116example 3) LP5562
1174 channels are defined.
118
119lp5562@30 {
120 compatible = "ti,lp5562";
121 reg = <0x30>;
122 clock-mode = /bits/8 <2>;
123
124 chan0 {
125 chan-name = "R";
126 led-cur = /bits/ 8 <0x20>;
127 max-cur = /bits/ 8 <0x60>;
128 };
129
130 chan1 {
131 chan-name = "G";
132 led-cur = /bits/ 8 <0x20>;
133 max-cur = /bits/ 8 <0x60>;
134 };
135
136 chan2 {
137 chan-name = "B";
138 led-cur = /bits/ 8 <0x20>;
139 max-cur = /bits/ 8 <0x60>;
140 };
141
142 chan3 {
143 chan-name = "W";
144 led-cur = /bits/ 8 <0x20>;
145 max-cur = /bits/ 8 <0x60>;
146 };
147};
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index dae4cd7be040..6f424eced181 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -268,10 +268,11 @@ static struct mc13xxx_led_platform_data moboard_led[] = {
268static struct mc13xxx_leds_platform_data moboard_leds = { 268static struct mc13xxx_leds_platform_data moboard_leds = {
269 .num_leds = ARRAY_SIZE(moboard_led), 269 .num_leds = ARRAY_SIZE(moboard_led),
270 .led = moboard_led, 270 .led = moboard_led,
271 .flags = MC13783_LED_SLEWLIMTC, 271 .led_control[0] = MC13783_LED_C0_ENABLE | MC13783_LED_C0_ABMODE(0),
272 .abmode = MC13783_LED_AB_DISABLED, 272 .led_control[1] = MC13783_LED_C1_SLEWLIM,
273 .tc1_period = MC13783_LED_PERIOD_10MS, 273 .led_control[2] = MC13783_LED_C2_SLEWLIM,
274 .tc2_period = MC13783_LED_PERIOD_10MS, 274 .led_control[3] = MC13783_LED_C3_PERIOD(0),
275 .led_control[4] = MC13783_LED_C3_PERIOD(0),
275}; 276};
276 277
277static struct mc13xxx_buttons_platform_data moboard_buttons = { 278static struct mc13xxx_buttons_platform_data moboard_buttons = {
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index ef992293598a..e43402dd1dea 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -388,12 +388,12 @@ config LEDS_DELL_NETBOOKS
388 notebooks that have an external LED. 388 notebooks that have an external LED.
389 389
390config LEDS_MC13783 390config LEDS_MC13783
391 tristate "LED Support for MC13783 PMIC" 391 tristate "LED Support for MC13XXX PMIC"
392 depends on LEDS_CLASS 392 depends on LEDS_CLASS
393 depends on MFD_MC13783 393 depends on MFD_MC13XXX
394 help 394 help
395 This option enable support for on-chip LED drivers found 395 This option enable support for on-chip LED drivers found
396 on Freescale Semiconductor MC13783 PMIC. 396 on Freescale Semiconductor MC13783/MC13892 PMIC.
397 397
398config LEDS_NS2 398config LEDS_NS2
399 tristate "LED support for Network Space v2 GPIO LEDs" 399 tristate "LED support for Network Space v2 GPIO LEDs"
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index a20752f562bc..4336e37a97f4 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -156,7 +156,7 @@ void led_classdev_resume(struct led_classdev *led_cdev)
156} 156}
157EXPORT_SYMBOL_GPL(led_classdev_resume); 157EXPORT_SYMBOL_GPL(led_classdev_resume);
158 158
159static int led_suspend(struct device *dev, pm_message_t state) 159static int led_suspend(struct device *dev)
160{ 160{
161 struct led_classdev *led_cdev = dev_get_drvdata(dev); 161 struct led_classdev *led_cdev = dev_get_drvdata(dev);
162 162
@@ -176,6 +176,11 @@ static int led_resume(struct device *dev)
176 return 0; 176 return 0;
177} 177}
178 178
179static const struct dev_pm_ops leds_class_dev_pm_ops = {
180 .suspend = led_suspend,
181 .resume = led_resume,
182};
183
179/** 184/**
180 * led_classdev_register - register a new object of led_classdev class. 185 * led_classdev_register - register a new object of led_classdev class.
181 * @parent: The device to register. 186 * @parent: The device to register.
@@ -252,8 +257,7 @@ static int __init leds_init(void)
252 leds_class = class_create(THIS_MODULE, "leds"); 257 leds_class = class_create(THIS_MODULE, "leds");
253 if (IS_ERR(leds_class)) 258 if (IS_ERR(leds_class))
254 return PTR_ERR(leds_class); 259 return PTR_ERR(leds_class);
255 leds_class->suspend = led_suspend; 260 leds_class->pm = &leds_class_dev_pm_ops;
256 leds_class->resume = led_resume;
257 leds_class->dev_attrs = led_class_attrs; 261 leds_class->dev_attrs = led_class_attrs;
258 return 0; 262 return 0;
259} 263}
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index f5b9ea315790..232b3ce902e5 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -204,7 +204,7 @@ static int pm860x_led_probe(struct platform_device *pdev)
204 sprintf(data->name, "led1-blue"); 204 sprintf(data->name, "led1-blue");
205 break; 205 break;
206 } 206 }
207 dev_set_drvdata(&pdev->dev, data); 207 platform_set_drvdata(pdev, data);
208 data->chip = chip; 208 data->chip = chip;
209 data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; 209 data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
210 data->port = pdev->id; 210 data->port = pdev->id;
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
index 8a39c5b20f76..90518f84b9c0 100644
--- a/drivers/leds/leds-atmel-pwm.c
+++ b/drivers/leds/leds-atmel-pwm.c
@@ -129,7 +129,6 @@ static int pwmled_remove(struct platform_device *pdev)
129 pwm_channel_free(&led->pwmc); 129 pwm_channel_free(&led->pwmc);
130 } 130 }
131 131
132 platform_set_drvdata(pdev, NULL);
133 return 0; 132 return 0;
134} 133}
135 134
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index b02b679abf31..84d74c373cae 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -20,7 +20,6 @@
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/workqueue.h> 21#include <linux/workqueue.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/pinctrl/consumer.h>
24#include <linux/err.h> 23#include <linux/err.h>
25 24
26struct gpio_led_data { 25struct gpio_led_data {
@@ -236,13 +235,8 @@ static int gpio_led_probe(struct platform_device *pdev)
236{ 235{
237 struct gpio_led_platform_data *pdata = pdev->dev.platform_data; 236 struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
238 struct gpio_leds_priv *priv; 237 struct gpio_leds_priv *priv;
239 struct pinctrl *pinctrl;
240 int i, ret = 0; 238 int i, ret = 0;
241 239
242 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
243 if (IS_ERR(pinctrl))
244 dev_warn(&pdev->dev,
245 "pins are not configured from the driver\n");
246 240
247 if (pdata && pdata->num_leds) { 241 if (pdata && pdata->num_leds) {
248 priv = devm_kzalloc(&pdev->dev, 242 priv = devm_kzalloc(&pdev->dev,
@@ -282,8 +276,6 @@ static int gpio_led_remove(struct platform_device *pdev)
282 for (i = 0; i < priv->num_leds; i++) 276 for (i = 0; i < priv->num_leds; i++)
283 delete_gpio_led(&priv->leds[i]); 277 delete_gpio_led(&priv->leds[i]);
284 278
285 platform_set_drvdata(pdev, NULL);
286
287 return 0; 279 return 0;
288} 280}
289 281
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 19752c928aa2..1392feb1bcf7 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -31,6 +31,7 @@
31#include <linux/mutex.h> 31#include <linux/mutex.h>
32#include <linux/platform_data/leds-lp55xx.h> 32#include <linux/platform_data/leds-lp55xx.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/of.h>
34 35
35#include "leds-lp55xx-common.h" 36#include "leds-lp55xx-common.h"
36 37
@@ -416,12 +417,20 @@ static int lp5521_probe(struct i2c_client *client,
416 int ret; 417 int ret;
417 struct lp55xx_chip *chip; 418 struct lp55xx_chip *chip;
418 struct lp55xx_led *led; 419 struct lp55xx_led *led;
419 struct lp55xx_platform_data *pdata = client->dev.platform_data; 420 struct lp55xx_platform_data *pdata;
420 421 struct device_node *np = client->dev.of_node;
421 if (!pdata) { 422
422 dev_err(&client->dev, "no platform data\n"); 423 if (!client->dev.platform_data) {
423 return -EINVAL; 424 if (np) {
425 ret = lp55xx_of_populate_pdata(&client->dev, np);
426 if (ret < 0)
427 return ret;
428 } else {
429 dev_err(&client->dev, "no platform data\n");
430 return -EINVAL;
431 }
424 } 432 }
433 pdata = client->dev.platform_data;
425 434
426 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 435 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
427 if (!chip) 436 if (!chip)
@@ -485,9 +494,18 @@ static const struct i2c_device_id lp5521_id[] = {
485}; 494};
486MODULE_DEVICE_TABLE(i2c, lp5521_id); 495MODULE_DEVICE_TABLE(i2c, lp5521_id);
487 496
497#ifdef CONFIG_OF
498static const struct of_device_id of_lp5521_leds_match[] = {
499 { .compatible = "national,lp5521", },
500 {},
501};
502
503MODULE_DEVICE_TABLE(of, of_lp5521_leds_match);
504#endif
488static struct i2c_driver lp5521_driver = { 505static struct i2c_driver lp5521_driver = {
489 .driver = { 506 .driver = {
490 .name = "lp5521", 507 .name = "lp5521",
508 .of_match_table = of_match_ptr(of_lp5521_leds_match),
491 }, 509 },
492 .probe = lp5521_probe, 510 .probe = lp5521_probe,
493 .remove = lp5521_remove, 511 .remove = lp5521_remove,
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 229f734040af..3979428f3100 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -429,12 +429,20 @@ static int lp5523_probe(struct i2c_client *client,
429 int ret; 429 int ret;
430 struct lp55xx_chip *chip; 430 struct lp55xx_chip *chip;
431 struct lp55xx_led *led; 431 struct lp55xx_led *led;
432 struct lp55xx_platform_data *pdata = client->dev.platform_data; 432 struct lp55xx_platform_data *pdata;
433 433 struct device_node *np = client->dev.of_node;
434 if (!pdata) { 434
435 dev_err(&client->dev, "no platform data\n"); 435 if (!client->dev.platform_data) {
436 return -EINVAL; 436 if (np) {
437 ret = lp55xx_of_populate_pdata(&client->dev, np);
438 if (ret < 0)
439 return ret;
440 } else {
441 dev_err(&client->dev, "no platform data\n");
442 return -EINVAL;
443 }
437 } 444 }
445 pdata = client->dev.platform_data;
438 446
439 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 447 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
440 if (!chip) 448 if (!chip)
@@ -500,9 +508,19 @@ static const struct i2c_device_id lp5523_id[] = {
500 508
501MODULE_DEVICE_TABLE(i2c, lp5523_id); 509MODULE_DEVICE_TABLE(i2c, lp5523_id);
502 510
511#ifdef CONFIG_OF
512static const struct of_device_id of_lp5523_leds_match[] = {
513 { .compatible = "national,lp5523", },
514 {},
515};
516
517MODULE_DEVICE_TABLE(of, of_lp5523_leds_match);
518#endif
519
503static struct i2c_driver lp5523_driver = { 520static struct i2c_driver lp5523_driver = {
504 .driver = { 521 .driver = {
505 .name = "lp5523x", 522 .name = "lp5523x",
523 .of_match_table = of_match_ptr(of_lp5523_leds_match),
506 }, 524 },
507 .probe = lp5523_probe, 525 .probe = lp5523_probe,
508 .remove = lp5523_remove, 526 .remove = lp5523_remove,
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c
index 513f2390ca2d..cbd856dac150 100644
--- a/drivers/leds/leds-lp5562.c
+++ b/drivers/leds/leds-lp5562.c
@@ -515,12 +515,20 @@ static int lp5562_probe(struct i2c_client *client,
515 int ret; 515 int ret;
516 struct lp55xx_chip *chip; 516 struct lp55xx_chip *chip;
517 struct lp55xx_led *led; 517 struct lp55xx_led *led;
518 struct lp55xx_platform_data *pdata = client->dev.platform_data; 518 struct lp55xx_platform_data *pdata;
519 519 struct device_node *np = client->dev.of_node;
520 if (!pdata) { 520
521 dev_err(&client->dev, "no platform data\n"); 521 if (!client->dev.platform_data) {
522 return -EINVAL; 522 if (np) {
523 ret = lp55xx_of_populate_pdata(&client->dev, np);
524 if (ret < 0)
525 return ret;
526 } else {
527 dev_err(&client->dev, "no platform data\n");
528 return -EINVAL;
529 }
523 } 530 }
531 pdata = client->dev.platform_data;
524 532
525 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 533 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
526 if (!chip) 534 if (!chip)
@@ -583,9 +591,19 @@ static const struct i2c_device_id lp5562_id[] = {
583}; 591};
584MODULE_DEVICE_TABLE(i2c, lp5562_id); 592MODULE_DEVICE_TABLE(i2c, lp5562_id);
585 593
594#ifdef CONFIG_OF
595static const struct of_device_id of_lp5562_leds_match[] = {
596 { .compatible = "ti,lp5562", },
597 {},
598};
599
600MODULE_DEVICE_TABLE(of, of_lp5562_leds_match);
601#endif
602
586static struct i2c_driver lp5562_driver = { 603static struct i2c_driver lp5562_driver = {
587 .driver = { 604 .driver = {
588 .name = "lp5562", 605 .name = "lp5562",
606 .of_match_table = of_match_ptr(of_lp5562_leds_match),
589 }, 607 },
590 .probe = lp5562_probe, 608 .probe = lp5562_probe,
591 .remove = lp5562_remove, 609 .remove = lp5562_remove,
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index ba34199dc3d9..c2fecd4d391c 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -19,6 +19,7 @@
19#include <linux/leds.h> 19#include <linux/leds.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/platform_data/leds-lp55xx.h> 21#include <linux/platform_data/leds-lp55xx.h>
22#include <linux/slab.h>
22 23
23#include "leds-lp55xx-common.h" 24#include "leds-lp55xx-common.h"
24 25
@@ -554,6 +555,50 @@ void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)
554} 555}
555EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs); 556EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);
556 557
558int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np)
559{
560 struct device_node *child;
561 struct lp55xx_platform_data *pdata;
562 struct lp55xx_led_config *cfg;
563 int num_channels;
564 int i = 0;
565
566 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
567 if (!pdata)
568 return -ENOMEM;
569
570 num_channels = of_get_child_count(np);
571 if (num_channels == 0) {
572 dev_err(dev, "no LED channels\n");
573 return -EINVAL;
574 }
575
576 cfg = devm_kzalloc(dev, sizeof(*cfg) * num_channels, GFP_KERNEL);
577 if (!cfg)
578 return -ENOMEM;
579
580 pdata->led_config = &cfg[0];
581 pdata->num_channels = num_channels;
582
583 for_each_child_of_node(np, child) {
584 cfg[i].chan_nr = i;
585
586 of_property_read_string(child, "chan-name", &cfg[i].name);
587 of_property_read_u8(child, "led-cur", &cfg[i].led_current);
588 of_property_read_u8(child, "max-cur", &cfg[i].max_current);
589
590 i++;
591 }
592
593 of_property_read_string(np, "label", &pdata->label);
594 of_property_read_u8(np, "clock-mode", &pdata->clock_mode);
595
596 dev->platform_data = pdata;
597
598 return 0;
599}
600EXPORT_SYMBOL_GPL(lp55xx_of_populate_pdata);
601
557MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>"); 602MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>");
558MODULE_DESCRIPTION("LP55xx Common Driver"); 603MODULE_DESCRIPTION("LP55xx Common Driver");
559MODULE_LICENSE("GPL"); 604MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-lp55xx-common.h b/drivers/leds/leds-lp55xx-common.h
index fa6a078bf547..dbbf86df0f1f 100644
--- a/drivers/leds/leds-lp55xx-common.h
+++ b/drivers/leds/leds-lp55xx-common.h
@@ -135,4 +135,8 @@ extern void lp55xx_unregister_leds(struct lp55xx_led *led,
135extern int lp55xx_register_sysfs(struct lp55xx_chip *chip); 135extern int lp55xx_register_sysfs(struct lp55xx_chip *chip);
136extern void lp55xx_unregister_sysfs(struct lp55xx_chip *chip); 136extern void lp55xx_unregister_sysfs(struct lp55xx_chip *chip);
137 137
138/* common device tree population function */
139extern int lp55xx_of_populate_pdata(struct device *dev,
140 struct device_node *np);
141
138#endif /* _LEDS_LP55XX_COMMON_H */ 142#endif /* _LEDS_LP55XX_COMMON_H */
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index e942adaa7504..fa9b439323bd 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * LEDs driver for Freescale MC13783 2 * LEDs driver for Freescale MC13783/MC13892
3 * 3 *
4 * Copyright (C) 2010 Philippe Rétornaz 4 * Copyright (C) 2010 Philippe Rétornaz
5 * 5 *
@@ -22,9 +22,16 @@
22#include <linux/leds.h> 22#include <linux/leds.h>
23#include <linux/workqueue.h> 23#include <linux/workqueue.h>
24#include <linux/mfd/mc13xxx.h> 24#include <linux/mfd/mc13xxx.h>
25#include <linux/slab.h>
26 25
27struct mc13783_led { 26#define MC13XXX_REG_LED_CONTROL(x) (51 + (x))
27
28struct mc13xxx_led_devtype {
29 int led_min;
30 int led_max;
31 int num_regs;
32};
33
34struct mc13xxx_led {
28 struct led_classdev cdev; 35 struct led_classdev cdev;
29 struct work_struct work; 36 struct work_struct work;
30 struct mc13xxx *master; 37 struct mc13xxx *master;
@@ -32,66 +39,35 @@ struct mc13783_led {
32 int id; 39 int id;
33}; 40};
34 41
35#define MC13783_REG_LED_CONTROL_0 51 42struct mc13xxx_leds {
36#define MC13783_LED_C0_ENABLE_BIT (1 << 0) 43 struct mc13xxx_led_devtype *devtype;
37#define MC13783_LED_C0_TRIODE_MD_BIT (1 << 7) 44 int num_leds;
38#define MC13783_LED_C0_TRIODE_AD_BIT (1 << 8) 45 struct mc13xxx_led led[0];
39#define MC13783_LED_C0_TRIODE_KP_BIT (1 << 9) 46};
40#define MC13783_LED_C0_BOOST_BIT (1 << 10) 47
41#define MC13783_LED_C0_ABMODE_MASK 0x7 48static void mc13xxx_led_work(struct work_struct *work)
42#define MC13783_LED_C0_ABMODE 11
43#define MC13783_LED_C0_ABREF_MASK 0x3
44#define MC13783_LED_C0_ABREF 14
45
46#define MC13783_REG_LED_CONTROL_1 52
47#define MC13783_LED_C1_TC1HALF_BIT (1 << 18)
48
49#define MC13783_REG_LED_CONTROL_2 53
50#define MC13783_LED_C2_BL_P_MASK 0xf
51#define MC13783_LED_C2_MD_P 9
52#define MC13783_LED_C2_AD_P 13
53#define MC13783_LED_C2_KP_P 17
54#define MC13783_LED_C2_BL_C_MASK 0x7
55#define MC13783_LED_C2_MD_C 0
56#define MC13783_LED_C2_AD_C 3
57#define MC13783_LED_C2_KP_C 6
58
59#define MC13783_REG_LED_CONTROL_3 54
60#define MC13783_LED_C3_TC_P 6
61#define MC13783_LED_C3_TC_P_MASK 0x1f
62
63#define MC13783_REG_LED_CONTROL_4 55
64#define MC13783_REG_LED_CONTROL_5 56
65
66#define MC13783_LED_Cx_PERIOD 21
67#define MC13783_LED_Cx_PERIOD_MASK 0x3
68#define MC13783_LED_Cx_SLEWLIM_BIT (1 << 23)
69#define MC13783_LED_Cx_TRIODE_TC_BIT (1 << 23)
70#define MC13783_LED_Cx_TC_C_MASK 0x3
71
72static void mc13783_led_work(struct work_struct *work)
73{ 49{
74 struct mc13783_led *led = container_of(work, struct mc13783_led, work); 50 struct mc13xxx_led *led = container_of(work, struct mc13xxx_led, work);
75 int reg = 0; 51 int reg, mask, value, bank, off, shift;
76 int mask = 0;
77 int value = 0;
78 int bank, off, shift;
79 52
80 switch (led->id) { 53 switch (led->id) {
81 case MC13783_LED_MD: 54 case MC13783_LED_MD:
82 reg = MC13783_REG_LED_CONTROL_2; 55 reg = MC13XXX_REG_LED_CONTROL(2);
83 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_MD_P; 56 shift = 9;
84 value = (led->new_brightness >> 4) << MC13783_LED_C2_MD_P; 57 mask = 0x0f;
58 value = led->new_brightness >> 4;
85 break; 59 break;
86 case MC13783_LED_AD: 60 case MC13783_LED_AD:
87 reg = MC13783_REG_LED_CONTROL_2; 61 reg = MC13XXX_REG_LED_CONTROL(2);
88 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_AD_P; 62 shift = 13;
89 value = (led->new_brightness >> 4) << MC13783_LED_C2_AD_P; 63 mask = 0x0f;
64 value = led->new_brightness >> 4;
90 break; 65 break;
91 case MC13783_LED_KP: 66 case MC13783_LED_KP:
92 reg = MC13783_REG_LED_CONTROL_2; 67 reg = MC13XXX_REG_LED_CONTROL(2);
93 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_KP_P; 68 shift = 17;
94 value = (led->new_brightness >> 4) << MC13783_LED_C2_KP_P; 69 mask = 0x0f;
70 value = led->new_brightness >> 4;
95 break; 71 break;
96 case MC13783_LED_R1: 72 case MC13783_LED_R1:
97 case MC13783_LED_G1: 73 case MC13783_LED_G1:
@@ -103,57 +79,78 @@ static void mc13783_led_work(struct work_struct *work)
103 case MC13783_LED_G3: 79 case MC13783_LED_G3:
104 case MC13783_LED_B3: 80 case MC13783_LED_B3:
105 off = led->id - MC13783_LED_R1; 81 off = led->id - MC13783_LED_R1;
106 bank = off/3; 82 bank = off / 3;
107 reg = MC13783_REG_LED_CONTROL_3 + off/3; 83 reg = MC13XXX_REG_LED_CONTROL(3) + bank;
108 shift = (off - bank * 3) * 5 + MC13783_LED_C3_TC_P; 84 shift = (off - bank * 3) * 5 + 6;
109 value = (led->new_brightness >> 3) << shift; 85 value = led->new_brightness >> 3;
110 mask = MC13783_LED_C3_TC_P_MASK << shift; 86 mask = 0x1f;
87 break;
88 case MC13892_LED_MD:
89 reg = MC13XXX_REG_LED_CONTROL(0);
90 shift = 3;
91 mask = 0x3f;
92 value = led->new_brightness >> 2;
93 break;
94 case MC13892_LED_AD:
95 reg = MC13XXX_REG_LED_CONTROL(0);
96 shift = 15;
97 mask = 0x3f;
98 value = led->new_brightness >> 2;
99 break;
100 case MC13892_LED_KP:
101 reg = MC13XXX_REG_LED_CONTROL(1);
102 shift = 3;
103 mask = 0x3f;
104 value = led->new_brightness >> 2;
111 break; 105 break;
106 case MC13892_LED_R:
107 case MC13892_LED_G:
108 case MC13892_LED_B:
109 off = led->id - MC13892_LED_R;
110 bank = off / 2;
111 reg = MC13XXX_REG_LED_CONTROL(2) + bank;
112 shift = (off - bank * 2) * 12 + 3;
113 value = led->new_brightness >> 2;
114 mask = 0x3f;
115 break;
116 default:
117 BUG();
112 } 118 }
113 119
114 mc13xxx_lock(led->master); 120 mc13xxx_lock(led->master);
115 121 mc13xxx_reg_rmw(led->master, reg, mask << shift, value << shift);
116 mc13xxx_reg_rmw(led->master, reg, mask, value);
117
118 mc13xxx_unlock(led->master); 122 mc13xxx_unlock(led->master);
119} 123}
120 124
121static void mc13783_led_set(struct led_classdev *led_cdev, 125static void mc13xxx_led_set(struct led_classdev *led_cdev,
122 enum led_brightness value) 126 enum led_brightness value)
123{ 127{
124 struct mc13783_led *led; 128 struct mc13xxx_led *led =
129 container_of(led_cdev, struct mc13xxx_led, cdev);
125 130
126 led = container_of(led_cdev, struct mc13783_led, cdev);
127 led->new_brightness = value; 131 led->new_brightness = value;
128 schedule_work(&led->work); 132 schedule_work(&led->work);
129} 133}
130 134
131static int mc13783_led_setup(struct mc13783_led *led, int max_current) 135static int __init mc13xxx_led_setup(struct mc13xxx_led *led, int max_current)
132{ 136{
133 int shift = 0; 137 int shift, mask, reg, ret, bank;
134 int mask = 0;
135 int value = 0;
136 int reg = 0;
137 int ret, bank;
138 138
139 switch (led->id) { 139 switch (led->id) {
140 case MC13783_LED_MD: 140 case MC13783_LED_MD:
141 shift = MC13783_LED_C2_MD_C; 141 reg = MC13XXX_REG_LED_CONTROL(2);
142 mask = MC13783_LED_C2_BL_C_MASK; 142 shift = 0;
143 value = max_current & MC13783_LED_C2_BL_C_MASK; 143 mask = 0x07;
144 reg = MC13783_REG_LED_CONTROL_2;
145 break; 144 break;
146 case MC13783_LED_AD: 145 case MC13783_LED_AD:
147 shift = MC13783_LED_C2_AD_C; 146 reg = MC13XXX_REG_LED_CONTROL(2);
148 mask = MC13783_LED_C2_BL_C_MASK; 147 shift = 3;
149 value = max_current & MC13783_LED_C2_BL_C_MASK; 148 mask = 0x07;
150 reg = MC13783_REG_LED_CONTROL_2;
151 break; 149 break;
152 case MC13783_LED_KP: 150 case MC13783_LED_KP:
153 shift = MC13783_LED_C2_KP_C; 151 reg = MC13XXX_REG_LED_CONTROL(2);
154 mask = MC13783_LED_C2_BL_C_MASK; 152 shift = 6;
155 value = max_current & MC13783_LED_C2_BL_C_MASK; 153 mask = 0x07;
156 reg = MC13783_REG_LED_CONTROL_2;
157 break; 154 break;
158 case MC13783_LED_R1: 155 case MC13783_LED_R1:
159 case MC13783_LED_G1: 156 case MC13783_LED_G1:
@@ -164,229 +161,195 @@ static int mc13783_led_setup(struct mc13783_led *led, int max_current)
164 case MC13783_LED_R3: 161 case MC13783_LED_R3:
165 case MC13783_LED_G3: 162 case MC13783_LED_G3:
166 case MC13783_LED_B3: 163 case MC13783_LED_B3:
167 bank = (led->id - MC13783_LED_R1)/3; 164 bank = (led->id - MC13783_LED_R1) / 3;
168 reg = MC13783_REG_LED_CONTROL_3 + bank; 165 reg = MC13XXX_REG_LED_CONTROL(3) + bank;
169 shift = ((led->id - MC13783_LED_R1) - bank * 3) * 2; 166 shift = ((led->id - MC13783_LED_R1) - bank * 3) * 2;
170 mask = MC13783_LED_Cx_TC_C_MASK; 167 mask = 0x03;
171 value = max_current & MC13783_LED_Cx_TC_C_MASK; 168 break;
169 case MC13892_LED_MD:
170 reg = MC13XXX_REG_LED_CONTROL(0);
171 shift = 9;
172 mask = 0x07;
172 break; 173 break;
174 case MC13892_LED_AD:
175 reg = MC13XXX_REG_LED_CONTROL(0);
176 shift = 21;
177 mask = 0x07;
178 break;
179 case MC13892_LED_KP:
180 reg = MC13XXX_REG_LED_CONTROL(1);
181 shift = 9;
182 mask = 0x07;
183 break;
184 case MC13892_LED_R:
185 case MC13892_LED_G:
186 case MC13892_LED_B:
187 bank = (led->id - MC13892_LED_R) / 2;
188 reg = MC13XXX_REG_LED_CONTROL(2) + bank;
189 shift = ((led->id - MC13892_LED_R) - bank * 2) * 12 + 9;
190 mask = 0x07;
191 break;
192 default:
193 BUG();
173 } 194 }
174 195
175 mc13xxx_lock(led->master); 196 mc13xxx_lock(led->master);
176
177 ret = mc13xxx_reg_rmw(led->master, reg, mask << shift, 197 ret = mc13xxx_reg_rmw(led->master, reg, mask << shift,
178 value << shift); 198 max_current << shift);
179
180 mc13xxx_unlock(led->master); 199 mc13xxx_unlock(led->master);
181 return ret;
182}
183
184static int mc13783_leds_prepare(struct platform_device *pdev)
185{
186 struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
187 struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
188 int ret = 0;
189 int reg = 0;
190
191 mc13xxx_lock(dev);
192
193 if (pdata->flags & MC13783_LED_TC1HALF)
194 reg |= MC13783_LED_C1_TC1HALF_BIT;
195
196 if (pdata->flags & MC13783_LED_SLEWLIMTC)
197 reg |= MC13783_LED_Cx_SLEWLIM_BIT;
198
199 ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_1, reg);
200 if (ret)
201 goto out;
202
203 reg = (pdata->bl_period & MC13783_LED_Cx_PERIOD_MASK) <<
204 MC13783_LED_Cx_PERIOD;
205
206 if (pdata->flags & MC13783_LED_SLEWLIMBL)
207 reg |= MC13783_LED_Cx_SLEWLIM_BIT;
208
209 ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_2, reg);
210 if (ret)
211 goto out;
212
213 reg = (pdata->tc1_period & MC13783_LED_Cx_PERIOD_MASK) <<
214 MC13783_LED_Cx_PERIOD;
215 200
216 if (pdata->flags & MC13783_LED_TRIODE_TC1)
217 reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
218
219 ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_3, reg);
220 if (ret)
221 goto out;
222
223 reg = (pdata->tc2_period & MC13783_LED_Cx_PERIOD_MASK) <<
224 MC13783_LED_Cx_PERIOD;
225
226 if (pdata->flags & MC13783_LED_TRIODE_TC2)
227 reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
228
229 ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_4, reg);
230 if (ret)
231 goto out;
232
233 reg = (pdata->tc3_period & MC13783_LED_Cx_PERIOD_MASK) <<
234 MC13783_LED_Cx_PERIOD;
235
236 if (pdata->flags & MC13783_LED_TRIODE_TC3)
237 reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
238
239 ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_5, reg);
240 if (ret)
241 goto out;
242
243 reg = MC13783_LED_C0_ENABLE_BIT;
244 if (pdata->flags & MC13783_LED_TRIODE_MD)
245 reg |= MC13783_LED_C0_TRIODE_MD_BIT;
246 if (pdata->flags & MC13783_LED_TRIODE_AD)
247 reg |= MC13783_LED_C0_TRIODE_AD_BIT;
248 if (pdata->flags & MC13783_LED_TRIODE_KP)
249 reg |= MC13783_LED_C0_TRIODE_KP_BIT;
250 if (pdata->flags & MC13783_LED_BOOST_EN)
251 reg |= MC13783_LED_C0_BOOST_BIT;
252
253 reg |= (pdata->abmode & MC13783_LED_C0_ABMODE_MASK) <<
254 MC13783_LED_C0_ABMODE;
255 reg |= (pdata->abref & MC13783_LED_C0_ABREF_MASK) <<
256 MC13783_LED_C0_ABREF;
257
258 ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_0, reg);
259
260out:
261 mc13xxx_unlock(dev);
262 return ret; 201 return ret;
263} 202}
264 203
265static int mc13783_led_probe(struct platform_device *pdev) 204static int __init mc13xxx_led_probe(struct platform_device *pdev)
266{ 205{
267 struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); 206 struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
268 struct mc13xxx_led_platform_data *led_cur; 207 struct mc13xxx *mcdev = dev_get_drvdata(pdev->dev.parent);
269 struct mc13783_led *led, *led_dat; 208 struct mc13xxx_led_devtype *devtype =
270 int ret, i; 209 (struct mc13xxx_led_devtype *)pdev->id_entry->driver_data;
271 int init_led = 0; 210 struct mc13xxx_leds *leds;
272 211 int i, id, num_leds, ret = -ENODATA;
273 if (pdata == NULL) { 212 u32 reg, init_led = 0;
274 dev_err(&pdev->dev, "missing platform data\n"); 213
214 if (!pdata) {
215 dev_err(&pdev->dev, "Missing platform data\n");
275 return -ENODEV; 216 return -ENODEV;
276 } 217 }
277 218
278 if (pdata->num_leds < 1 || pdata->num_leds > (MC13783_LED_MAX + 1)) { 219 num_leds = pdata->num_leds;
279 dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds); 220
221 if ((num_leds < 1) ||
222 (num_leds > (devtype->led_max - devtype->led_min + 1))) {
223 dev_err(&pdev->dev, "Invalid LED count %d\n", num_leds);
280 return -EINVAL; 224 return -EINVAL;
281 } 225 }
282 226
283 led = devm_kzalloc(&pdev->dev, pdata->num_leds * sizeof(*led), 227 leds = devm_kzalloc(&pdev->dev, num_leds * sizeof(struct mc13xxx_led) +
284 GFP_KERNEL); 228 sizeof(struct mc13xxx_leds), GFP_KERNEL);
285 if (led == NULL) { 229 if (!leds)
286 dev_err(&pdev->dev, "failed to alloc memory\n");
287 return -ENOMEM; 230 return -ENOMEM;
231
232 leds->devtype = devtype;
233 leds->num_leds = num_leds;
234 platform_set_drvdata(pdev, leds);
235
236 mc13xxx_lock(mcdev);
237 for (i = 0; i < devtype->num_regs; i++) {
238 reg = pdata->led_control[i];
239 WARN_ON(reg >= (1 << 24));
240 ret = mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), reg);
241 if (ret)
242 break;
288 } 243 }
244 mc13xxx_unlock(mcdev);
289 245
290 ret = mc13783_leds_prepare(pdev);
291 if (ret) { 246 if (ret) {
292 dev_err(&pdev->dev, "unable to init led driver\n"); 247 dev_err(&pdev->dev, "Unable to init LED driver\n");
293 return ret; 248 return ret;
294 } 249 }
295 250
296 for (i = 0; i < pdata->num_leds; i++) { 251 for (i = 0; i < num_leds; i++) {
297 led_dat = &led[i]; 252 const char *name, *trig;
298 led_cur = &pdata->led[i]; 253 char max_current;
254
255 ret = -EINVAL;
299 256
300 if (led_cur->id > MC13783_LED_MAX || led_cur->id < 0) { 257 id = pdata->led[i].id;
301 dev_err(&pdev->dev, "invalid id %d\n", led_cur->id); 258 name = pdata->led[i].name;
302 ret = -EINVAL; 259 trig = pdata->led[i].default_trigger;
303 goto err_register; 260 max_current = pdata->led[i].max_current;
261
262 if ((id > devtype->led_max) || (id < devtype->led_min)) {
263 dev_err(&pdev->dev, "Invalid ID %i\n", id);
264 break;
304 } 265 }
305 266
306 if (init_led & (1 << led_cur->id)) { 267 if (init_led & (1 << id)) {
307 dev_err(&pdev->dev, "led %d already initialized\n", 268 dev_warn(&pdev->dev,
308 led_cur->id); 269 "LED %i already initialized\n", id);
309 ret = -EINVAL; 270 break;
310 goto err_register;
311 } 271 }
312 272
313 init_led |= 1 << led_cur->id; 273 init_led |= 1 << id;
314 led_dat->cdev.name = led_cur->name; 274 leds->led[i].id = id;
315 led_dat->cdev.default_trigger = led_cur->default_trigger; 275 leds->led[i].master = mcdev;
316 led_dat->cdev.brightness_set = mc13783_led_set; 276 leds->led[i].cdev.name = name;
317 led_dat->cdev.brightness = LED_OFF; 277 leds->led[i].cdev.default_trigger = trig;
318 led_dat->id = led_cur->id; 278 leds->led[i].cdev.brightness_set = mc13xxx_led_set;
319 led_dat->master = dev_get_drvdata(pdev->dev.parent); 279 leds->led[i].cdev.brightness = LED_OFF;
320 280
321 INIT_WORK(&led_dat->work, mc13783_led_work); 281 INIT_WORK(&leds->led[i].work, mc13xxx_led_work);
322 282
323 ret = led_classdev_register(pdev->dev.parent, &led_dat->cdev); 283 ret = mc13xxx_led_setup(&leds->led[i], max_current);
324 if (ret) { 284 if (ret) {
325 dev_err(&pdev->dev, "failed to register led %d\n", 285 dev_err(&pdev->dev, "Unable to setup LED %i\n", id);
326 led_dat->id); 286 break;
327 goto err_register;
328 } 287 }
329 288 ret = led_classdev_register(pdev->dev.parent,
330 ret = mc13783_led_setup(led_dat, led_cur->max_current); 289 &leds->led[i].cdev);
331 if (ret) { 290 if (ret) {
332 dev_err(&pdev->dev, "unable to init led %d\n", 291 dev_err(&pdev->dev, "Failed to register LED %i\n", id);
333 led_dat->id); 292 break;
334 i++;
335 goto err_register;
336 } 293 }
337 } 294 }
338 295
339 platform_set_drvdata(pdev, led); 296 if (ret)
340 return 0; 297 while (--i >= 0) {
341 298 led_classdev_unregister(&leds->led[i].cdev);
342err_register: 299 cancel_work_sync(&leds->led[i].work);
343 for (i = i - 1; i >= 0; i--) { 300 }
344 led_classdev_unregister(&led[i].cdev);
345 cancel_work_sync(&led[i].work);
346 }
347 301
348 return ret; 302 return ret;
349} 303}
350 304
351static int mc13783_led_remove(struct platform_device *pdev) 305static int mc13xxx_led_remove(struct platform_device *pdev)
352{ 306{
353 struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); 307 struct mc13xxx *mcdev = dev_get_drvdata(pdev->dev.parent);
354 struct mc13783_led *led = platform_get_drvdata(pdev); 308 struct mc13xxx_leds *leds = platform_get_drvdata(pdev);
355 struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
356 int i; 309 int i;
357 310
358 for (i = 0; i < pdata->num_leds; i++) { 311 for (i = 0; i < leds->num_leds; i++) {
359 led_classdev_unregister(&led[i].cdev); 312 led_classdev_unregister(&leds->led[i].cdev);
360 cancel_work_sync(&led[i].work); 313 cancel_work_sync(&leds->led[i].work);
361 } 314 }
362 315
363 mc13xxx_lock(dev); 316 mc13xxx_lock(mcdev);
364 317 for (i = 0; i < leds->devtype->num_regs; i++)
365 mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_0, 0); 318 mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), 0);
366 mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_1, 0); 319 mc13xxx_unlock(mcdev);
367 mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_2, 0);
368 mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_3, 0);
369 mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_4, 0);
370 mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_5, 0);
371
372 mc13xxx_unlock(dev);
373 320
374 platform_set_drvdata(pdev, NULL);
375 return 0; 321 return 0;
376} 322}
377 323
378static struct platform_driver mc13783_led_driver = { 324static const struct mc13xxx_led_devtype mc13783_led_devtype = {
325 .led_min = MC13783_LED_MD,
326 .led_max = MC13783_LED_B3,
327 .num_regs = 6,
328};
329
330static const struct mc13xxx_led_devtype mc13892_led_devtype = {
331 .led_min = MC13892_LED_MD,
332 .led_max = MC13892_LED_B,
333 .num_regs = 4,
334};
335
336static const struct platform_device_id mc13xxx_led_id_table[] = {
337 { "mc13783-led", (kernel_ulong_t)&mc13783_led_devtype, },
338 { "mc13892-led", (kernel_ulong_t)&mc13892_led_devtype, },
339 { }
340};
341MODULE_DEVICE_TABLE(platform, mc13xxx_led_id_table);
342
343static struct platform_driver mc13xxx_led_driver = {
379 .driver = { 344 .driver = {
380 .name = "mc13783-led", 345 .name = "mc13xxx-led",
381 .owner = THIS_MODULE, 346 .owner = THIS_MODULE,
382 }, 347 },
383 .probe = mc13783_led_probe, 348 .remove = mc13xxx_led_remove,
384 .remove = mc13783_led_remove, 349 .id_table = mc13xxx_led_id_table,
385}; 350};
351module_platform_driver_probe(mc13xxx_led_driver, mc13xxx_led_probe);
386 352
387module_platform_driver(mc13783_led_driver); 353MODULE_DESCRIPTION("LEDs driver for Freescale MC13XXX PMIC");
388
389MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC");
390MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>"); 354MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>");
391MODULE_LICENSE("GPL"); 355MODULE_LICENSE("GPL");
392MODULE_ALIAS("platform:mc13783-led");
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index 70137b1eecf5..e7df9875c400 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -374,8 +374,6 @@ static int ns2_led_remove(struct platform_device *pdev)
374 for (i = 0; i < priv->num_leds; i++) 374 for (i = 0; i < priv->num_leds; i++)
375 delete_ns2_led(&priv->leds_data[i]); 375 delete_ns2_led(&priv->leds_data[i]);
376 376
377 platform_set_drvdata(pdev, NULL);
378
379 return 0; 377 return 0;
380} 378}
381 379
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
index 9483f1c1078d..adebf4931e1e 100644
--- a/drivers/leds/leds-renesas-tpu.c
+++ b/drivers/leds/leds-renesas-tpu.c
@@ -63,7 +63,7 @@ static DEFINE_SPINLOCK(r_tpu_lock);
63#define TGRC 8 /* Timer general register C (+0x20) */ 63#define TGRC 8 /* Timer general register C (+0x20) */
64#define TGRD 9 /* Timer general register D (+0x24) */ 64#define TGRD 9 /* Timer general register D (+0x24) */
65 65
66static inline unsigned short r_tpu_read(struct r_tpu_priv *p, int reg_nr) 66static inline u16 r_tpu_read(struct r_tpu_priv *p, int reg_nr)
67{ 67{
68 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data; 68 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
69 void __iomem *base = p->mapbase; 69 void __iomem *base = p->mapbase;
@@ -75,8 +75,7 @@ static inline unsigned short r_tpu_read(struct r_tpu_priv *p, int reg_nr)
75 return ioread16(base + offs); 75 return ioread16(base + offs);
76} 76}
77 77
78static inline void r_tpu_write(struct r_tpu_priv *p, int reg_nr, 78static inline void r_tpu_write(struct r_tpu_priv *p, int reg_nr, u16 value)
79 unsigned short value)
80{ 79{
81 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data; 80 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
82 void __iomem *base = p->mapbase; 81 void __iomem *base = p->mapbase;
@@ -93,7 +92,8 @@ static inline void r_tpu_write(struct r_tpu_priv *p, int reg_nr,
93static void r_tpu_start_stop_ch(struct r_tpu_priv *p, int start) 92static void r_tpu_start_stop_ch(struct r_tpu_priv *p, int start)
94{ 93{
95 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data; 94 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
96 unsigned long flags, value; 95 unsigned long flags;
96 u16 value;
97 97
98 /* start stop register shared by multiple timer channels */ 98 /* start stop register shared by multiple timer channels */
99 spin_lock_irqsave(&r_tpu_lock, flags); 99 spin_lock_irqsave(&r_tpu_lock, flags);
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
index 89792990088d..388632d23d44 100644
--- a/drivers/leds/leds-sunfire.c
+++ b/drivers/leds/leds-sunfire.c
@@ -159,14 +159,14 @@ static int sunfire_led_generic_probe(struct platform_device *pdev,
159 } 159 }
160 } 160 }
161 161
162 dev_set_drvdata(&pdev->dev, p); 162 platform_set_drvdata(pdev, p);
163 163
164 return 0; 164 return 0;
165} 165}
166 166
167static int sunfire_led_generic_remove(struct platform_device *pdev) 167static int sunfire_led_generic_remove(struct platform_device *pdev)
168{ 168{
169 struct sunfire_drvdata *p = dev_get_drvdata(&pdev->dev); 169 struct sunfire_drvdata *p = platform_get_drvdata(pdev);
170 int i; 170 int i;
171 171
172 for (i = 0; i < NUM_LEDS_PER_BOARD; i++) 172 for (i = 0; i < NUM_LEDS_PER_BOARD; i++)
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c
index 6bd5c679d877..120815a42701 100644
--- a/drivers/leds/leds-wm831x-status.c
+++ b/drivers/leds/leds-wm831x-status.c
@@ -241,7 +241,7 @@ static int wm831x_status_probe(struct platform_device *pdev)
241 GFP_KERNEL); 241 GFP_KERNEL);
242 if (!drvdata) 242 if (!drvdata)
243 return -ENOMEM; 243 return -ENOMEM;
244 dev_set_drvdata(&pdev->dev, drvdata); 244 platform_set_drvdata(pdev, drvdata);
245 245
246 drvdata->wm831x = wm831x; 246 drvdata->wm831x = wm831x;
247 drvdata->reg = res->start; 247 drvdata->reg = res->start;
diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h
index bf070755982e..41ed59276c00 100644
--- a/include/linux/mfd/mc13xxx.h
+++ b/include/linux/mfd/mc13xxx.h
@@ -78,20 +78,30 @@ struct mc13xxx_regulator_platform_data {
78 struct mc13xxx_regulator_init_data *regulators; 78 struct mc13xxx_regulator_init_data *regulators;
79}; 79};
80 80
81enum {
82 /* MC13783 LED IDs */
83 MC13783_LED_MD,
84 MC13783_LED_AD,
85 MC13783_LED_KP,
86 MC13783_LED_R1,
87 MC13783_LED_G1,
88 MC13783_LED_B1,
89 MC13783_LED_R2,
90 MC13783_LED_G2,
91 MC13783_LED_B2,
92 MC13783_LED_R3,
93 MC13783_LED_G3,
94 MC13783_LED_B3,
95 /* MC13892 LED IDs */
96 MC13892_LED_MD,
97 MC13892_LED_AD,
98 MC13892_LED_KP,
99 MC13892_LED_R,
100 MC13892_LED_G,
101 MC13892_LED_B,
102};
103
81struct mc13xxx_led_platform_data { 104struct mc13xxx_led_platform_data {
82#define MC13783_LED_MD 0
83#define MC13783_LED_AD 1
84#define MC13783_LED_KP 2
85#define MC13783_LED_R1 3
86#define MC13783_LED_G1 4
87#define MC13783_LED_B1 5
88#define MC13783_LED_R2 6
89#define MC13783_LED_G2 7
90#define MC13783_LED_B2 8
91#define MC13783_LED_R3 9
92#define MC13783_LED_G3 10
93#define MC13783_LED_B3 11
94#define MC13783_LED_MAX MC13783_LED_B3
95 int id; 105 int id;
96 const char *name; 106 const char *name;
97 const char *default_trigger; 107 const char *default_trigger;
@@ -100,46 +110,36 @@ struct mc13xxx_led_platform_data {
100 char max_current; 110 char max_current;
101}; 111};
102 112
113#define MAX_LED_CONTROL_REGS 6
114
103struct mc13xxx_leds_platform_data { 115struct mc13xxx_leds_platform_data {
104 int num_leds;
105 struct mc13xxx_led_platform_data *led; 116 struct mc13xxx_led_platform_data *led;
117 int num_leds;
106 118
107#define MC13783_LED_TRIODE_MD (1 << 0) 119/* LED Control 0 */
108#define MC13783_LED_TRIODE_AD (1 << 1) 120#define MC13783_LED_C0_ENABLE (1 << 0)
109#define MC13783_LED_TRIODE_KP (1 << 2) 121#define MC13783_LED_C0_TRIODE_MD (1 << 7)
110#define MC13783_LED_BOOST_EN (1 << 3) 122#define MC13783_LED_C0_TRIODE_AD (1 << 8)
111#define MC13783_LED_TC1HALF (1 << 4) 123#define MC13783_LED_C0_TRIODE_KP (1 << 9)
112#define MC13783_LED_SLEWLIMTC (1 << 5) 124#define MC13783_LED_C0_BOOST (1 << 10)
113#define MC13783_LED_SLEWLIMBL (1 << 6) 125#define MC13783_LED_C0_ABMODE(x) (((x) & 0x7) << 11)
114#define MC13783_LED_TRIODE_TC1 (1 << 7) 126#define MC13783_LED_C0_ABREF(x) (((x) & 0x3) << 14)
115#define MC13783_LED_TRIODE_TC2 (1 << 8) 127/* LED Control 1 */
116#define MC13783_LED_TRIODE_TC3 (1 << 9) 128#define MC13783_LED_C1_TC1HALF (1 << 18)
117 int flags; 129#define MC13783_LED_C1_SLEWLIM (1 << 23)
118 130/* LED Control 2 */
119#define MC13783_LED_AB_DISABLED 0 131#define MC13783_LED_C2_PERIOD(x) (((x) & 0x3) << 21)
120#define MC13783_LED_AB_MD1 1 132#define MC13783_LED_C2_SLEWLIM (1 << 23)
121#define MC13783_LED_AB_MD12 2 133/* LED Control 3 */
122#define MC13783_LED_AB_MD123 3 134#define MC13783_LED_C3_PERIOD(x) (((x) & 0x3) << 21)
123#define MC13783_LED_AB_MD1234 4 135#define MC13783_LED_C3_TRIODE_TC1 (1 << 23)
124#define MC13783_LED_AB_MD1234_AD1 5 136/* LED Control 4 */
125#define MC13783_LED_AB_MD1234_AD12 6 137#define MC13783_LED_C4_PERIOD(x) (((x) & 0x3) << 21)
126#define MC13783_LED_AB_MD1_AD 7 138#define MC13783_LED_C4_TRIODE_TC2 (1 << 23)
127 char abmode; 139/* LED Control 5 */
128 140#define MC13783_LED_C5_PERIOD(x) (((x) & 0x3) << 21)
129#define MC13783_LED_ABREF_200MV 0 141#define MC13783_LED_C5_TRIODE_TC3 (1 << 23)
130#define MC13783_LED_ABREF_400MV 1 142 u32 led_control[MAX_LED_CONTROL_REGS];
131#define MC13783_LED_ABREF_600MV 2
132#define MC13783_LED_ABREF_800MV 3
133 char abref;
134
135#define MC13783_LED_PERIOD_10MS 0
136#define MC13783_LED_PERIOD_100MS 1
137#define MC13783_LED_PERIOD_500MS 2
138#define MC13783_LED_PERIOD_2S 3
139 char bl_period;
140 char tc1_period;
141 char tc2_period;
142 char tc3_period;
143}; 143};
144 144
145struct mc13xxx_buttons_platform_data { 145struct mc13xxx_buttons_platform_data {