1 /*
2  * LP5521/LP5523/LP55231 Common Driver
3  *
4  * Copyright 2012 Texas Instruments
5  *
6  * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
7  *
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.
11  *
12  * Derived from leds-lp5521.c, leds-lp5523.c
13  */
14 
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>
21 
22 #include "leds-lp55xx-common.h"
23 
24 static struct lp55xx_led *cdev_to_lp55xx_led(struct led_classdev *cdev)
25 {
26 	return container_of(cdev, struct lp55xx_led, cdev);
27 }
28 
29 static struct lp55xx_led *dev_to_lp55xx_led(struct device *dev)
30 {
31 	return cdev_to_lp55xx_led(dev_get_drvdata(dev));
32 }
33 
34 static void lp55xx_reset_device(struct lp55xx_chip *chip)
35 {
36 	struct lp55xx_device_config *cfg = chip->cfg;
37 	u8 addr = cfg->reset.addr;
38 	u8 val  = cfg->reset.val;
39 
40 	/* no error checking here because no ACK from the device after reset */
41 	lp55xx_write(chip, addr, val);
42 }
43 
44 static int lp55xx_detect_device(struct lp55xx_chip *chip)
45 {
46 	struct lp55xx_device_config *cfg = chip->cfg;
47 	u8 addr = cfg->enable.addr;
48 	u8 val  = cfg->enable.val;
49 	int ret;
50 
51 	ret = lp55xx_write(chip, addr, val);
52 	if (ret)
53 		return ret;
54 
55 	usleep_range(1000, 2000);
56 
57 	ret = lp55xx_read(chip, addr, &val);
58 	if (ret)
59 		return ret;
60 
61 	if (val != cfg->enable.val)
62 		return -ENODEV;
63 
64 	return 0;
65 }
66 
67 static int lp55xx_post_init_device(struct lp55xx_chip *chip)
68 {
69 	struct lp55xx_device_config *cfg = chip->cfg;
70 
71 	if (!cfg->post_init_device)
72 		return 0;
73 
74 	return cfg->post_init_device(chip);
75 }
76 
77 static ssize_t lp55xx_show_current(struct device *dev,
78 			    struct device_attribute *attr,
79 			    char *buf)
80 {
81 	struct lp55xx_led *led = dev_to_lp55xx_led(dev);
82 
83 	return sprintf(buf, "%d\n", led->led_current);
84 }
85 
86 static ssize_t lp55xx_store_current(struct device *dev,
87 			     struct device_attribute *attr,
88 			     const char *buf, size_t len)
89 {
90 	struct lp55xx_led *led = dev_to_lp55xx_led(dev);
91 	struct lp55xx_chip *chip = led->chip;
92 	unsigned long curr;
93 
94 	if (kstrtoul(buf, 0, &curr))
95 		return -EINVAL;
96 
97 	if (curr > led->max_current)
98 		return -EINVAL;
99 
100 	if (!chip->cfg->set_led_current)
101 		return len;
102 
103 	mutex_lock(&chip->lock);
104 	chip->cfg->set_led_current(led, (u8)curr);
105 	mutex_unlock(&chip->lock);
106 
107 	return len;
108 }
109 
110 static ssize_t lp55xx_show_max_current(struct device *dev,
111 			    struct device_attribute *attr,
112 			    char *buf)
113 {
114 	struct lp55xx_led *led = dev_to_lp55xx_led(dev);
115 
116 	return sprintf(buf, "%d\n", led->max_current);
117 }
118 
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);
122 
123 static struct attribute *lp55xx_led_attributes[] = {
124 	&dev_attr_led_current.attr,
125 	&dev_attr_max_current.attr,
126 	NULL,
127 };
128 
129 static struct attribute_group lp55xx_led_attr_group = {
130 	.attrs = lp55xx_led_attributes
131 };
132 
133 static void lp55xx_set_brightness(struct led_classdev *cdev,
134 			     enum led_brightness brightness)
135 {
136 	struct lp55xx_led *led = cdev_to_lp55xx_led(cdev);
137 
138 	led->brightness = (u8)brightness;
139 	schedule_work(&led->brightness_work);
140 }
141 
142 static int lp55xx_init_led(struct lp55xx_led *led,
143 			struct lp55xx_chip *chip, int chan)
144 {
145 	struct lp55xx_platform_data *pdata = chip->pdata;
146 	struct lp55xx_device_config *cfg = chip->cfg;
147 	struct device *dev = &chip->cl->dev;
148 	char name[32];
149 	int ret;
150 	int max_channel = cfg->max_channel;
151 
152 	if (chan >= max_channel) {
153 		dev_err(dev, "invalid channel: %d / %d\n", chan, max_channel);
154 		return -EINVAL;
155 	}
156 
157 	if (pdata->led_config[chan].led_current == 0)
158 		return 0;
159 
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;
163 
164 	if (led->chan_nr >= max_channel) {
165 		dev_err(dev, "Use channel numbers between 0 and %d\n",
166 			max_channel - 1);
167 		return -EINVAL;
168 	}
169 
170 	led->cdev.brightness_set = lp55xx_set_brightness;
171 
172 	if (pdata->led_config[chan].name) {
173 		led->cdev.name = pdata->led_config[chan].name;
174 	} else {
175 		snprintf(name, sizeof(name), "%s:channel%d",
176 			pdata->label ? : chip->cl->name, chan);
177 		led->cdev.name = name;
178 	}
179 
180 	/*
181 	 * register led class device for each channel and
182 	 * add device attributes
183 	 */
184 
185 	ret = led_classdev_register(dev, &led->cdev);
186 	if (ret) {
187 		dev_err(dev, "led register err: %d\n", ret);
188 		return ret;
189 	}
190 
191 	ret = sysfs_create_group(&led->cdev.dev->kobj, &lp55xx_led_attr_group);
192 	if (ret) {
193 		dev_err(dev, "led sysfs err: %d\n", ret);
194 		led_classdev_unregister(&led->cdev);
195 		return ret;
196 	}
197 
198 	return 0;
199 }
200 
201 static void lp55xx_firmware_loaded(const struct firmware *fw, void *context)
202 {
203 	struct lp55xx_chip *chip = context;
204 	struct device *dev = &chip->cl->dev;
205 
206 	if (!fw) {
207 		dev_err(dev, "firmware request failed\n");
208 		goto out;
209 	}
210 
211 	/* handling firmware data is chip dependent */
212 	mutex_lock(&chip->lock);
213 
214 	chip->fw = fw;
215 	if (chip->cfg->firmware_cb)
216 		chip->cfg->firmware_cb(chip);
217 
218 	mutex_unlock(&chip->lock);
219 
220 out:
221 	/* firmware should be released for other channel use */
222 	release_firmware(chip->fw);
223 }
224 
225 static int lp55xx_request_firmware(struct lp55xx_chip *chip)
226 {
227 	const char *name = chip->cl->name;
228 	struct device *dev = &chip->cl->dev;
229 
230 	return request_firmware_nowait(THIS_MODULE, true, name, dev,
231 				GFP_KERNEL, chip, lp55xx_firmware_loaded);
232 }
233 
234 static ssize_t lp55xx_show_engine_select(struct device *dev,
235 			    struct device_attribute *attr,
236 			    char *buf)
237 {
238 	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
239 	struct lp55xx_chip *chip = led->chip;
240 
241 	return sprintf(buf, "%d\n", chip->engine_idx);
242 }
243 
244 static ssize_t lp55xx_store_engine_select(struct device *dev,
245 			     struct device_attribute *attr,
246 			     const char *buf, size_t len)
247 {
248 	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
249 	struct lp55xx_chip *chip = led->chip;
250 	unsigned long val;
251 	int ret;
252 
253 	if (kstrtoul(buf, 0, &val))
254 		return -EINVAL;
255 
256 	/* select the engine to be run */
257 
258 	switch (val) {
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);
266 		break;
267 	default:
268 		dev_err(dev, "%lu: invalid engine index. (1, 2, 3)\n", val);
269 		return -EINVAL;
270 	}
271 
272 	if (ret) {
273 		dev_err(dev, "request firmware err: %d\n", ret);
274 		return ret;
275 	}
276 
277 	return len;
278 }
279 
280 static inline void lp55xx_run_engine(struct lp55xx_chip *chip, bool start)
281 {
282 	if (chip->cfg->run_engine)
283 		chip->cfg->run_engine(chip, start);
284 }
285 
286 static ssize_t lp55xx_store_engine_run(struct device *dev,
287 			     struct device_attribute *attr,
288 			     const char *buf, size_t len)
289 {
290 	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
291 	struct lp55xx_chip *chip = led->chip;
292 	unsigned long val;
293 
294 	if (kstrtoul(buf, 0, &val))
295 		return -EINVAL;
296 
297 	/* run or stop the selected engine */
298 
299 	if (val <= 0) {
300 		lp55xx_run_engine(chip, false);
301 		return len;
302 	}
303 
304 	mutex_lock(&chip->lock);
305 	lp55xx_run_engine(chip, true);
306 	mutex_unlock(&chip->lock);
307 
308 	return len;
309 }
310 
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);
314 
315 static struct attribute *lp55xx_engine_attributes[] = {
316 	&dev_attr_select_engine.attr,
317 	&dev_attr_run_engine.attr,
318 	NULL,
319 };
320 
321 static const struct attribute_group lp55xx_engine_attr_group = {
322 	.attrs = lp55xx_engine_attributes,
323 };
324 
325 int lp55xx_write(struct lp55xx_chip *chip, u8 reg, u8 val)
326 {
327 	return i2c_smbus_write_byte_data(chip->cl, reg, val);
328 }
329 EXPORT_SYMBOL_GPL(lp55xx_write);
330 
331 int lp55xx_read(struct lp55xx_chip *chip, u8 reg, u8 *val)
332 {
333 	s32 ret;
334 
335 	ret = i2c_smbus_read_byte_data(chip->cl, reg);
336 	if (ret < 0)
337 		return ret;
338 
339 	*val = ret;
340 	return 0;
341 }
342 EXPORT_SYMBOL_GPL(lp55xx_read);
343 
344 int lp55xx_update_bits(struct lp55xx_chip *chip, u8 reg, u8 mask, u8 val)
345 {
346 	int ret;
347 	u8 tmp;
348 
349 	ret = lp55xx_read(chip, reg, &tmp);
350 	if (ret)
351 		return ret;
352 
353 	tmp &= ~mask;
354 	tmp |= val & mask;
355 
356 	return lp55xx_write(chip, reg, tmp);
357 }
358 EXPORT_SYMBOL_GPL(lp55xx_update_bits);
359 
360 int lp55xx_init_device(struct lp55xx_chip *chip)
361 {
362 	struct lp55xx_platform_data *pdata;
363 	struct lp55xx_device_config *cfg;
364 	struct device *dev = &chip->cl->dev;
365 	int ret = 0;
366 
367 	WARN_ON(!chip);
368 
369 	pdata = chip->pdata;
370 	cfg = chip->cfg;
371 
372 	if (!pdata || !cfg)
373 		return -EINVAL;
374 
375 	if (pdata->setup_resources) {
376 		ret = pdata->setup_resources();
377 		if (ret < 0) {
378 			dev_err(dev, "setup resoure err: %d\n", ret);
379 			goto err;
380 		}
381 	}
382 
383 	if (pdata->enable) {
384 		pdata->enable(0);
385 		usleep_range(1000, 2000); /* Keep enable down at least 1ms */
386 		pdata->enable(1);
387 		usleep_range(1000, 2000); /* 500us abs min. */
388 	}
389 
390 	lp55xx_reset_device(chip);
391 
392 	/*
393 	 * Exact value is not available. 10 - 20ms
394 	 * appears to be enough for reset.
395 	 */
396 	usleep_range(10000, 20000);
397 
398 	ret = lp55xx_detect_device(chip);
399 	if (ret) {
400 		dev_err(dev, "device detection err: %d\n", ret);
401 		goto err;
402 	}
403 
404 	/* chip specific initialization */
405 	ret = lp55xx_post_init_device(chip);
406 	if (ret) {
407 		dev_err(dev, "post init device err: %d\n", ret);
408 		goto err_post_init;
409 	}
410 
411 	return 0;
412 
413 err_post_init:
414 	lp55xx_deinit_device(chip);
415 err:
416 	return ret;
417 }
418 EXPORT_SYMBOL_GPL(lp55xx_init_device);
419 
420 void lp55xx_deinit_device(struct lp55xx_chip *chip)
421 {
422 	struct lp55xx_platform_data *pdata = chip->pdata;
423 
424 	if (pdata->enable)
425 		pdata->enable(0);
426 
427 	if (pdata->release_resources)
428 		pdata->release_resources();
429 }
430 EXPORT_SYMBOL_GPL(lp55xx_deinit_device);
431 
432 int lp55xx_register_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)
433 {
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;
438 	u8 led_current;
439 	int ret;
440 	int i;
441 
442 	if (!cfg->brightness_work_fn) {
443 		dev_err(&chip->cl->dev, "empty brightness configuration\n");
444 		return -EINVAL;
445 	}
446 
447 	for (i = 0; i < num_channels; i++) {
448 
449 		/* do not initialize channels that are not connected */
450 		if (pdata->led_config[i].led_current == 0)
451 			continue;
452 
453 		led_current = pdata->led_config[i].led_current;
454 		each = led + i;
455 		ret = lp55xx_init_led(each, chip, i);
456 		if (ret)
457 			goto err_init_led;
458 
459 		INIT_WORK(&each->brightness_work, cfg->brightness_work_fn);
460 
461 		chip->num_leds++;
462 		each->chip = chip;
463 
464 		/* setting led current at each channel */
465 		if (cfg->set_led_current)
466 			cfg->set_led_current(each, led_current);
467 	}
468 
469 	return 0;
470 
471 err_init_led:
472 	lp55xx_unregister_leds(led, chip);
473 	return ret;
474 }
475 EXPORT_SYMBOL_GPL(lp55xx_register_leds);
476 
477 void lp55xx_unregister_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)
478 {
479 	int i;
480 	struct lp55xx_led *each;
481 
482 	for (i = 0; i < chip->num_leds; i++) {
483 		each = led + i;
484 		led_classdev_unregister(&each->cdev);
485 		flush_work(&each->brightness_work);
486 	}
487 }
488 EXPORT_SYMBOL_GPL(lp55xx_unregister_leds);
489 
490 int lp55xx_register_sysfs(struct lp55xx_chip *chip)
491 {
492 	struct device *dev = &chip->cl->dev;
493 	struct lp55xx_device_config *cfg = chip->cfg;
494 	int ret;
495 
496 	if (!cfg->run_engine || !cfg->firmware_cb)
497 		goto dev_specific_attrs;
498 
499 	ret = sysfs_create_group(&dev->kobj, &lp55xx_engine_attr_group);
500 	if (ret)
501 		return ret;
502 
503 dev_specific_attrs:
504 	return cfg->dev_attr_group ?
505 		sysfs_create_group(&dev->kobj, cfg->dev_attr_group) : 0;
506 }
507 EXPORT_SYMBOL_GPL(lp55xx_register_sysfs);
508 
509 void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)
510 {
511 	struct device *dev = &chip->cl->dev;
512 	struct lp55xx_device_config *cfg = chip->cfg;
513 
514 	if (cfg->dev_attr_group)
515 		sysfs_remove_group(&dev->kobj, cfg->dev_attr_group);
516 
517 	sysfs_remove_group(&dev->kobj, &lp55xx_engine_attr_group);
518 }
519 EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);
520 
521 MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>");
522 MODULE_DESCRIPTION("LP55xx Common Driver");
523 MODULE_LICENSE("GPL");
524