1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74#include <linux/module.h>
75#include <linux/slab.h>
76#include <linux/leds.h>
77#include <linux/err.h>
78#include <linux/i2c.h>
79#include <linux/gpio/driver.h>
80#include <linux/property.h>
81#include <linux/workqueue.h>
82
83
84#define TCA6507_LS_LED_OFF 0x0
85#define TCA6507_LS_LED_OFF1 0x1
86#define TCA6507_LS_LED_PWM0 0x2
87#define TCA6507_LS_LED_PWM1 0x3
88#define TCA6507_LS_LED_ON 0x4
89#define TCA6507_LS_LED_MIR 0x5
90#define TCA6507_LS_BLINK0 0x6
91#define TCA6507_LS_BLINK1 0x7
92
93struct tca6507_platform_data {
94 struct led_platform_data leds;
95#ifdef CONFIG_GPIOLIB
96 int gpio_base;
97#endif
98};
99
100#define TCA6507_MAKE_GPIO 1
101
102enum {
103 BANK0,
104 BANK1,
105 MASTER,
106};
107static int bank_source[3] = {
108 TCA6507_LS_LED_PWM0,
109 TCA6507_LS_LED_PWM1,
110 TCA6507_LS_LED_MIR,
111};
112static int blink_source[2] = {
113 TCA6507_LS_BLINK0,
114 TCA6507_LS_BLINK1,
115};
116
117
118#define TCA6507_REG_CNT 11
119
120
121
122
123
124#define TCA6507_FADE_ON 0x03
125#define TCA6507_FULL_ON 0x04
126#define TCA6507_FADE_OFF 0x05
127#define TCA6507_FIRST_OFF 0x06
128#define TCA6507_SECOND_OFF 0x07
129#define TCA6507_MAX_INTENSITY 0x08
130#define TCA6507_MASTER_INTENSITY 0x09
131#define TCA6507_INITIALIZE 0x0A
132
133#define INIT_CODE 0x8
134
135#define TIMECODES 16
136static int time_codes[TIMECODES] = {
137 0, 64, 128, 192, 256, 384, 512, 768,
138 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
139};
140
141
142static inline int TO_LEVEL(int brightness)
143{
144 return brightness >> 4;
145}
146
147
148static inline int TO_BRIGHT(int level)
149{
150 if (level)
151 return (level << 4) | 0xf;
152 return 0;
153}
154
155#define NUM_LEDS 7
156struct tca6507_chip {
157 int reg_set;
158
159
160 u8 reg_file[TCA6507_REG_CNT];
161
162 struct bank {
163 int level;
164 int ontime, offtime;
165 int on_dflt, off_dflt;
166 int time_use, level_use;
167 } bank[3];
168 struct i2c_client *client;
169 struct work_struct work;
170 spinlock_t lock;
171
172 struct tca6507_led {
173 struct tca6507_chip *chip;
174 struct led_classdev led_cdev;
175 int num;
176 int ontime, offtime;
177 int on_dflt, off_dflt;
178 int bank;
179 int blink;
180 } leds[NUM_LEDS];
181#ifdef CONFIG_GPIOLIB
182 struct gpio_chip gpio;
183 int gpio_map[NUM_LEDS];
184#endif
185};
186
187static const struct i2c_device_id tca6507_id[] = {
188 { "tca6507" },
189 { }
190};
191MODULE_DEVICE_TABLE(i2c, tca6507_id);
192
193static int choose_times(int msec, int *c1p, int *c2p)
194{
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 int c1, c2;
210 int tmax = msec * 9 / 8;
211 int tmin = msec * 7 / 8;
212 int diff = 65536;
213
214
215
216
217 for (c1 = 1; c1 < TIMECODES; c1++) {
218 int t = time_codes[c1];
219 if (t*2 < tmin)
220 continue;
221 if (t > tmax)
222 break;
223 for (c2 = 0; c2 <= c1; c2++) {
224 int tt = t + time_codes[c2];
225 int d;
226 if (tt < tmin)
227 continue;
228 if (tt > tmax)
229 break;
230
231 d = abs(msec - tt);
232 if (d >= diff)
233 continue;
234
235 *c1p = c1;
236 *c2p = c2;
237 diff = d;
238 if (d == 0)
239 return msec;
240 }
241 }
242 if (diff < 65536) {
243 int actual;
244 if (msec & 1) {
245 swap(*c2p, *c1p);
246 }
247 actual = time_codes[*c1p] + time_codes[*c2p];
248 if (*c1p < *c2p)
249 return actual + 1;
250 else
251 return actual;
252 }
253
254 return -EINVAL;
255}
256
257
258
259
260
261static void set_select(struct tca6507_chip *tca, int led, int val)
262{
263 int mask = (1 << led);
264 int bit;
265
266 for (bit = 0; bit < 3; bit++) {
267 int n = tca->reg_file[bit] & ~mask;
268 if (val & (1 << bit))
269 n |= mask;
270 if (tca->reg_file[bit] != n) {
271 tca->reg_file[bit] = n;
272 tca->reg_set |= (1 << bit);
273 }
274 }
275}
276
277
278
279
280
281static void set_code(struct tca6507_chip *tca, int reg, int bank, int new)
282{
283 int mask = 0xF;
284 int n;
285 if (bank) {
286 mask <<= 4;
287 new <<= 4;
288 }
289 n = tca->reg_file[reg] & ~mask;
290 n |= new;
291 if (tca->reg_file[reg] != n) {
292 tca->reg_file[reg] = n;
293 tca->reg_set |= 1 << reg;
294 }
295}
296
297
298static void set_level(struct tca6507_chip *tca, int bank, int level)
299{
300 switch (bank) {
301 case BANK0:
302 case BANK1:
303 set_code(tca, TCA6507_MAX_INTENSITY, bank, level);
304 break;
305 case MASTER:
306 set_code(tca, TCA6507_MASTER_INTENSITY, 0, level);
307 break;
308 }
309 tca->bank[bank].level = level;
310}
311
312
313static void set_times(struct tca6507_chip *tca, int bank)
314{
315 int c1, c2;
316 int result;
317
318 result = choose_times(tca->bank[bank].ontime, &c1, &c2);
319 if (result < 0)
320 return;
321 dev_dbg(&tca->client->dev,
322 "Chose on times %d(%d) %d(%d) for %dms\n",
323 c1, time_codes[c1],
324 c2, time_codes[c2], tca->bank[bank].ontime);
325 set_code(tca, TCA6507_FADE_ON, bank, c2);
326 set_code(tca, TCA6507_FULL_ON, bank, c1);
327 tca->bank[bank].ontime = result;
328
329 result = choose_times(tca->bank[bank].offtime, &c1, &c2);
330 dev_dbg(&tca->client->dev,
331 "Chose off times %d(%d) %d(%d) for %dms\n",
332 c1, time_codes[c1],
333 c2, time_codes[c2], tca->bank[bank].offtime);
334 set_code(tca, TCA6507_FADE_OFF, bank, c2);
335 set_code(tca, TCA6507_FIRST_OFF, bank, c1);
336 set_code(tca, TCA6507_SECOND_OFF, bank, c1);
337 tca->bank[bank].offtime = result;
338
339 set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE);
340}
341
342
343
344static void tca6507_work(struct work_struct *work)
345{
346 struct tca6507_chip *tca = container_of(work, struct tca6507_chip,
347 work);
348 struct i2c_client *cl = tca->client;
349 int set;
350 u8 file[TCA6507_REG_CNT];
351 int r;
352
353 spin_lock_irq(&tca->lock);
354 set = tca->reg_set;
355 memcpy(file, tca->reg_file, TCA6507_REG_CNT);
356 tca->reg_set = 0;
357 spin_unlock_irq(&tca->lock);
358
359 for (r = 0; r < TCA6507_REG_CNT; r++)
360 if (set & (1<<r))
361 i2c_smbus_write_byte_data(cl, r, file[r]);
362}
363
364static void led_release(struct tca6507_led *led)
365{
366
367 struct tca6507_chip *tca = led->chip;
368 if (led->bank >= 0) {
369 struct bank *b = tca->bank + led->bank;
370 if (led->blink)
371 b->time_use--;
372 b->level_use--;
373 }
374 led->blink = 0;
375 led->bank = -1;
376}
377
378static int led_prepare(struct tca6507_led *led)
379{
380
381
382 int level = TO_LEVEL(led->led_cdev.brightness);
383 struct tca6507_chip *tca = led->chip;
384 int c1, c2;
385 int i;
386 struct bank *b;
387 int need_init = 0;
388
389 led->led_cdev.brightness = TO_BRIGHT(level);
390 if (level == 0) {
391 set_select(tca, led->num, TCA6507_LS_LED_OFF);
392 return 0;
393 }
394
395 if (led->ontime == 0 || led->offtime == 0) {
396
397
398
399
400
401
402 int best = -1;
403 int diff = 15-level;
404
405 if (level == 15) {
406 set_select(tca, led->num, TCA6507_LS_LED_ON);
407 return 0;
408 }
409
410 for (i = MASTER; i >= BANK0; i--) {
411 int d;
412 if (tca->bank[i].level == level ||
413 tca->bank[i].level_use == 0) {
414 best = i;
415 break;
416 }
417 d = abs(level - tca->bank[i].level);
418 if (d < diff) {
419 diff = d;
420 best = i;
421 }
422 }
423 if (best == -1) {
424
425 set_select(tca, led->num, TCA6507_LS_LED_ON);
426 led->led_cdev.brightness = LED_FULL;
427 return 0;
428 }
429
430 if (!tca->bank[best].level_use)
431 set_level(tca, best, level);
432
433 tca->bank[best].level_use++;
434 led->bank = best;
435 set_select(tca, led->num, bank_source[best]);
436 led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level);
437 return 0;
438 }
439
440
441
442
443
444
445 if (choose_times(led->ontime, &c1, &c2) < 0)
446 return -EINVAL;
447 if (choose_times(led->offtime, &c1, &c2) < 0)
448 return -EINVAL;
449
450 for (i = BANK0; i <= BANK1; i++) {
451 if (tca->bank[i].level_use == 0)
452
453 break;
454 if (tca->bank[i].level != level)
455
456
457
458
459 continue;
460
461 if (tca->bank[i].time_use == 0)
462
463 break;
464
465 if (!(tca->bank[i].on_dflt ||
466 led->on_dflt ||
467 tca->bank[i].ontime == led->ontime))
468
469 continue;
470
471 if (!(tca->bank[i].off_dflt ||
472 led->off_dflt ||
473 tca->bank[i].offtime == led->offtime))
474
475 continue;
476
477
478 break;
479 }
480
481 if (i > BANK1)
482
483 return -EINVAL;
484
485 b = &tca->bank[i];
486 if (b->level_use == 0)
487 set_level(tca, i, level);
488 b->level_use++;
489 led->bank = i;
490
491 if (b->on_dflt ||
492 !led->on_dflt ||
493 b->time_use == 0) {
494 b->ontime = led->ontime;
495 b->on_dflt = led->on_dflt;
496 need_init = 1;
497 }
498
499 if (b->off_dflt ||
500 !led->off_dflt ||
501 b->time_use == 0) {
502 b->offtime = led->offtime;
503 b->off_dflt = led->off_dflt;
504 need_init = 1;
505 }
506
507 if (need_init)
508 set_times(tca, i);
509
510 led->ontime = b->ontime;
511 led->offtime = b->offtime;
512
513 b->time_use++;
514 led->blink = 1;
515 led->led_cdev.brightness = TO_BRIGHT(b->level);
516 set_select(tca, led->num, blink_source[i]);
517 return 0;
518}
519
520static int led_assign(struct tca6507_led *led)
521{
522 struct tca6507_chip *tca = led->chip;
523 int err;
524 unsigned long flags;
525
526 spin_lock_irqsave(&tca->lock, flags);
527 led_release(led);
528 err = led_prepare(led);
529 if (err) {
530
531
532
533
534 led->ontime = 0;
535 led->offtime = 0;
536 led_prepare(led);
537 }
538 spin_unlock_irqrestore(&tca->lock, flags);
539
540 if (tca->reg_set)
541 schedule_work(&tca->work);
542 return err;
543}
544
545static void tca6507_brightness_set(struct led_classdev *led_cdev,
546 enum led_brightness brightness)
547{
548 struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
549 led_cdev);
550 led->led_cdev.brightness = brightness;
551 led->ontime = 0;
552 led->offtime = 0;
553 led_assign(led);
554}
555
556static int tca6507_blink_set(struct led_classdev *led_cdev,
557 unsigned long *delay_on,
558 unsigned long *delay_off)
559{
560 struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
561 led_cdev);
562
563 if (*delay_on == 0)
564 led->on_dflt = 1;
565 else if (delay_on != &led_cdev->blink_delay_on)
566 led->on_dflt = 0;
567 led->ontime = *delay_on;
568
569 if (*delay_off == 0)
570 led->off_dflt = 1;
571 else if (delay_off != &led_cdev->blink_delay_off)
572 led->off_dflt = 0;
573 led->offtime = *delay_off;
574
575 if (led->ontime == 0)
576 led->ontime = 512;
577 if (led->offtime == 0)
578 led->offtime = 512;
579
580 if (led->led_cdev.brightness == LED_OFF)
581 led->led_cdev.brightness = LED_FULL;
582 if (led_assign(led) < 0) {
583 led->ontime = 0;
584 led->offtime = 0;
585 led->led_cdev.brightness = LED_OFF;
586 return -EINVAL;
587 }
588 *delay_on = led->ontime;
589 *delay_off = led->offtime;
590 return 0;
591}
592
593#ifdef CONFIG_GPIOLIB
594static void tca6507_gpio_set_value(struct gpio_chip *gc,
595 unsigned offset, int val)
596{
597 struct tca6507_chip *tca = gpiochip_get_data(gc);
598 unsigned long flags;
599
600 spin_lock_irqsave(&tca->lock, flags);
601
602
603
604
605 set_select(tca, tca->gpio_map[offset],
606 val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON);
607 spin_unlock_irqrestore(&tca->lock, flags);
608 if (tca->reg_set)
609 schedule_work(&tca->work);
610}
611
612static int tca6507_gpio_direction_output(struct gpio_chip *gc,
613 unsigned offset, int val)
614{
615 tca6507_gpio_set_value(gc, offset, val);
616 return 0;
617}
618
619static int tca6507_probe_gpios(struct device *dev,
620 struct tca6507_chip *tca,
621 struct tca6507_platform_data *pdata)
622{
623 int err;
624 int i = 0;
625 int gpios = 0;
626
627 for (i = 0; i < NUM_LEDS; i++)
628 if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) {
629
630 tca->gpio_map[gpios] = i;
631 gpios++;
632 }
633
634 if (!gpios)
635 return 0;
636
637 tca->gpio.label = "gpio-tca6507";
638 tca->gpio.ngpio = gpios;
639 tca->gpio.base = pdata->gpio_base;
640 tca->gpio.owner = THIS_MODULE;
641 tca->gpio.direction_output = tca6507_gpio_direction_output;
642 tca->gpio.set = tca6507_gpio_set_value;
643 tca->gpio.parent = dev;
644 err = gpiochip_add_data(&tca->gpio, tca);
645 if (err) {
646 tca->gpio.ngpio = 0;
647 return err;
648 }
649 return 0;
650}
651
652static void tca6507_remove_gpio(struct tca6507_chip *tca)
653{
654 if (tca->gpio.ngpio)
655 gpiochip_remove(&tca->gpio);
656}
657#else
658static int tca6507_probe_gpios(struct device *dev,
659 struct tca6507_chip *tca,
660 struct tca6507_platform_data *pdata)
661{
662 return 0;
663}
664static void tca6507_remove_gpio(struct tca6507_chip *tca)
665{
666}
667#endif
668
669static struct tca6507_platform_data *
670tca6507_led_dt_init(struct device *dev)
671{
672 struct tca6507_platform_data *pdata;
673 struct fwnode_handle *child;
674 struct led_info *tca_leds;
675 int count;
676
677 count = device_get_child_node_count(dev);
678 if (!count || count > NUM_LEDS)
679 return ERR_PTR(-ENODEV);
680
681 tca_leds = devm_kcalloc(dev, NUM_LEDS, sizeof(struct led_info),
682 GFP_KERNEL);
683 if (!tca_leds)
684 return ERR_PTR(-ENOMEM);
685
686 device_for_each_child_node(dev, child) {
687 struct led_info led;
688 u32 reg;
689 int ret;
690
691 if (fwnode_property_read_string(child, "label", &led.name))
692 led.name = fwnode_get_name(child);
693
694 fwnode_property_read_string(child, "linux,default-trigger",
695 &led.default_trigger);
696
697 led.flags = 0;
698 if (fwnode_property_match_string(child, "compatible",
699 "gpio") >= 0)
700 led.flags |= TCA6507_MAKE_GPIO;
701
702 ret = fwnode_property_read_u32(child, "reg", ®);
703 if (ret || reg >= NUM_LEDS) {
704 fwnode_handle_put(child);
705 return ERR_PTR(ret ? : -EINVAL);
706 }
707
708 tca_leds[reg] = led;
709 }
710
711 pdata = devm_kzalloc(dev, sizeof(struct tca6507_platform_data),
712 GFP_KERNEL);
713 if (!pdata)
714 return ERR_PTR(-ENOMEM);
715
716 pdata->leds.leds = tca_leds;
717 pdata->leds.num_leds = NUM_LEDS;
718#ifdef CONFIG_GPIOLIB
719 pdata->gpio_base = -1;
720#endif
721
722 return pdata;
723}
724
725static const struct of_device_id __maybe_unused of_tca6507_leds_match[] = {
726 { .compatible = "ti,tca6507", },
727 {},
728};
729MODULE_DEVICE_TABLE(of, of_tca6507_leds_match);
730
731static int tca6507_probe(struct i2c_client *client,
732 const struct i2c_device_id *id)
733{
734 struct device *dev = &client->dev;
735 struct i2c_adapter *adapter;
736 struct tca6507_chip *tca;
737 struct tca6507_platform_data *pdata;
738 int err;
739 int i = 0;
740
741 adapter = client->adapter;
742
743 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
744 return -EIO;
745
746 pdata = tca6507_led_dt_init(dev);
747 if (IS_ERR(pdata)) {
748 dev_err(dev, "Need %d entries in platform-data list\n", NUM_LEDS);
749 return PTR_ERR(pdata);
750 }
751 tca = devm_kzalloc(dev, sizeof(*tca), GFP_KERNEL);
752 if (!tca)
753 return -ENOMEM;
754
755 tca->client = client;
756 INIT_WORK(&tca->work, tca6507_work);
757 spin_lock_init(&tca->lock);
758 i2c_set_clientdata(client, tca);
759
760 for (i = 0; i < NUM_LEDS; i++) {
761 struct tca6507_led *l = tca->leds + i;
762
763 l->chip = tca;
764 l->num = i;
765 if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) {
766 l->led_cdev.name = pdata->leds.leds[i].name;
767 l->led_cdev.default_trigger
768 = pdata->leds.leds[i].default_trigger;
769 l->led_cdev.brightness_set = tca6507_brightness_set;
770 l->led_cdev.blink_set = tca6507_blink_set;
771 l->bank = -1;
772 err = led_classdev_register(dev, &l->led_cdev);
773 if (err < 0)
774 goto exit;
775 }
776 }
777 err = tca6507_probe_gpios(dev, tca, pdata);
778 if (err)
779 goto exit;
780
781 tca->reg_set = 0x7f;
782 schedule_work(&tca->work);
783
784 return 0;
785exit:
786 while (i--) {
787 if (tca->leds[i].led_cdev.name)
788 led_classdev_unregister(&tca->leds[i].led_cdev);
789 }
790 return err;
791}
792
793static int tca6507_remove(struct i2c_client *client)
794{
795 int i;
796 struct tca6507_chip *tca = i2c_get_clientdata(client);
797 struct tca6507_led *tca_leds = tca->leds;
798
799 for (i = 0; i < NUM_LEDS; i++) {
800 if (tca_leds[i].led_cdev.name)
801 led_classdev_unregister(&tca_leds[i].led_cdev);
802 }
803 tca6507_remove_gpio(tca);
804 cancel_work_sync(&tca->work);
805
806 return 0;
807}
808
809static struct i2c_driver tca6507_driver = {
810 .driver = {
811 .name = "leds-tca6507",
812 .of_match_table = of_match_ptr(of_tca6507_leds_match),
813 },
814 .probe = tca6507_probe,
815 .remove = tca6507_remove,
816 .id_table = tca6507_id,
817};
818
819module_i2c_driver(tca6507_driver);
820
821MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
822MODULE_DESCRIPTION("TCA6507 LED/GPO driver");
823MODULE_LICENSE("GPL v2");
824