2 * LP5521/LP5523/LP55231 Common Driver
4 * Copyright 2012 Texas Instruments
6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * Derived from leds-lp5521.c, leds-lp5523.c
15 #include <linux/delay.h>
16 #include <linux/firmware.h>
17 #include <linux/i2c.h>
18 #include <linux/leds.h>
19 #include <linux/module.h>
20 #include <linux/platform_data/leds-lp55xx.h>
22 #include "leds-lp55xx-common.h"
24 static struct lp55xx_led
*cdev_to_lp55xx_led(struct led_classdev
*cdev
)
26 return container_of(cdev
, struct lp55xx_led
, cdev
);
29 static struct lp55xx_led
*dev_to_lp55xx_led(struct device
*dev
)
31 return cdev_to_lp55xx_led(dev_get_drvdata(dev
));
34 static void lp55xx_reset_device(struct lp55xx_chip
*chip
)
36 struct lp55xx_device_config
*cfg
= chip
->cfg
;
37 u8 addr
= cfg
->reset
.addr
;
38 u8 val
= cfg
->reset
.val
;
40 /* no error checking here because no ACK from the device after reset */
41 lp55xx_write(chip
, addr
, val
);
44 static int lp55xx_detect_device(struct lp55xx_chip
*chip
)
46 struct lp55xx_device_config
*cfg
= chip
->cfg
;
47 u8 addr
= cfg
->enable
.addr
;
48 u8 val
= cfg
->enable
.val
;
51 ret
= lp55xx_write(chip
, addr
, val
);
55 usleep_range(1000, 2000);
57 ret
= lp55xx_read(chip
, addr
, &val
);
61 if (val
!= cfg
->enable
.val
)
67 static int lp55xx_post_init_device(struct lp55xx_chip
*chip
)
69 struct lp55xx_device_config
*cfg
= chip
->cfg
;
71 if (!cfg
->post_init_device
)
74 return cfg
->post_init_device(chip
);
77 static ssize_t
lp55xx_show_current(struct device
*dev
,
78 struct device_attribute
*attr
,
81 struct lp55xx_led
*led
= dev_to_lp55xx_led(dev
);
83 return sprintf(buf
, "%d\n", led
->led_current
);
86 static ssize_t
lp55xx_store_current(struct device
*dev
,
87 struct device_attribute
*attr
,
88 const char *buf
, size_t len
)
90 struct lp55xx_led
*led
= dev_to_lp55xx_led(dev
);
91 struct lp55xx_chip
*chip
= led
->chip
;
94 if (kstrtoul(buf
, 0, &curr
))
97 if (curr
> led
->max_current
)
100 if (!chip
->cfg
->set_led_current
)
103 mutex_lock(&chip
->lock
);
104 chip
->cfg
->set_led_current(led
, (u8
)curr
);
105 mutex_unlock(&chip
->lock
);
110 static ssize_t
lp55xx_show_max_current(struct device
*dev
,
111 struct device_attribute
*attr
,
114 struct lp55xx_led
*led
= dev_to_lp55xx_led(dev
);
116 return sprintf(buf
, "%d\n", led
->max_current
);
119 static DEVICE_ATTR(led_current
, S_IRUGO
| S_IWUSR
, lp55xx_show_current
,
120 lp55xx_store_current
);
121 static DEVICE_ATTR(max_current
, S_IRUGO
, lp55xx_show_max_current
, NULL
);
123 static struct attribute
*lp55xx_led_attributes
[] = {
124 &dev_attr_led_current
.attr
,
125 &dev_attr_max_current
.attr
,
129 static struct attribute_group lp55xx_led_attr_group
= {
130 .attrs
= lp55xx_led_attributes
133 static void lp55xx_set_brightness(struct led_classdev
*cdev
,
134 enum led_brightness brightness
)
136 struct lp55xx_led
*led
= cdev_to_lp55xx_led(cdev
);
138 led
->brightness
= (u8
)brightness
;
139 schedule_work(&led
->brightness_work
);
142 static int lp55xx_init_led(struct lp55xx_led
*led
,
143 struct lp55xx_chip
*chip
, int chan
)
145 struct lp55xx_platform_data
*pdata
= chip
->pdata
;
146 struct lp55xx_device_config
*cfg
= chip
->cfg
;
147 struct device
*dev
= &chip
->cl
->dev
;
150 int max_channel
= cfg
->max_channel
;
152 if (chan
>= max_channel
) {
153 dev_err(dev
, "invalid channel: %d / %d\n", chan
, max_channel
);
157 if (pdata
->led_config
[chan
].led_current
== 0)
160 led
->led_current
= pdata
->led_config
[chan
].led_current
;
161 led
->max_current
= pdata
->led_config
[chan
].max_current
;
162 led
->chan_nr
= pdata
->led_config
[chan
].chan_nr
;
164 if (led
->chan_nr
>= max_channel
) {
165 dev_err(dev
, "Use channel numbers between 0 and %d\n",
170 led
->cdev
.brightness_set
= lp55xx_set_brightness
;
172 if (pdata
->led_config
[chan
].name
) {
173 led
->cdev
.name
= pdata
->led_config
[chan
].name
;
175 snprintf(name
, sizeof(name
), "%s:channel%d",
176 pdata
->label
? : chip
->cl
->name
, chan
);
177 led
->cdev
.name
= name
;
181 * register led class device for each channel and
182 * add device attributes
185 ret
= led_classdev_register(dev
, &led
->cdev
);
187 dev_err(dev
, "led register err: %d\n", ret
);
191 ret
= sysfs_create_group(&led
->cdev
.dev
->kobj
, &lp55xx_led_attr_group
);
193 dev_err(dev
, "led sysfs err: %d\n", ret
);
194 led_classdev_unregister(&led
->cdev
);
201 static void lp55xx_firmware_loaded(const struct firmware
*fw
, void *context
)
203 struct lp55xx_chip
*chip
= context
;
204 struct device
*dev
= &chip
->cl
->dev
;
207 dev_err(dev
, "firmware request failed\n");
211 /* handling firmware data is chip dependent */
212 mutex_lock(&chip
->lock
);
215 if (chip
->cfg
->firmware_cb
)
216 chip
->cfg
->firmware_cb(chip
);
218 mutex_unlock(&chip
->lock
);
221 /* firmware should be released for other channel use */
222 release_firmware(chip
->fw
);
225 static int lp55xx_request_firmware(struct lp55xx_chip
*chip
)
227 const char *name
= chip
->cl
->name
;
228 struct device
*dev
= &chip
->cl
->dev
;
230 return request_firmware_nowait(THIS_MODULE
, true, name
, dev
,
231 GFP_KERNEL
, chip
, lp55xx_firmware_loaded
);
234 static ssize_t
lp55xx_show_engine_select(struct device
*dev
,
235 struct device_attribute
*attr
,
238 struct lp55xx_led
*led
= i2c_get_clientdata(to_i2c_client(dev
));
239 struct lp55xx_chip
*chip
= led
->chip
;
241 return sprintf(buf
, "%d\n", chip
->engine_idx
);
244 static ssize_t
lp55xx_store_engine_select(struct device
*dev
,
245 struct device_attribute
*attr
,
246 const char *buf
, size_t len
)
248 struct lp55xx_led
*led
= i2c_get_clientdata(to_i2c_client(dev
));
249 struct lp55xx_chip
*chip
= led
->chip
;
253 if (kstrtoul(buf
, 0, &val
))
256 /* select the engine to be run */
259 case LP55XX_ENGINE_1
:
260 case LP55XX_ENGINE_2
:
261 case LP55XX_ENGINE_3
:
262 mutex_lock(&chip
->lock
);
263 chip
->engine_idx
= val
;
264 ret
= lp55xx_request_firmware(chip
);
265 mutex_unlock(&chip
->lock
);
268 dev_err(dev
, "%lu: invalid engine index. (1, 2, 3)\n", val
);
273 dev_err(dev
, "request firmware err: %d\n", ret
);
280 static inline void lp55xx_run_engine(struct lp55xx_chip
*chip
, bool start
)
282 if (chip
->cfg
->run_engine
)
283 chip
->cfg
->run_engine(chip
, start
);
286 static ssize_t
lp55xx_store_engine_run(struct device
*dev
,
287 struct device_attribute
*attr
,
288 const char *buf
, size_t len
)
290 struct lp55xx_led
*led
= i2c_get_clientdata(to_i2c_client(dev
));
291 struct lp55xx_chip
*chip
= led
->chip
;
294 if (kstrtoul(buf
, 0, &val
))
297 /* run or stop the selected engine */
300 lp55xx_run_engine(chip
, false);
304 mutex_lock(&chip
->lock
);
305 lp55xx_run_engine(chip
, true);
306 mutex_unlock(&chip
->lock
);
311 static DEVICE_ATTR(select_engine
, S_IRUGO
| S_IWUSR
,
312 lp55xx_show_engine_select
, lp55xx_store_engine_select
);
313 static DEVICE_ATTR(run_engine
, S_IWUSR
, NULL
, lp55xx_store_engine_run
);
315 static struct attribute
*lp55xx_engine_attributes
[] = {
316 &dev_attr_select_engine
.attr
,
317 &dev_attr_run_engine
.attr
,
321 static const struct attribute_group lp55xx_engine_attr_group
= {
322 .attrs
= lp55xx_engine_attributes
,
325 int lp55xx_write(struct lp55xx_chip
*chip
, u8 reg
, u8 val
)
327 return i2c_smbus_write_byte_data(chip
->cl
, reg
, val
);
329 EXPORT_SYMBOL_GPL(lp55xx_write
);
331 int lp55xx_read(struct lp55xx_chip
*chip
, u8 reg
, u8
*val
)
335 ret
= i2c_smbus_read_byte_data(chip
->cl
, reg
);
342 EXPORT_SYMBOL_GPL(lp55xx_read
);
344 int lp55xx_update_bits(struct lp55xx_chip
*chip
, u8 reg
, u8 mask
, u8 val
)
349 ret
= lp55xx_read(chip
, reg
, &tmp
);
356 return lp55xx_write(chip
, reg
, tmp
);
358 EXPORT_SYMBOL_GPL(lp55xx_update_bits
);
360 int lp55xx_init_device(struct lp55xx_chip
*chip
)
362 struct lp55xx_platform_data
*pdata
;
363 struct lp55xx_device_config
*cfg
;
364 struct device
*dev
= &chip
->cl
->dev
;
375 if (pdata
->setup_resources
) {
376 ret
= pdata
->setup_resources();
378 dev_err(dev
, "setup resoure err: %d\n", ret
);
385 usleep_range(1000, 2000); /* Keep enable down at least 1ms */
387 usleep_range(1000, 2000); /* 500us abs min. */
390 lp55xx_reset_device(chip
);
393 * Exact value is not available. 10 - 20ms
394 * appears to be enough for reset.
396 usleep_range(10000, 20000);
398 ret
= lp55xx_detect_device(chip
);
400 dev_err(dev
, "device detection err: %d\n", ret
);
404 /* chip specific initialization */
405 ret
= lp55xx_post_init_device(chip
);
407 dev_err(dev
, "post init device err: %d\n", ret
);
414 lp55xx_deinit_device(chip
);
418 EXPORT_SYMBOL_GPL(lp55xx_init_device
);
420 void lp55xx_deinit_device(struct lp55xx_chip
*chip
)
422 struct lp55xx_platform_data
*pdata
= chip
->pdata
;
427 if (pdata
->release_resources
)
428 pdata
->release_resources();
430 EXPORT_SYMBOL_GPL(lp55xx_deinit_device
);
432 int lp55xx_register_leds(struct lp55xx_led
*led
, struct lp55xx_chip
*chip
)
434 struct lp55xx_platform_data
*pdata
= chip
->pdata
;
435 struct lp55xx_device_config
*cfg
= chip
->cfg
;
436 int num_channels
= pdata
->num_channels
;
437 struct lp55xx_led
*each
;
442 if (!cfg
->brightness_work_fn
) {
443 dev_err(&chip
->cl
->dev
, "empty brightness configuration\n");
447 for (i
= 0; i
< num_channels
; i
++) {
449 /* do not initialize channels that are not connected */
450 if (pdata
->led_config
[i
].led_current
== 0)
453 led_current
= pdata
->led_config
[i
].led_current
;
455 ret
= lp55xx_init_led(each
, chip
, i
);
459 INIT_WORK(&each
->brightness_work
, cfg
->brightness_work_fn
);
464 /* setting led current at each channel */
465 if (cfg
->set_led_current
)
466 cfg
->set_led_current(each
, led_current
);
472 lp55xx_unregister_leds(led
, chip
);
475 EXPORT_SYMBOL_GPL(lp55xx_register_leds
);
477 void lp55xx_unregister_leds(struct lp55xx_led
*led
, struct lp55xx_chip
*chip
)
480 struct lp55xx_led
*each
;
482 for (i
= 0; i
< chip
->num_leds
; i
++) {
484 led_classdev_unregister(&each
->cdev
);
485 flush_work(&each
->brightness_work
);
488 EXPORT_SYMBOL_GPL(lp55xx_unregister_leds
);
490 int lp55xx_register_sysfs(struct lp55xx_chip
*chip
)
492 struct device
*dev
= &chip
->cl
->dev
;
493 struct lp55xx_device_config
*cfg
= chip
->cfg
;
496 if (!cfg
->run_engine
|| !cfg
->firmware_cb
)
497 goto dev_specific_attrs
;
499 ret
= sysfs_create_group(&dev
->kobj
, &lp55xx_engine_attr_group
);
504 return cfg
->dev_attr_group
?
505 sysfs_create_group(&dev
->kobj
, cfg
->dev_attr_group
) : 0;
507 EXPORT_SYMBOL_GPL(lp55xx_register_sysfs
);
509 void lp55xx_unregister_sysfs(struct lp55xx_chip
*chip
)
511 struct device
*dev
= &chip
->cl
->dev
;
512 struct lp55xx_device_config
*cfg
= chip
->cfg
;
514 if (cfg
->dev_attr_group
)
515 sysfs_remove_group(&dev
->kobj
, cfg
->dev_attr_group
);
517 sysfs_remove_group(&dev
->kobj
, &lp55xx_engine_attr_group
);
519 EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs
);
521 MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>");
522 MODULE_DESCRIPTION("LP55xx Common Driver");
523 MODULE_LICENSE("GPL");