aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-mx3/mach-mx31moboard.c45
-rw-r--r--arch/arm/mach-orion5x/dns323-setup.c22
-rw-r--r--drivers/leds/Kconfig17
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/led-class.c2
-rw-r--r--drivers/leds/leds-88pm860x.c11
-rw-r--r--drivers/leds/leds-gpio.c31
-rw-r--r--drivers/leds/leds-lp3944.c9
-rw-r--r--drivers/leds/leds-mc13783.c403
-rw-r--r--drivers/leds/leds-net5501.c94
-rw-r--r--drivers/leds/leds-ss4200.c2
-rw-r--r--drivers/mfd/mc13783-core.c4
-rw-r--r--include/linux/leds.h12
-rw-r--r--include/linux/mfd/mc13783.h66
14 files changed, 691 insertions, 29 deletions
diff --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c
index 33a8d35498a7..62b5e40165df 100644
--- a/arch/arm/mach-mx3/mach-mx31moboard.c
+++ b/arch/arm/mach-mx3/mach-mx31moboard.c
@@ -220,11 +220,54 @@ static struct mc13783_regulator_init_data moboard_regulators[] = {
220 }, 220 },
221}; 221};
222 222
223static struct mc13783_led_platform_data moboard_led[] = {
224 {
225 .id = MC13783_LED_R1,
226 .name = "coreboard-led-4:red",
227 .max_current = 2,
228 },
229 {
230 .id = MC13783_LED_G1,
231 .name = "coreboard-led-4:green",
232 .max_current = 2,
233 },
234 {
235 .id = MC13783_LED_B1,
236 .name = "coreboard-led-4:blue",
237 .max_current = 2,
238 },
239 {
240 .id = MC13783_LED_R2,
241 .name = "coreboard-led-5:red",
242 .max_current = 3,
243 },
244 {
245 .id = MC13783_LED_G2,
246 .name = "coreboard-led-5:green",
247 .max_current = 3,
248 },
249 {
250 .id = MC13783_LED_B2,
251 .name = "coreboard-led-5:blue",
252 .max_current = 3,
253 },
254};
255
256static struct mc13783_leds_platform_data moboard_leds = {
257 .num_leds = ARRAY_SIZE(moboard_led),
258 .led = moboard_led,
259 .flags = MC13783_LED_SLEWLIMTC,
260 .abmode = MC13783_LED_AB_DISABLED,
261 .tc1_period = MC13783_LED_PERIOD_10MS,
262 .tc2_period = MC13783_LED_PERIOD_10MS,
263};
264
223static struct mc13783_platform_data moboard_pmic = { 265static struct mc13783_platform_data moboard_pmic = {
224 .regulators = moboard_regulators, 266 .regulators = moboard_regulators,
225 .num_regulators = ARRAY_SIZE(moboard_regulators), 267 .num_regulators = ARRAY_SIZE(moboard_regulators),
268 .leds = &moboard_leds,
226 .flags = MC13783_USE_REGULATOR | MC13783_USE_RTC | 269 .flags = MC13783_USE_REGULATOR | MC13783_USE_RTC |
227 MC13783_USE_ADC, 270 MC13783_USE_ADC | MC13783_USE_LED,
228}; 271};
229 272
230static struct spi_board_info moboard_spi_board_info[] __initdata = { 273static struct spi_board_info moboard_spi_board_info[] __initdata = {
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index 685f34a9634b..fe0de1698edc 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -240,22 +240,23 @@ error_fail:
240 240
241#define ORION_BLINK_HALF_PERIOD 100 /* ms */ 241#define ORION_BLINK_HALF_PERIOD 100 /* ms */
242 242
243static int dns323_gpio_blink_set(unsigned gpio, 243static int dns323_gpio_blink_set(unsigned gpio, int state,
244 unsigned long *delay_on, unsigned long *delay_off) 244 unsigned long *delay_on, unsigned long *delay_off)
245{ 245{
246 static int value = 0;
247 246
248 if (!*delay_on && !*delay_off) 247 if (delay_on && delay_off && !*delay_on && !*delay_off)
249 *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD; 248 *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD;
250 249
251 if (ORION_BLINK_HALF_PERIOD == *delay_on 250 switch(state) {
252 && ORION_BLINK_HALF_PERIOD == *delay_off) { 251 case GPIO_LED_NO_BLINK_LOW:
253 value = !value; 252 case GPIO_LED_NO_BLINK_HIGH:
254 orion_gpio_set_blink(gpio, value); 253 orion_gpio_set_blink(gpio, 0);
255 return 0; 254 gpio_set_value(gpio, state);
255 break;
256 case GPIO_LED_BLINK:
257 orion_gpio_set_blink(gpio, 1);
256 } 258 }
257 259 return 0;
258 return -EINVAL;
259} 260}
260 261
261static struct gpio_led dns323_leds[] = { 262static struct gpio_led dns323_leds[] = {
@@ -263,6 +264,7 @@ static struct gpio_led dns323_leds[] = {
263 .name = "power:blue", 264 .name = "power:blue",
264 .gpio = DNS323_GPIO_LED_POWER2, 265 .gpio = DNS323_GPIO_LED_POWER2,
265 .default_trigger = "timer", 266 .default_trigger = "timer",
267 .active_low = 1,
266 }, { 268 }, {
267 .name = "right:amber", 269 .name = "right:amber",
268 .gpio = DNS323_GPIO_LED_RIGHT_AMBER, 270 .gpio = DNS323_GPIO_LED_RIGHT_AMBER,
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 505eb64c329c..f98d17a7108b 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -67,6 +67,16 @@ config LEDS_NET48XX
67 This option enables support for the Soekris net4801 and net4826 error 67 This option enables support for the Soekris net4801 and net4826 error
68 LED. 68 LED.
69 69
70config LEDS_NET5501
71 tristate "LED Support for Soekris net5501 series Error LED"
72 depends on LEDS_CLASS && LEDS_TRIGGERS
73 depends on LEDS_GPIO_PLATFORM && GPIO_CS5535
74 select LEDS_TRIGGER_DEFAULT_ON
75 default n
76 help
77 Add support for the Soekris net5501 board (detection, error led
78 and GPIO).
79
70config LEDS_FSG 80config LEDS_FSG
71 tristate "LED Support for the Freecom FSG-3" 81 tristate "LED Support for the Freecom FSG-3"
72 depends on MACH_FSG 82 depends on MACH_FSG
@@ -285,6 +295,13 @@ config LEDS_DELL_NETBOOKS
285 This adds support for the Latitude 2100 and similar 295 This adds support for the Latitude 2100 and similar
286 notebooks that have an external LED. 296 notebooks that have an external LED.
287 297
298config LEDS_MC13783
299 tristate "LED Support for MC13783 PMIC"
300 depends on MFD_MC13783
301 help
302 This option enable support for on-chip LED drivers found
303 on Freescale Semiconductor MC13783 PMIC.
304
288config LEDS_TRIGGERS 305config LEDS_TRIGGERS
289 bool "LED Trigger support" 306 bool "LED Trigger support"
290 help 307 help
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 0cd8b9957380..2493de499374 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o
13obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o 13obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
14obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o 14obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
15obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o 15obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
16obj-$(CONFIG_LEDS_NET5501) += leds-net5501.o
16obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o 17obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
17obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o 18obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o
18obj-$(CONFIG_LEDS_H1940) += leds-h1940.o 19obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
@@ -35,6 +36,7 @@ obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o
35obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o 36obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o
36obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o 37obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o
37obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o 38obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o
39obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
38 40
39# LED SPI Drivers 41# LED SPI Drivers
40obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o 42obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 69e7d86a5143..260660076507 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -74,7 +74,7 @@ static ssize_t led_max_brightness_show(struct device *dev,
74 74
75static struct device_attribute led_class_attrs[] = { 75static struct device_attribute led_class_attrs[] = {
76 __ATTR(brightness, 0644, led_brightness_show, led_brightness_store), 76 __ATTR(brightness, 0644, led_brightness_show, led_brightness_store),
77 __ATTR(max_brightness, 0644, led_max_brightness_show, NULL), 77 __ATTR(max_brightness, 0444, led_max_brightness_show, NULL),
78#ifdef CONFIG_LEDS_TRIGGERS 78#ifdef CONFIG_LEDS_TRIGGERS
79 __ATTR(trigger, 0644, led_trigger_show, led_trigger_store), 79 __ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
80#endif 80#endif
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index 16a60c06c96c..b7677106cff8 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -256,8 +256,10 @@ static int pm860x_led_probe(struct platform_device *pdev)
256 if (pdev->dev.parent->platform_data) { 256 if (pdev->dev.parent->platform_data) {
257 pm860x_pdata = pdev->dev.parent->platform_data; 257 pm860x_pdata = pdev->dev.parent->platform_data;
258 pdata = pm860x_pdata->led; 258 pdata = pm860x_pdata->led;
259 } else 259 } else {
260 pdata = NULL; 260 dev_err(&pdev->dev, "missing platform data\n");
261 return -EINVAL;
262 }
261 263
262 data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); 264 data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL);
263 if (data == NULL) 265 if (data == NULL)
@@ -268,8 +270,11 @@ static int pm860x_led_probe(struct platform_device *pdev)
268 data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; 270 data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
269 data->iset = pdata->iset; 271 data->iset = pdata->iset;
270 data->port = __check_device(pdata, data->name); 272 data->port = __check_device(pdata, data->name);
271 if (data->port < 0) 273 if (data->port < 0) {
274 dev_err(&pdev->dev, "check device failed\n");
275 kfree(data);
272 return -EINVAL; 276 return -EINVAL;
277 }
273 278
274 data->current_brightness = 0; 279 data->current_brightness = 0;
275 data->cdev.name = data->name; 280 data->cdev.name = data->name;
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 6d94b0b9979c..26843dd6b859 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -26,7 +26,8 @@ struct gpio_led_data {
26 u8 new_level; 26 u8 new_level;
27 u8 can_sleep; 27 u8 can_sleep;
28 u8 active_low; 28 u8 active_low;
29 int (*platform_gpio_blink_set)(unsigned gpio, 29 u8 blinking;
30 int (*platform_gpio_blink_set)(unsigned gpio, int state,
30 unsigned long *delay_on, unsigned long *delay_off); 31 unsigned long *delay_on, unsigned long *delay_off);
31}; 32};
32 33
@@ -35,7 +36,13 @@ static void gpio_led_work(struct work_struct *work)
35 struct gpio_led_data *led_dat = 36 struct gpio_led_data *led_dat =
36 container_of(work, struct gpio_led_data, work); 37 container_of(work, struct gpio_led_data, work);
37 38
38 gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); 39 if (led_dat->blinking) {
40 led_dat->platform_gpio_blink_set(led_dat->gpio,
41 led_dat->new_level,
42 NULL, NULL);
43 led_dat->blinking = 0;
44 } else
45 gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
39} 46}
40 47
41static void gpio_led_set(struct led_classdev *led_cdev, 48static void gpio_led_set(struct led_classdev *led_cdev,
@@ -60,8 +67,14 @@ static void gpio_led_set(struct led_classdev *led_cdev,
60 if (led_dat->can_sleep) { 67 if (led_dat->can_sleep) {
61 led_dat->new_level = level; 68 led_dat->new_level = level;
62 schedule_work(&led_dat->work); 69 schedule_work(&led_dat->work);
63 } else 70 } else {
64 gpio_set_value(led_dat->gpio, level); 71 if (led_dat->blinking) {
72 led_dat->platform_gpio_blink_set(led_dat->gpio, level,
73 NULL, NULL);
74 led_dat->blinking = 0;
75 } else
76 gpio_set_value(led_dat->gpio, level);
77 }
65} 78}
66 79
67static int gpio_blink_set(struct led_classdev *led_cdev, 80static int gpio_blink_set(struct led_classdev *led_cdev,
@@ -70,12 +83,14 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
70 struct gpio_led_data *led_dat = 83 struct gpio_led_data *led_dat =
71 container_of(led_cdev, struct gpio_led_data, cdev); 84 container_of(led_cdev, struct gpio_led_data, cdev);
72 85
73 return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off); 86 led_dat->blinking = 1;
87 return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
88 delay_on, delay_off);
74} 89}
75 90
76static int __devinit create_gpio_led(const struct gpio_led *template, 91static int __devinit create_gpio_led(const struct gpio_led *template,
77 struct gpio_led_data *led_dat, struct device *parent, 92 struct gpio_led_data *led_dat, struct device *parent,
78 int (*blink_set)(unsigned, unsigned long *, unsigned long *)) 93 int (*blink_set)(unsigned, int, unsigned long *, unsigned long *))
79{ 94{
80 int ret, state; 95 int ret, state;
81 96
@@ -97,6 +112,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template,
97 led_dat->gpio = template->gpio; 112 led_dat->gpio = template->gpio;
98 led_dat->can_sleep = gpio_cansleep(template->gpio); 113 led_dat->can_sleep = gpio_cansleep(template->gpio);
99 led_dat->active_low = template->active_low; 114 led_dat->active_low = template->active_low;
115 led_dat->blinking = 0;
100 if (blink_set) { 116 if (blink_set) {
101 led_dat->platform_gpio_blink_set = blink_set; 117 led_dat->platform_gpio_blink_set = blink_set;
102 led_dat->cdev.blink_set = gpio_blink_set; 118 led_dat->cdev.blink_set = gpio_blink_set;
@@ -113,7 +129,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template,
113 ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state); 129 ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
114 if (ret < 0) 130 if (ret < 0)
115 goto err; 131 goto err;
116 132
117 INIT_WORK(&led_dat->work, gpio_led_work); 133 INIT_WORK(&led_dat->work, gpio_led_work);
118 134
119 ret = led_classdev_register(parent, &led_dat->cdev); 135 ret = led_classdev_register(parent, &led_dat->cdev);
@@ -234,6 +250,7 @@ static int __devinit of_gpio_leds_probe(struct of_device *ofdev,
234 led.gpio = of_get_gpio_flags(child, 0, &flags); 250 led.gpio = of_get_gpio_flags(child, 0, &flags);
235 led.active_low = flags & OF_GPIO_ACTIVE_LOW; 251 led.active_low = flags & OF_GPIO_ACTIVE_LOW;
236 led.name = of_get_property(child, "label", NULL) ? : child->name; 252 led.name = of_get_property(child, "label", NULL) ? : child->name;
253 led.blinking = 0;
237 led.default_trigger = 254 led.default_trigger =
238 of_get_property(child, "linux,default-trigger", NULL); 255 of_get_property(child, "linux,default-trigger", NULL);
239 state = of_get_property(child, "default-state", NULL); 256 state = of_get_property(child, "default-state", NULL);
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
index 8d5ecceba181..932a58da76c4 100644
--- a/drivers/leds/leds-lp3944.c
+++ b/drivers/leds/leds-lp3944.c
@@ -379,6 +379,7 @@ static int __devinit lp3944_probe(struct i2c_client *client,
379{ 379{
380 struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data; 380 struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data;
381 struct lp3944_data *data; 381 struct lp3944_data *data;
382 int err;
382 383
383 if (lp3944_pdata == NULL) { 384 if (lp3944_pdata == NULL) {
384 dev_err(&client->dev, "no platform data\n"); 385 dev_err(&client->dev, "no platform data\n");
@@ -401,9 +402,13 @@ static int __devinit lp3944_probe(struct i2c_client *client,
401 402
402 mutex_init(&data->lock); 403 mutex_init(&data->lock);
403 404
404 dev_info(&client->dev, "lp3944 enabled\n"); 405 err = lp3944_configure(client, data, lp3944_pdata);
406 if (err < 0) {
407 kfree(data);
408 return err;
409 }
405 410
406 lp3944_configure(client, data, lp3944_pdata); 411 dev_info(&client->dev, "lp3944 enabled\n");
407 return 0; 412 return 0;
408} 413}
409 414
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
new file mode 100644
index 000000000000..f05bb08d0f09
--- /dev/null
+++ b/drivers/leds/leds-mc13783.c
@@ -0,0 +1,403 @@
1/*
2 * LEDs driver for Freescale MC13783
3 *
4 * Copyright (C) 2010 Philippe Rétornaz
5 *
6 * Based on leds-da903x:
7 * Copyright (C) 2008 Compulab, Ltd.
8 * Mike Rapoport <mike@compulab.co.il>
9 *
10 * Copyright (C) 2006-2008 Marvell International Ltd.
11 * Eric Miao <eric.miao@marvell.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/platform_device.h>
22#include <linux/leds.h>
23#include <linux/workqueue.h>
24#include <linux/mfd/mc13783.h>
25#include <linux/slab.h>
26
27struct mc13783_led {
28 struct led_classdev cdev;
29 struct work_struct work;
30 struct mc13783 *master;
31 enum led_brightness new_brightness;
32 int id;
33};
34
35#define MC13783_REG_LED_CONTROL_0 51
36#define MC13783_LED_C0_ENABLE_BIT (1 << 0)
37#define MC13783_LED_C0_TRIODE_MD_BIT (1 << 7)
38#define MC13783_LED_C0_TRIODE_AD_BIT (1 << 8)
39#define MC13783_LED_C0_TRIODE_KP_BIT (1 << 9)
40#define MC13783_LED_C0_BOOST_BIT (1 << 10)
41#define MC13783_LED_C0_ABMODE_MASK 0x7
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{
74 struct mc13783_led *led = container_of(work, struct mc13783_led, work);
75 int reg = 0;
76 int mask = 0;
77 int value = 0;
78 int bank, off, shift;
79
80 switch (led->id) {
81 case MC13783_LED_MD:
82 reg = MC13783_REG_LED_CONTROL_2;
83 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_MD_P;
84 value = (led->new_brightness >> 4) << MC13783_LED_C2_MD_P;
85 break;
86 case MC13783_LED_AD:
87 reg = MC13783_REG_LED_CONTROL_2;
88 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_AD_P;
89 value = (led->new_brightness >> 4) << MC13783_LED_C2_AD_P;
90 break;
91 case MC13783_LED_KP:
92 reg = MC13783_REG_LED_CONTROL_2;
93 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_KP_P;
94 value = (led->new_brightness >> 4) << MC13783_LED_C2_KP_P;
95 break;
96 case MC13783_LED_R1:
97 case MC13783_LED_G1:
98 case MC13783_LED_B1:
99 case MC13783_LED_R2:
100 case MC13783_LED_G2:
101 case MC13783_LED_B2:
102 case MC13783_LED_R3:
103 case MC13783_LED_G3:
104 case MC13783_LED_B3:
105 off = led->id - MC13783_LED_R1;
106 bank = off/3;
107 reg = MC13783_REG_LED_CONTROL_3 + off/3;
108 shift = (off - bank * 3) * 5 + MC13783_LED_C3_TC_P;
109 value = (led->new_brightness >> 3) << shift;
110 mask = MC13783_LED_C3_TC_P_MASK << shift;
111 break;
112 }
113
114 mc13783_lock(led->master);
115
116 mc13783_reg_rmw(led->master, reg, mask, value);
117
118 mc13783_unlock(led->master);
119}
120
121static void mc13783_led_set(struct led_classdev *led_cdev,
122 enum led_brightness value)
123{
124 struct mc13783_led *led;
125
126 led = container_of(led_cdev, struct mc13783_led, cdev);
127 led->new_brightness = value;
128 schedule_work(&led->work);
129}
130
131static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
132{
133 int shift = 0;
134 int mask = 0;
135 int value = 0;
136 int reg = 0;
137 int ret, bank;
138
139 switch (led->id) {
140 case MC13783_LED_MD:
141 shift = MC13783_LED_C2_MD_C;
142 mask = MC13783_LED_C2_BL_C_MASK;
143 value = max_current & MC13783_LED_C2_BL_C_MASK;
144 reg = MC13783_REG_LED_CONTROL_2;
145 break;
146 case MC13783_LED_AD:
147 shift = MC13783_LED_C2_AD_C;
148 mask = MC13783_LED_C2_BL_C_MASK;
149 value = max_current & MC13783_LED_C2_BL_C_MASK;
150 reg = MC13783_REG_LED_CONTROL_2;
151 break;
152 case MC13783_LED_KP:
153 shift = MC13783_LED_C2_KP_C;
154 mask = MC13783_LED_C2_BL_C_MASK;
155 value = max_current & MC13783_LED_C2_BL_C_MASK;
156 reg = MC13783_REG_LED_CONTROL_2;
157 break;
158 case MC13783_LED_R1:
159 case MC13783_LED_G1:
160 case MC13783_LED_B1:
161 case MC13783_LED_R2:
162 case MC13783_LED_G2:
163 case MC13783_LED_B2:
164 case MC13783_LED_R3:
165 case MC13783_LED_G3:
166 case MC13783_LED_B3:
167 bank = (led->id - MC13783_LED_R1)/3;
168 reg = MC13783_REG_LED_CONTROL_3 + bank;
169 shift = ((led->id - MC13783_LED_R1) - bank * 3) * 2;
170 mask = MC13783_LED_Cx_TC_C_MASK;
171 value = max_current & MC13783_LED_Cx_TC_C_MASK;
172 break;
173 }
174
175 mc13783_lock(led->master);
176
177 ret = mc13783_reg_rmw(led->master, reg, mask << shift,
178 value << shift);
179
180 mc13783_unlock(led->master);
181 return ret;
182}
183
184static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
185{
186 struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
187 struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
188 int ret = 0;
189 int reg = 0;
190
191 mc13783_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 = mc13783_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 = mc13783_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
216 if (pdata->flags & MC13783_LED_TRIODE_TC1)
217 reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
218
219 ret = mc13783_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 = mc13783_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 = mc13783_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 = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, reg);
259
260out:
261 mc13783_unlock(dev);
262 return ret;
263}
264
265static int __devinit mc13783_led_probe(struct platform_device *pdev)
266{
267 struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
268 struct mc13783_led_platform_data *led_cur;
269 struct mc13783_led *led, *led_dat;
270 int ret, i;
271 int init_led = 0;
272
273 if (pdata == NULL) {
274 dev_err(&pdev->dev, "missing platform data\n");
275 return -ENODEV;
276 }
277
278 if (pdata->num_leds < 1 || pdata->num_leds > MC13783_LED_MAX) {
279 dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds);
280 return -EINVAL;
281 }
282
283 led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
284 if (led == NULL) {
285 dev_err(&pdev->dev, "failed to alloc memory\n");
286 return -ENOMEM;
287 }
288
289 ret = mc13783_leds_prepare(pdev);
290 if (ret) {
291 dev_err(&pdev->dev, "unable to init led driver\n");
292 goto err_free;
293 }
294
295 for (i = 0; i < pdata->num_leds; i++) {
296 led_dat = &led[i];
297 led_cur = &pdata->led[i];
298
299 if (led_cur->id > MC13783_LED_MAX || led_cur->id < 0) {
300 dev_err(&pdev->dev, "invalid id %d\n", led_cur->id);
301 ret = -EINVAL;
302 goto err_register;
303 }
304
305 if (init_led & (1 << led_cur->id)) {
306 dev_err(&pdev->dev, "led %d already initialized\n",
307 led_cur->id);
308 ret = -EINVAL;
309 goto err_register;
310 }
311
312 init_led |= 1 << led_cur->id;
313 led_dat->cdev.name = led_cur->name;
314 led_dat->cdev.default_trigger = led_cur->default_trigger;
315 led_dat->cdev.brightness_set = mc13783_led_set;
316 led_dat->cdev.brightness = LED_OFF;
317 led_dat->id = led_cur->id;
318 led_dat->master = dev_get_drvdata(pdev->dev.parent);
319
320 INIT_WORK(&led_dat->work, mc13783_led_work);
321
322 ret = led_classdev_register(pdev->dev.parent, &led_dat->cdev);
323 if (ret) {
324 dev_err(&pdev->dev, "failed to register led %d\n",
325 led_dat->id);
326 goto err_register;
327 }
328
329 ret = mc13783_led_setup(led_dat, led_cur->max_current);
330 if (ret) {
331 dev_err(&pdev->dev, "unable to init led %d\n",
332 led_dat->id);
333 i++;
334 goto err_register;
335 }
336 }
337
338 platform_set_drvdata(pdev, led);
339 return 0;
340
341err_register:
342 for (i = i - 1; i >= 0; i--) {
343 led_classdev_unregister(&led[i].cdev);
344 cancel_work_sync(&led[i].work);
345 }
346
347err_free:
348 kfree(led);
349 return ret;
350}
351
352static int __devexit mc13783_led_remove(struct platform_device *pdev)
353{
354 struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
355 struct mc13783_led *led = platform_get_drvdata(pdev);
356 struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
357 int i;
358
359 for (i = 0; i < pdata->num_leds; i++) {
360 led_classdev_unregister(&led[i].cdev);
361 cancel_work_sync(&led[i].work);
362 }
363
364 mc13783_lock(dev);
365
366 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, 0);
367 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, 0);
368 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, 0);
369 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, 0);
370 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, 0);
371 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, 0);
372
373 mc13783_unlock(dev);
374
375 kfree(led);
376 return 0;
377}
378
379static struct platform_driver mc13783_led_driver = {
380 .driver = {
381 .name = "mc13783-led",
382 .owner = THIS_MODULE,
383 },
384 .probe = mc13783_led_probe,
385 .remove = __devexit_p(mc13783_led_remove),
386};
387
388static int __init mc13783_led_init(void)
389{
390 return platform_driver_register(&mc13783_led_driver);
391}
392module_init(mc13783_led_init);
393
394static void __exit mc13783_led_exit(void)
395{
396 platform_driver_unregister(&mc13783_led_driver);
397}
398module_exit(mc13783_led_exit);
399
400MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC");
401MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>");
402MODULE_LICENSE("GPL");
403MODULE_ALIAS("platform:mc13783-led");
diff --git a/drivers/leds/leds-net5501.c b/drivers/leds/leds-net5501.c
new file mode 100644
index 000000000000..3063f591f0dc
--- /dev/null
+++ b/drivers/leds/leds-net5501.c
@@ -0,0 +1,94 @@
1/*
2 * Soekris board support code
3 *
4 * Copyright (C) 2008-2009 Tower Technologies
5 * Written by Alessandro Zummo <a.zummo@towertech.it>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/string.h>
16#include <linux/leds.h>
17#include <linux/platform_device.h>
18#include <linux/gpio.h>
19
20#include <asm/geode.h>
21
22static struct gpio_led net5501_leds[] = {
23 {
24 .name = "error",
25 .gpio = 6,
26 .default_trigger = "default-on",
27 },
28};
29
30static struct gpio_led_platform_data net5501_leds_data = {
31 .num_leds = ARRAY_SIZE(net5501_leds),
32 .leds = net5501_leds,
33};
34
35static struct platform_device net5501_leds_dev = {
36 .name = "leds-gpio",
37 .id = -1,
38 .dev.platform_data = &net5501_leds_data,
39};
40
41static void __init init_net5501(void)
42{
43 platform_device_register(&net5501_leds_dev);
44}
45
46struct soekris_board {
47 u16 offset;
48 char *sig;
49 u8 len;
50 void (*init)(void);
51};
52
53static struct soekris_board __initdata boards[] = {
54 { 0xb7b, "net5501", 7, init_net5501 }, /* net5501 v1.33/1.33c */
55 { 0xb1f, "net5501", 7, init_net5501 }, /* net5501 v1.32i */
56};
57
58static int __init soekris_init(void)
59{
60 int i;
61 unsigned char *rombase, *bios;
62
63 if (!is_geode())
64 return 0;
65
66 rombase = ioremap(0xffff0000, 0xffff);
67 if (!rombase) {
68 printk(KERN_INFO "Soekris net5501 LED driver failed to get rombase");
69 return 0;
70 }
71
72 bios = rombase + 0x20; /* null terminated */
73
74 if (strncmp(bios, "comBIOS", 7))
75 goto unmap;
76
77 for (i = 0; i < ARRAY_SIZE(boards); i++) {
78 unsigned char *model = rombase + boards[i].offset;
79
80 if (strncmp(model, boards[i].sig, boards[i].len) == 0) {
81 printk(KERN_INFO "Soekris %s: %s\n", model, bios);
82
83 if (boards[i].init)
84 boards[i].init();
85 break;
86 }
87 }
88
89unmap:
90 iounmap(rombase);
91 return 0;
92}
93
94arch_initcall(soekris_init);
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 51477ec71391..a688293abd0b 100644
--- a/drivers/leds/leds-ss4200.c
+++ b/drivers/leds/leds-ss4200.c
@@ -534,7 +534,7 @@ static int __init nas_gpio_init(void)
534 set_power_light_amber_noblink(); 534 set_power_light_amber_noblink();
535 return 0; 535 return 0;
536out_err: 536out_err:
537 for (; i >= 0; i--) 537 for (i--; i >= 0; i--)
538 unregister_nasgpio_led(i); 538 unregister_nasgpio_led(i);
539 pci_unregister_driver(&nas_gpio_pci_driver); 539 pci_unregister_driver(&nas_gpio_pci_driver);
540 return ret; 540 return ret;
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c
index 1f68ecadddc2..fecf38a4f025 100644
--- a/drivers/mfd/mc13783-core.c
+++ b/drivers/mfd/mc13783-core.c
@@ -679,6 +679,10 @@ err_revision:
679 if (pdata->flags & MC13783_USE_TOUCHSCREEN) 679 if (pdata->flags & MC13783_USE_TOUCHSCREEN)
680 mc13783_add_subdevice(mc13783, "mc13783-ts"); 680 mc13783_add_subdevice(mc13783, "mc13783-ts");
681 681
682 if (pdata->flags & MC13783_USE_LED)
683 mc13783_add_subdevice_pdata(mc13783, "mc13783-led",
684 pdata->leds, sizeof(*pdata->leds));
685
682 return 0; 686 return 0;
683} 687}
684 688
diff --git a/include/linux/leds.h b/include/linux/leds.h
index d8bf9665e70c..ba6986a11663 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -149,14 +149,18 @@ struct gpio_led {
149 unsigned default_state : 2; 149 unsigned default_state : 2;
150 /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */ 150 /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
151}; 151};
152#define LEDS_GPIO_DEFSTATE_OFF 0 152#define LEDS_GPIO_DEFSTATE_OFF 0
153#define LEDS_GPIO_DEFSTATE_ON 1 153#define LEDS_GPIO_DEFSTATE_ON 1
154#define LEDS_GPIO_DEFSTATE_KEEP 2 154#define LEDS_GPIO_DEFSTATE_KEEP 2
155 155
156struct gpio_led_platform_data { 156struct gpio_led_platform_data {
157 int num_leds; 157 int num_leds;
158 struct gpio_led *leds; 158 struct gpio_led *leds;
159 int (*gpio_blink_set)(unsigned gpio, 159
160#define GPIO_LED_NO_BLINK_LOW 0 /* No blink GPIO state low */
161#define GPIO_LED_NO_BLINK_HIGH 1 /* No blink GPIO state high */
162#define GPIO_LED_BLINK 2 /* Plase, blink */
163 int (*gpio_blink_set)(unsigned gpio, int state,
160 unsigned long *delay_on, 164 unsigned long *delay_on,
161 unsigned long *delay_off); 165 unsigned long *delay_off);
162}; 166};
diff --git a/include/linux/mfd/mc13783.h b/include/linux/mfd/mc13783.h
index 8895d9d8879c..4a894f688549 100644
--- a/include/linux/mfd/mc13783.h
+++ b/include/linux/mfd/mc13783.h
@@ -64,6 +64,70 @@ static inline int mc13783_ackirq(struct mc13783 *mc13783, int irq)
64 MC13783_ADC0_TSMOD1 | \ 64 MC13783_ADC0_TSMOD1 | \
65 MC13783_ADC0_TSMOD2) 65 MC13783_ADC0_TSMOD2)
66 66
67struct mc13783_led_platform_data {
68#define MC13783_LED_MD 0
69#define MC13783_LED_AD 1
70#define MC13783_LED_KP 2
71#define MC13783_LED_R1 3
72#define MC13783_LED_G1 4
73#define MC13783_LED_B1 5
74#define MC13783_LED_R2 6
75#define MC13783_LED_G2 7
76#define MC13783_LED_B2 8
77#define MC13783_LED_R3 9
78#define MC13783_LED_G3 10
79#define MC13783_LED_B3 11
80#define MC13783_LED_MAX MC13783_LED_B3
81 int id;
82 const char *name;
83 const char *default_trigger;
84
85/* Three or two bits current selection depending on the led */
86 char max_current;
87};
88
89struct mc13783_leds_platform_data {
90 int num_leds;
91 struct mc13783_led_platform_data *led;
92
93#define MC13783_LED_TRIODE_MD (1 << 0)
94#define MC13783_LED_TRIODE_AD (1 << 1)
95#define MC13783_LED_TRIODE_KP (1 << 2)
96#define MC13783_LED_BOOST_EN (1 << 3)
97#define MC13783_LED_TC1HALF (1 << 4)
98#define MC13783_LED_SLEWLIMTC (1 << 5)
99#define MC13783_LED_SLEWLIMBL (1 << 6)
100#define MC13783_LED_TRIODE_TC1 (1 << 7)
101#define MC13783_LED_TRIODE_TC2 (1 << 8)
102#define MC13783_LED_TRIODE_TC3 (1 << 9)
103 int flags;
104
105#define MC13783_LED_AB_DISABLED 0
106#define MC13783_LED_AB_MD1 1
107#define MC13783_LED_AB_MD12 2
108#define MC13783_LED_AB_MD123 3
109#define MC13783_LED_AB_MD1234 4
110#define MC13783_LED_AB_MD1234_AD1 5
111#define MC13783_LED_AB_MD1234_AD12 6
112#define MC13783_LED_AB_MD1_AD 7
113 char abmode;
114
115#define MC13783_LED_ABREF_200MV 0
116#define MC13783_LED_ABREF_400MV 1
117#define MC13783_LED_ABREF_600MV 2
118#define MC13783_LED_ABREF_800MV 3
119 char abref;
120
121#define MC13783_LED_PERIOD_10MS 0
122#define MC13783_LED_PERIOD_100MS 1
123#define MC13783_LED_PERIOD_500MS 2
124#define MC13783_LED_PERIOD_2S 3
125 char bl_period;
126 char tc1_period;
127 char tc2_period;
128 char tc3_period;
129};
130
67/* to be cleaned up */ 131/* to be cleaned up */
68struct regulator_init_data; 132struct regulator_init_data;
69 133
@@ -80,12 +144,14 @@ struct mc13783_regulator_platform_data {
80struct mc13783_platform_data { 144struct mc13783_platform_data {
81 int num_regulators; 145 int num_regulators;
82 struct mc13783_regulator_init_data *regulators; 146 struct mc13783_regulator_init_data *regulators;
147 struct mc13783_leds_platform_data *leds;
83 148
84#define MC13783_USE_TOUCHSCREEN (1 << 0) 149#define MC13783_USE_TOUCHSCREEN (1 << 0)
85#define MC13783_USE_CODEC (1 << 1) 150#define MC13783_USE_CODEC (1 << 1)
86#define MC13783_USE_ADC (1 << 2) 151#define MC13783_USE_ADC (1 << 2)
87#define MC13783_USE_RTC (1 << 3) 152#define MC13783_USE_RTC (1 << 3)
88#define MC13783_USE_REGULATOR (1 << 4) 153#define MC13783_USE_REGULATOR (1 << 4)
154#define MC13783_USE_LED (1 << 5)
89 unsigned int flags; 155 unsigned int flags;
90}; 156};
91 157