diff options
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/Kconfig | 10 | ||||
-rw-r--r-- | drivers/leds/Makefile | 1 | ||||
-rw-r--r-- | drivers/leds/led-triggers.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-88pm860x.c | 205 | ||||
-rw-r--r-- | drivers/leds/leds-lm3533.c | 6 | ||||
-rw-r--r-- | drivers/leds/leds-lp8788.c | 4 | ||||
-rw-r--r-- | drivers/leds/leds-netxbig.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-ns2.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-renesas-tpu.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-s3c24xx.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-wm8350.c | 2 | ||||
-rw-r--r-- | drivers/leds/ledtrig-cpu.c | 163 |
12 files changed, 283 insertions, 118 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index c96bbaadeebd..16578d3b52bb 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -506,6 +506,16 @@ config LEDS_TRIGGER_BACKLIGHT | |||
506 | 506 | ||
507 | If unsure, say N. | 507 | If unsure, say N. |
508 | 508 | ||
509 | config LEDS_TRIGGER_CPU | ||
510 | bool "LED CPU Trigger" | ||
511 | depends on LEDS_TRIGGERS | ||
512 | help | ||
513 | This allows LEDs to be controlled by active CPUs. This shows | ||
514 | the active CPUs across an array of LEDs so you can see which | ||
515 | CPUs are active on the system at any given moment. | ||
516 | |||
517 | If unsure, say N. | ||
518 | |||
509 | config LEDS_TRIGGER_GPIO | 519 | config LEDS_TRIGGER_GPIO |
510 | tristate "LED GPIO Trigger" | 520 | tristate "LED GPIO Trigger" |
511 | depends on LEDS_TRIGGERS | 521 | depends on LEDS_TRIGGERS |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index a4429a9217bc..a9b627c4f8ba 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -61,5 +61,6 @@ obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o | |||
61 | obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o | 61 | obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o |
62 | obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o | 62 | obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o |
63 | obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o | 63 | obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o |
64 | obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o | ||
64 | obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o | 65 | obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o |
65 | obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o | 66 | obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o |
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 6157cbbf4113..363975b3c925 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c | |||
@@ -224,7 +224,7 @@ void led_trigger_event(struct led_trigger *trig, | |||
224 | struct led_classdev *led_cdev; | 224 | struct led_classdev *led_cdev; |
225 | 225 | ||
226 | led_cdev = list_entry(entry, struct led_classdev, trig_list); | 226 | led_cdev = list_entry(entry, struct led_classdev, trig_list); |
227 | led_set_brightness(led_cdev, brightness); | 227 | __led_set_brightness(led_cdev, brightness); |
228 | } | 228 | } |
229 | read_unlock(&trig->leddev_list_lock); | 229 | read_unlock(&trig->leddev_list_lock); |
230 | } | 230 | } |
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 61897cfeeda6..b7e8cc0957fc 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/of.h> | ||
15 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
16 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
17 | #include <linux/leds.h> | 18 | #include <linux/leds.h> |
@@ -20,18 +21,12 @@ | |||
20 | #include <linux/mfd/88pm860x.h> | 21 | #include <linux/mfd/88pm860x.h> |
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
22 | 23 | ||
23 | #define LED_PWM_SHIFT (3) | ||
24 | #define LED_PWM_MASK (0x1F) | 24 | #define LED_PWM_MASK (0x1F) |
25 | #define LED_CURRENT_MASK (0x07 << 5) | 25 | #define LED_CURRENT_MASK (0x07 << 5) |
26 | 26 | ||
27 | #define LED_BLINK_ON_MASK (0x07) | ||
28 | #define LED_BLINK_MASK (0x7F) | 27 | #define LED_BLINK_MASK (0x7F) |
29 | 28 | ||
30 | #define LED_BLINK_ON(x) ((x & 0x7) * 66 + 66) | ||
31 | #define LED_BLINK_ON_MIN LED_BLINK_ON(0) | ||
32 | #define LED_BLINK_ON_MAX LED_BLINK_ON(0x7) | ||
33 | #define LED_ON_CONTINUOUS (0x0F << 3) | 29 | #define LED_ON_CONTINUOUS (0x0F << 3) |
34 | #define LED_TO_ON(x) ((x - 66) / 66) | ||
35 | 30 | ||
36 | #define LED1_BLINK_EN (1 << 1) | 31 | #define LED1_BLINK_EN (1 << 1) |
37 | #define LED2_BLINK_EN (1 << 2) | 32 | #define LED2_BLINK_EN (1 << 2) |
@@ -49,85 +44,25 @@ struct pm860x_led { | |||
49 | unsigned char brightness; | 44 | unsigned char brightness; |
50 | unsigned char current_brightness; | 45 | unsigned char current_brightness; |
51 | 46 | ||
52 | int blink_data; | 47 | int reg_control; |
53 | int blink_time; | 48 | int reg_blink; |
54 | int blink_on; | 49 | int blink_mask; |
55 | int blink_off; | ||
56 | }; | 50 | }; |
57 | 51 | ||
58 | /* return offset of color register */ | ||
59 | static inline int __led_off(int port) | ||
60 | { | ||
61 | int ret = -EINVAL; | ||
62 | |||
63 | switch (port) { | ||
64 | case PM8606_LED1_RED: | ||
65 | case PM8606_LED1_GREEN: | ||
66 | case PM8606_LED1_BLUE: | ||
67 | ret = port - PM8606_LED1_RED + PM8606_RGB1B; | ||
68 | break; | ||
69 | case PM8606_LED2_RED: | ||
70 | case PM8606_LED2_GREEN: | ||
71 | case PM8606_LED2_BLUE: | ||
72 | ret = port - PM8606_LED2_RED + PM8606_RGB2B; | ||
73 | break; | ||
74 | } | ||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | /* return offset of blink register */ | ||
79 | static inline int __blink_off(int port) | ||
80 | { | ||
81 | int ret = -EINVAL; | ||
82 | |||
83 | switch (port) { | ||
84 | case PM8606_LED1_RED: | ||
85 | case PM8606_LED1_GREEN: | ||
86 | case PM8606_LED1_BLUE: | ||
87 | ret = PM8606_RGB1A; | ||
88 | break; | ||
89 | case PM8606_LED2_RED: | ||
90 | case PM8606_LED2_GREEN: | ||
91 | case PM8606_LED2_BLUE: | ||
92 | ret = PM8606_RGB2A; | ||
93 | break; | ||
94 | } | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | static inline int __blink_ctl_mask(int port) | ||
99 | { | ||
100 | int ret = -EINVAL; | ||
101 | |||
102 | switch (port) { | ||
103 | case PM8606_LED1_RED: | ||
104 | case PM8606_LED1_GREEN: | ||
105 | case PM8606_LED1_BLUE: | ||
106 | ret = LED1_BLINK_EN; | ||
107 | break; | ||
108 | case PM8606_LED2_RED: | ||
109 | case PM8606_LED2_GREEN: | ||
110 | case PM8606_LED2_BLUE: | ||
111 | ret = LED2_BLINK_EN; | ||
112 | break; | ||
113 | } | ||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static int led_power_set(struct pm860x_chip *chip, int port, int on) | 52 | static int led_power_set(struct pm860x_chip *chip, int port, int on) |
118 | { | 53 | { |
119 | int ret = -EINVAL; | 54 | int ret = -EINVAL; |
120 | 55 | ||
121 | switch (port) { | 56 | switch (port) { |
122 | case PM8606_LED1_RED: | 57 | case 0: |
123 | case PM8606_LED1_GREEN: | 58 | case 1: |
124 | case PM8606_LED1_BLUE: | 59 | case 2: |
125 | ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) : | 60 | ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) : |
126 | pm8606_osc_disable(chip, RGB1_ENABLE); | 61 | pm8606_osc_disable(chip, RGB1_ENABLE); |
127 | break; | 62 | break; |
128 | case PM8606_LED2_RED: | 63 | case 3: |
129 | case PM8606_LED2_GREEN: | 64 | case 4: |
130 | case PM8606_LED2_BLUE: | 65 | case 5: |
131 | ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) : | 66 | ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) : |
132 | pm8606_osc_disable(chip, RGB2_ENABLE); | 67 | pm8606_osc_disable(chip, RGB2_ENABLE); |
133 | break; | 68 | break; |
@@ -141,7 +76,7 @@ static void pm860x_led_work(struct work_struct *work) | |||
141 | struct pm860x_led *led; | 76 | struct pm860x_led *led; |
142 | struct pm860x_chip *chip; | 77 | struct pm860x_chip *chip; |
143 | unsigned char buf[3]; | 78 | unsigned char buf[3]; |
144 | int mask, ret; | 79 | int ret; |
145 | 80 | ||
146 | led = container_of(work, struct pm860x_led, work); | 81 | led = container_of(work, struct pm860x_led, work); |
147 | chip = led->chip; | 82 | chip = led->chip; |
@@ -149,34 +84,34 @@ static void pm860x_led_work(struct work_struct *work) | |||
149 | if ((led->current_brightness == 0) && led->brightness) { | 84 | if ((led->current_brightness == 0) && led->brightness) { |
150 | led_power_set(chip, led->port, 1); | 85 | led_power_set(chip, led->port, 1); |
151 | if (led->iset) { | 86 | if (led->iset) { |
152 | pm860x_set_bits(led->i2c, __led_off(led->port), | 87 | pm860x_set_bits(led->i2c, led->reg_control, |
153 | LED_CURRENT_MASK, led->iset); | 88 | LED_CURRENT_MASK, led->iset); |
154 | } | 89 | } |
155 | pm860x_set_bits(led->i2c, __blink_off(led->port), | 90 | pm860x_set_bits(led->i2c, led->reg_blink, |
156 | LED_BLINK_MASK, LED_ON_CONTINUOUS); | 91 | LED_BLINK_MASK, LED_ON_CONTINUOUS); |
157 | mask = __blink_ctl_mask(led->port); | 92 | pm860x_set_bits(led->i2c, PM8606_WLED3B, led->blink_mask, |
158 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask); | 93 | led->blink_mask); |
159 | } | 94 | } |
160 | pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK, | 95 | pm860x_set_bits(led->i2c, led->reg_control, LED_PWM_MASK, |
161 | led->brightness); | 96 | led->brightness); |
162 | 97 | ||
163 | if (led->brightness == 0) { | 98 | if (led->brightness == 0) { |
164 | pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf); | 99 | pm860x_bulk_read(led->i2c, led->reg_control, 3, buf); |
165 | ret = buf[0] & LED_PWM_MASK; | 100 | ret = buf[0] & LED_PWM_MASK; |
166 | ret |= buf[1] & LED_PWM_MASK; | 101 | ret |= buf[1] & LED_PWM_MASK; |
167 | ret |= buf[2] & LED_PWM_MASK; | 102 | ret |= buf[2] & LED_PWM_MASK; |
168 | if (ret == 0) { | 103 | if (ret == 0) { |
169 | /* unset current since no led is lighting */ | 104 | /* unset current since no led is lighting */ |
170 | pm860x_set_bits(led->i2c, __led_off(led->port), | 105 | pm860x_set_bits(led->i2c, led->reg_control, |
171 | LED_CURRENT_MASK, 0); | 106 | LED_CURRENT_MASK, 0); |
172 | mask = __blink_ctl_mask(led->port); | 107 | pm860x_set_bits(led->i2c, PM8606_WLED3B, |
173 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); | 108 | led->blink_mask, 0); |
174 | led_power_set(chip, led->port, 0); | 109 | led_power_set(chip, led->port, 0); |
175 | } | 110 | } |
176 | } | 111 | } |
177 | led->current_brightness = led->brightness; | 112 | led->current_brightness = led->brightness; |
178 | dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", | 113 | dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", |
179 | __led_off(led->port), led->brightness); | 114 | led->reg_control, led->brightness); |
180 | mutex_unlock(&led->lock); | 115 | mutex_unlock(&led->lock); |
181 | } | 116 | } |
182 | 117 | ||
@@ -189,39 +124,92 @@ static void pm860x_led_set(struct led_classdev *cdev, | |||
189 | schedule_work(&data->work); | 124 | schedule_work(&data->work); |
190 | } | 125 | } |
191 | 126 | ||
127 | #ifdef CONFIG_OF | ||
128 | static int pm860x_led_dt_init(struct platform_device *pdev, | ||
129 | struct pm860x_led *data) | ||
130 | { | ||
131 | struct device_node *nproot = pdev->dev.parent->of_node, *np; | ||
132 | int iset = 0; | ||
133 | if (!nproot) | ||
134 | return -ENODEV; | ||
135 | nproot = of_find_node_by_name(nproot, "leds"); | ||
136 | if (!nproot) { | ||
137 | dev_err(&pdev->dev, "failed to find leds node\n"); | ||
138 | return -ENODEV; | ||
139 | } | ||
140 | for_each_child_of_node(nproot, np) { | ||
141 | if (!of_node_cmp(np->name, data->name)) { | ||
142 | of_property_read_u32(np, "marvell,88pm860x-iset", | ||
143 | &iset); | ||
144 | data->iset = PM8606_LED_CURRENT(iset); | ||
145 | break; | ||
146 | } | ||
147 | } | ||
148 | return 0; | ||
149 | } | ||
150 | #else | ||
151 | #define pm860x_led_dt_init(x, y) (-1) | ||
152 | #endif | ||
153 | |||
192 | static int pm860x_led_probe(struct platform_device *pdev) | 154 | static int pm860x_led_probe(struct platform_device *pdev) |
193 | { | 155 | { |
194 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | 156 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
195 | struct pm860x_led_pdata *pdata; | 157 | struct pm860x_led_pdata *pdata = pdev->dev.platform_data; |
196 | struct pm860x_led *data; | 158 | struct pm860x_led *data; |
197 | struct resource *res; | 159 | struct resource *res; |
198 | int ret; | 160 | int ret = 0; |
199 | |||
200 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
201 | if (res == NULL) { | ||
202 | dev_err(&pdev->dev, "No I/O resource!\n"); | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
206 | pdata = pdev->dev.platform_data; | ||
207 | if (pdata == NULL) { | ||
208 | dev_err(&pdev->dev, "No platform data!\n"); | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | 161 | ||
212 | data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_led), GFP_KERNEL); | 162 | data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_led), GFP_KERNEL); |
213 | if (data == NULL) | 163 | if (data == NULL) |
214 | return -ENOMEM; | 164 | return -ENOMEM; |
215 | strncpy(data->name, res->name, MFD_NAME_SIZE - 1); | 165 | res = platform_get_resource_byname(pdev, IORESOURCE_REG, "control"); |
166 | if (!res) { | ||
167 | dev_err(&pdev->dev, "No REG resource for control\n"); | ||
168 | ret = -ENXIO; | ||
169 | goto out; | ||
170 | } | ||
171 | data->reg_control = res->start; | ||
172 | res = platform_get_resource_byname(pdev, IORESOURCE_REG, "blink"); | ||
173 | if (!res) { | ||
174 | dev_err(&pdev->dev, "No REG resource for blink\n"); | ||
175 | ret = -ENXIO; | ||
176 | goto out; | ||
177 | } | ||
178 | data->reg_blink = res->start; | ||
179 | memset(data->name, 0, MFD_NAME_SIZE); | ||
180 | switch (pdev->id) { | ||
181 | case 0: | ||
182 | data->blink_mask = LED1_BLINK_EN; | ||
183 | sprintf(data->name, "led0-red"); | ||
184 | break; | ||
185 | case 1: | ||
186 | data->blink_mask = LED1_BLINK_EN; | ||
187 | sprintf(data->name, "led0-green"); | ||
188 | break; | ||
189 | case 2: | ||
190 | data->blink_mask = LED1_BLINK_EN; | ||
191 | sprintf(data->name, "led0-blue"); | ||
192 | break; | ||
193 | case 3: | ||
194 | data->blink_mask = LED2_BLINK_EN; | ||
195 | sprintf(data->name, "led1-red"); | ||
196 | break; | ||
197 | case 4: | ||
198 | data->blink_mask = LED2_BLINK_EN; | ||
199 | sprintf(data->name, "led1-green"); | ||
200 | break; | ||
201 | case 5: | ||
202 | data->blink_mask = LED2_BLINK_EN; | ||
203 | sprintf(data->name, "led1-blue"); | ||
204 | break; | ||
205 | } | ||
216 | dev_set_drvdata(&pdev->dev, data); | 206 | dev_set_drvdata(&pdev->dev, data); |
217 | data->chip = chip; | 207 | data->chip = chip; |
218 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; | 208 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; |
219 | data->iset = pdata->iset; | 209 | data->port = pdev->id; |
220 | data->port = pdata->flags; | 210 | if (pm860x_led_dt_init(pdev, data)) |
221 | if (data->port < 0) { | 211 | if (pdata) |
222 | dev_err(&pdev->dev, "check device failed\n"); | 212 | data->iset = pdata->iset; |
223 | return -EINVAL; | ||
224 | } | ||
225 | 213 | ||
226 | data->current_brightness = 0; | 214 | data->current_brightness = 0; |
227 | data->cdev.name = data->name; | 215 | data->cdev.name = data->name; |
@@ -236,6 +224,9 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
236 | } | 224 | } |
237 | pm860x_led_set(&data->cdev, 0); | 225 | pm860x_led_set(&data->cdev, 0); |
238 | return 0; | 226 | return 0; |
227 | out: | ||
228 | devm_kfree(&pdev->dev, data); | ||
229 | return ret; | ||
239 | } | 230 | } |
240 | 231 | ||
241 | static int pm860x_led_remove(struct platform_device *pdev) | 232 | static int pm860x_led_remove(struct platform_device *pdev) |
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c index f56b6e7ffdac..f6837b99908c 100644 --- a/drivers/leds/leds-lm3533.c +++ b/drivers/leds/leds-lm3533.c | |||
@@ -737,7 +737,7 @@ err_sysfs_remove: | |||
737 | sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group); | 737 | sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group); |
738 | err_unregister: | 738 | err_unregister: |
739 | led_classdev_unregister(&led->cdev); | 739 | led_classdev_unregister(&led->cdev); |
740 | flush_work_sync(&led->work); | 740 | flush_work(&led->work); |
741 | 741 | ||
742 | return ret; | 742 | return ret; |
743 | } | 743 | } |
@@ -751,7 +751,7 @@ static int __devexit lm3533_led_remove(struct platform_device *pdev) | |||
751 | lm3533_ctrlbank_disable(&led->cb); | 751 | lm3533_ctrlbank_disable(&led->cb); |
752 | sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group); | 752 | sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group); |
753 | led_classdev_unregister(&led->cdev); | 753 | led_classdev_unregister(&led->cdev); |
754 | flush_work_sync(&led->work); | 754 | flush_work(&led->work); |
755 | 755 | ||
756 | return 0; | 756 | return 0; |
757 | } | 757 | } |
@@ -765,7 +765,7 @@ static void lm3533_led_shutdown(struct platform_device *pdev) | |||
765 | 765 | ||
766 | lm3533_ctrlbank_disable(&led->cb); | 766 | lm3533_ctrlbank_disable(&led->cb); |
767 | lm3533_led_set(&led->cdev, LED_OFF); /* disable blink */ | 767 | lm3533_led_set(&led->cdev, LED_OFF); /* disable blink */ |
768 | flush_work_sync(&led->work); | 768 | flush_work(&led->work); |
769 | } | 769 | } |
770 | 770 | ||
771 | static struct platform_driver lm3533_led_driver = { | 771 | static struct platform_driver lm3533_led_driver = { |
diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c index 53bd136f1ef0..64009a176651 100644 --- a/drivers/leds/leds-lp8788.c +++ b/drivers/leds/leds-lp8788.c | |||
@@ -63,7 +63,7 @@ static int lp8788_led_init_device(struct lp8788_led *led, | |||
63 | /* scale configuration */ | 63 | /* scale configuration */ |
64 | addr = LP8788_ISINK_CTRL; | 64 | addr = LP8788_ISINK_CTRL; |
65 | mask = 1 << (cfg->num + LP8788_ISINK_SCALE_OFFSET); | 65 | mask = 1 << (cfg->num + LP8788_ISINK_SCALE_OFFSET); |
66 | val = cfg->scale << cfg->num; | 66 | val = cfg->scale << (cfg->num + LP8788_ISINK_SCALE_OFFSET); |
67 | ret = lp8788_update_bits(led->lp, addr, mask, val); | 67 | ret = lp8788_update_bits(led->lp, addr, mask, val); |
68 | if (ret) | 68 | if (ret) |
69 | return ret; | 69 | return ret; |
@@ -172,7 +172,7 @@ static int __devexit lp8788_led_remove(struct platform_device *pdev) | |||
172 | struct lp8788_led *led = platform_get_drvdata(pdev); | 172 | struct lp8788_led *led = platform_get_drvdata(pdev); |
173 | 173 | ||
174 | led_classdev_unregister(&led->led_dev); | 174 | led_classdev_unregister(&led->led_dev); |
175 | flush_work_sync(&led->work); | 175 | flush_work(&led->work); |
176 | 176 | ||
177 | return 0; | 177 | return 0; |
178 | } | 178 | } |
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index e37618e363cf..461bbf9b33fa 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/gpio.h> | 29 | #include <linux/gpio.h> |
30 | #include <linux/leds.h> | 30 | #include <linux/leds.h> |
31 | #include <mach/leds-netxbig.h> | 31 | #include <linux/platform_data/leds-kirkwood-netxbig.h> |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * GPIO extension bus. | 34 | * GPIO extension bus. |
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 10528dafb043..d176ec83f5d9 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/gpio.h> | 29 | #include <linux/gpio.h> |
30 | #include <linux/leds.h> | 30 | #include <linux/leds.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <mach/leds-ns2.h> | 32 | #include <linux/platform_data/leds-kirkwood-ns2.h> |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in | 35 | * The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in |
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c index 9ee12c28059a..771ea067e680 100644 --- a/drivers/leds/leds-renesas-tpu.c +++ b/drivers/leds/leds-renesas-tpu.c | |||
@@ -247,7 +247,7 @@ static int __devinit r_tpu_probe(struct platform_device *pdev) | |||
247 | 247 | ||
248 | if (!cfg) { | 248 | if (!cfg) { |
249 | dev_err(&pdev->dev, "missing platform data\n"); | 249 | dev_err(&pdev->dev, "missing platform data\n"); |
250 | goto err0; | 250 | return -ENODEV; |
251 | } | 251 | } |
252 | 252 | ||
253 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); | 253 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); |
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c index 942f0ea18178..e1a0df63a37f 100644 --- a/drivers/leds/leds-s3c24xx.c +++ b/drivers/leds/leds-s3c24xx.c | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
23 | #include <mach/regs-gpio.h> | 23 | #include <mach/regs-gpio.h> |
24 | #include <mach/leds-gpio.h> | 24 | #include <linux/platform_data/leds-s3c24xx.h> |
25 | 25 | ||
26 | /* our context */ | 26 | /* our context */ |
27 | 27 | ||
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c index 918d4baff1c7..4c62113f7a77 100644 --- a/drivers/leds/leds-wm8350.c +++ b/drivers/leds/leds-wm8350.c | |||
@@ -275,7 +275,7 @@ static int wm8350_led_remove(struct platform_device *pdev) | |||
275 | struct wm8350_led *led = platform_get_drvdata(pdev); | 275 | struct wm8350_led *led = platform_get_drvdata(pdev); |
276 | 276 | ||
277 | led_classdev_unregister(&led->cdev); | 277 | led_classdev_unregister(&led->cdev); |
278 | flush_work_sync(&led->work); | 278 | flush_work(&led->work); |
279 | wm8350_led_disable(led); | 279 | wm8350_led_disable(led); |
280 | regulator_put(led->dcdc); | 280 | regulator_put(led->dcdc); |
281 | regulator_put(led->isink); | 281 | regulator_put(led->isink); |
diff --git a/drivers/leds/ledtrig-cpu.c b/drivers/leds/ledtrig-cpu.c new file mode 100644 index 000000000000..b312056da14d --- /dev/null +++ b/drivers/leds/ledtrig-cpu.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * ledtrig-cpu.c - LED trigger based on CPU activity | ||
3 | * | ||
4 | * This LED trigger will be registered for each possible CPU and named as | ||
5 | * cpu0, cpu1, cpu2, cpu3, etc. | ||
6 | * | ||
7 | * It can be bound to any LED just like other triggers using either a | ||
8 | * board file or via sysfs interface. | ||
9 | * | ||
10 | * An API named ledtrig_cpu is exported for any user, who want to add CPU | ||
11 | * activity indication in their code | ||
12 | * | ||
13 | * Copyright 2011 Linus Walleij <linus.walleij@linaro.org> | ||
14 | * Copyright 2011 - 2012 Bryan Wu <bryan.wu@canonical.com> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License version 2 as | ||
18 | * published by the Free Software Foundation. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/percpu.h> | ||
27 | #include <linux/syscore_ops.h> | ||
28 | #include <linux/rwsem.h> | ||
29 | #include "leds.h" | ||
30 | |||
31 | #define MAX_NAME_LEN 8 | ||
32 | |||
33 | struct led_trigger_cpu { | ||
34 | char name[MAX_NAME_LEN]; | ||
35 | struct led_trigger *_trig; | ||
36 | struct mutex lock; | ||
37 | int lock_is_inited; | ||
38 | }; | ||
39 | |||
40 | static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); | ||
41 | |||
42 | /** | ||
43 | * ledtrig_cpu - emit a CPU event as a trigger | ||
44 | * @evt: CPU event to be emitted | ||
45 | * | ||
46 | * Emit a CPU event on a CPU core, which will trigger a | ||
47 | * binded LED to turn on or turn off. | ||
48 | */ | ||
49 | void ledtrig_cpu(enum cpu_led_event ledevt) | ||
50 | { | ||
51 | struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig); | ||
52 | |||
53 | /* mutex lock should be initialized before calling mutex_call() */ | ||
54 | if (!trig->lock_is_inited) | ||
55 | return; | ||
56 | |||
57 | mutex_lock(&trig->lock); | ||
58 | |||
59 | /* Locate the correct CPU LED */ | ||
60 | switch (ledevt) { | ||
61 | case CPU_LED_IDLE_END: | ||
62 | case CPU_LED_START: | ||
63 | /* Will turn the LED on, max brightness */ | ||
64 | led_trigger_event(trig->_trig, LED_FULL); | ||
65 | break; | ||
66 | |||
67 | case CPU_LED_IDLE_START: | ||
68 | case CPU_LED_STOP: | ||
69 | case CPU_LED_HALTED: | ||
70 | /* Will turn the LED off */ | ||
71 | led_trigger_event(trig->_trig, LED_OFF); | ||
72 | break; | ||
73 | |||
74 | default: | ||
75 | /* Will leave the LED as it is */ | ||
76 | break; | ||
77 | } | ||
78 | |||
79 | mutex_unlock(&trig->lock); | ||
80 | } | ||
81 | EXPORT_SYMBOL(ledtrig_cpu); | ||
82 | |||
83 | static int ledtrig_cpu_syscore_suspend(void) | ||
84 | { | ||
85 | ledtrig_cpu(CPU_LED_STOP); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static void ledtrig_cpu_syscore_resume(void) | ||
90 | { | ||
91 | ledtrig_cpu(CPU_LED_START); | ||
92 | } | ||
93 | |||
94 | static void ledtrig_cpu_syscore_shutdown(void) | ||
95 | { | ||
96 | ledtrig_cpu(CPU_LED_HALTED); | ||
97 | } | ||
98 | |||
99 | static struct syscore_ops ledtrig_cpu_syscore_ops = { | ||
100 | .shutdown = ledtrig_cpu_syscore_shutdown, | ||
101 | .suspend = ledtrig_cpu_syscore_suspend, | ||
102 | .resume = ledtrig_cpu_syscore_resume, | ||
103 | }; | ||
104 | |||
105 | static int __init ledtrig_cpu_init(void) | ||
106 | { | ||
107 | int cpu; | ||
108 | |||
109 | /* Supports up to 9999 cpu cores */ | ||
110 | BUILD_BUG_ON(CONFIG_NR_CPUS > 9999); | ||
111 | |||
112 | /* | ||
113 | * Registering CPU led trigger for each CPU core here | ||
114 | * ignores CPU hotplug, but after this CPU hotplug works | ||
115 | * fine with this trigger. | ||
116 | */ | ||
117 | for_each_possible_cpu(cpu) { | ||
118 | struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu); | ||
119 | |||
120 | mutex_init(&trig->lock); | ||
121 | |||
122 | snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu); | ||
123 | |||
124 | mutex_lock(&trig->lock); | ||
125 | led_trigger_register_simple(trig->name, &trig->_trig); | ||
126 | trig->lock_is_inited = 1; | ||
127 | mutex_unlock(&trig->lock); | ||
128 | } | ||
129 | |||
130 | register_syscore_ops(&ledtrig_cpu_syscore_ops); | ||
131 | |||
132 | pr_info("ledtrig-cpu: registered to indicate activity on CPUs\n"); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | module_init(ledtrig_cpu_init); | ||
137 | |||
138 | static void __exit ledtrig_cpu_exit(void) | ||
139 | { | ||
140 | int cpu; | ||
141 | |||
142 | for_each_possible_cpu(cpu) { | ||
143 | struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu); | ||
144 | |||
145 | mutex_lock(&trig->lock); | ||
146 | |||
147 | led_trigger_unregister_simple(trig->_trig); | ||
148 | trig->_trig = NULL; | ||
149 | memset(trig->name, 0, MAX_NAME_LEN); | ||
150 | trig->lock_is_inited = 0; | ||
151 | |||
152 | mutex_unlock(&trig->lock); | ||
153 | mutex_destroy(&trig->lock); | ||
154 | } | ||
155 | |||
156 | unregister_syscore_ops(&ledtrig_cpu_syscore_ops); | ||
157 | } | ||
158 | module_exit(ledtrig_cpu_exit); | ||
159 | |||
160 | MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); | ||
161 | MODULE_AUTHOR("Bryan Wu <bryan.wu@canonical.com>"); | ||
162 | MODULE_DESCRIPTION("CPU LED trigger"); | ||
163 | MODULE_LICENSE("GPL"); | ||