0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 #include <linux/module.h>
0075 #include <linux/slab.h>
0076 #include <linux/leds.h>
0077 #include <linux/err.h>
0078 #include <linux/i2c.h>
0079 #include <linux/gpio/driver.h>
0080 #include <linux/property.h>
0081 #include <linux/workqueue.h>
0082
0083
0084 #define TCA6507_LS_LED_OFF 0x0
0085 #define TCA6507_LS_LED_OFF1 0x1
0086 #define TCA6507_LS_LED_PWM0 0x2
0087 #define TCA6507_LS_LED_PWM1 0x3
0088 #define TCA6507_LS_LED_ON 0x4
0089 #define TCA6507_LS_LED_MIR 0x5
0090 #define TCA6507_LS_BLINK0 0x6
0091 #define TCA6507_LS_BLINK1 0x7
0092
0093 struct tca6507_platform_data {
0094 struct led_platform_data leds;
0095 #ifdef CONFIG_GPIOLIB
0096 int gpio_base;
0097 #endif
0098 };
0099
0100 #define TCA6507_MAKE_GPIO 1
0101
0102 enum {
0103 BANK0,
0104 BANK1,
0105 MASTER,
0106 };
0107 static int bank_source[3] = {
0108 TCA6507_LS_LED_PWM0,
0109 TCA6507_LS_LED_PWM1,
0110 TCA6507_LS_LED_MIR,
0111 };
0112 static int blink_source[2] = {
0113 TCA6507_LS_BLINK0,
0114 TCA6507_LS_BLINK1,
0115 };
0116
0117
0118 #define TCA6507_REG_CNT 11
0119
0120
0121
0122
0123
0124 #define TCA6507_FADE_ON 0x03
0125 #define TCA6507_FULL_ON 0x04
0126 #define TCA6507_FADE_OFF 0x05
0127 #define TCA6507_FIRST_OFF 0x06
0128 #define TCA6507_SECOND_OFF 0x07
0129 #define TCA6507_MAX_INTENSITY 0x08
0130 #define TCA6507_MASTER_INTENSITY 0x09
0131 #define TCA6507_INITIALIZE 0x0A
0132
0133 #define INIT_CODE 0x8
0134
0135 #define TIMECODES 16
0136 static int time_codes[TIMECODES] = {
0137 0, 64, 128, 192, 256, 384, 512, 768,
0138 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
0139 };
0140
0141
0142 static inline int TO_LEVEL(int brightness)
0143 {
0144 return brightness >> 4;
0145 }
0146
0147
0148 static inline int TO_BRIGHT(int level)
0149 {
0150 if (level)
0151 return (level << 4) | 0xf;
0152 return 0;
0153 }
0154
0155 #define NUM_LEDS 7
0156 struct tca6507_chip {
0157 int reg_set;
0158
0159
0160 u8 reg_file[TCA6507_REG_CNT];
0161
0162 struct bank {
0163 int level;
0164 int ontime, offtime;
0165 int on_dflt, off_dflt;
0166 int time_use, level_use;
0167 } bank[3];
0168 struct i2c_client *client;
0169 struct work_struct work;
0170 spinlock_t lock;
0171
0172 struct tca6507_led {
0173 struct tca6507_chip *chip;
0174 struct led_classdev led_cdev;
0175 int num;
0176 int ontime, offtime;
0177 int on_dflt, off_dflt;
0178 int bank;
0179 int blink;
0180 } leds[NUM_LEDS];
0181 #ifdef CONFIG_GPIOLIB
0182 struct gpio_chip gpio;
0183 int gpio_map[NUM_LEDS];
0184 #endif
0185 };
0186
0187 static const struct i2c_device_id tca6507_id[] = {
0188 { "tca6507" },
0189 { }
0190 };
0191 MODULE_DEVICE_TABLE(i2c, tca6507_id);
0192
0193 static int choose_times(int msec, int *c1p, int *c2p)
0194 {
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209 int c1, c2;
0210 int tmax = msec * 9 / 8;
0211 int tmin = msec * 7 / 8;
0212 int diff = 65536;
0213
0214
0215
0216
0217 for (c1 = 1; c1 < TIMECODES; c1++) {
0218 int t = time_codes[c1];
0219 if (t*2 < tmin)
0220 continue;
0221 if (t > tmax)
0222 break;
0223 for (c2 = 0; c2 <= c1; c2++) {
0224 int tt = t + time_codes[c2];
0225 int d;
0226 if (tt < tmin)
0227 continue;
0228 if (tt > tmax)
0229 break;
0230
0231 d = abs(msec - tt);
0232 if (d >= diff)
0233 continue;
0234
0235 *c1p = c1;
0236 *c2p = c2;
0237 diff = d;
0238 if (d == 0)
0239 return msec;
0240 }
0241 }
0242 if (diff < 65536) {
0243 int actual;
0244 if (msec & 1) {
0245 swap(*c2p, *c1p);
0246 }
0247 actual = time_codes[*c1p] + time_codes[*c2p];
0248 if (*c1p < *c2p)
0249 return actual + 1;
0250 else
0251 return actual;
0252 }
0253
0254 return -EINVAL;
0255 }
0256
0257
0258
0259
0260
0261 static void set_select(struct tca6507_chip *tca, int led, int val)
0262 {
0263 int mask = (1 << led);
0264 int bit;
0265
0266 for (bit = 0; bit < 3; bit++) {
0267 int n = tca->reg_file[bit] & ~mask;
0268 if (val & (1 << bit))
0269 n |= mask;
0270 if (tca->reg_file[bit] != n) {
0271 tca->reg_file[bit] = n;
0272 tca->reg_set |= (1 << bit);
0273 }
0274 }
0275 }
0276
0277
0278
0279
0280
0281 static void set_code(struct tca6507_chip *tca, int reg, int bank, int new)
0282 {
0283 int mask = 0xF;
0284 int n;
0285 if (bank) {
0286 mask <<= 4;
0287 new <<= 4;
0288 }
0289 n = tca->reg_file[reg] & ~mask;
0290 n |= new;
0291 if (tca->reg_file[reg] != n) {
0292 tca->reg_file[reg] = n;
0293 tca->reg_set |= 1 << reg;
0294 }
0295 }
0296
0297
0298 static void set_level(struct tca6507_chip *tca, int bank, int level)
0299 {
0300 switch (bank) {
0301 case BANK0:
0302 case BANK1:
0303 set_code(tca, TCA6507_MAX_INTENSITY, bank, level);
0304 break;
0305 case MASTER:
0306 set_code(tca, TCA6507_MASTER_INTENSITY, 0, level);
0307 break;
0308 }
0309 tca->bank[bank].level = level;
0310 }
0311
0312
0313 static void set_times(struct tca6507_chip *tca, int bank)
0314 {
0315 int c1, c2;
0316 int result;
0317
0318 result = choose_times(tca->bank[bank].ontime, &c1, &c2);
0319 if (result < 0)
0320 return;
0321 dev_dbg(&tca->client->dev,
0322 "Chose on times %d(%d) %d(%d) for %dms\n",
0323 c1, time_codes[c1],
0324 c2, time_codes[c2], tca->bank[bank].ontime);
0325 set_code(tca, TCA6507_FADE_ON, bank, c2);
0326 set_code(tca, TCA6507_FULL_ON, bank, c1);
0327 tca->bank[bank].ontime = result;
0328
0329 result = choose_times(tca->bank[bank].offtime, &c1, &c2);
0330 dev_dbg(&tca->client->dev,
0331 "Chose off times %d(%d) %d(%d) for %dms\n",
0332 c1, time_codes[c1],
0333 c2, time_codes[c2], tca->bank[bank].offtime);
0334 set_code(tca, TCA6507_FADE_OFF, bank, c2);
0335 set_code(tca, TCA6507_FIRST_OFF, bank, c1);
0336 set_code(tca, TCA6507_SECOND_OFF, bank, c1);
0337 tca->bank[bank].offtime = result;
0338
0339 set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE);
0340 }
0341
0342
0343
0344 static void tca6507_work(struct work_struct *work)
0345 {
0346 struct tca6507_chip *tca = container_of(work, struct tca6507_chip,
0347 work);
0348 struct i2c_client *cl = tca->client;
0349 int set;
0350 u8 file[TCA6507_REG_CNT];
0351 int r;
0352
0353 spin_lock_irq(&tca->lock);
0354 set = tca->reg_set;
0355 memcpy(file, tca->reg_file, TCA6507_REG_CNT);
0356 tca->reg_set = 0;
0357 spin_unlock_irq(&tca->lock);
0358
0359 for (r = 0; r < TCA6507_REG_CNT; r++)
0360 if (set & (1<<r))
0361 i2c_smbus_write_byte_data(cl, r, file[r]);
0362 }
0363
0364 static void led_release(struct tca6507_led *led)
0365 {
0366
0367 struct tca6507_chip *tca = led->chip;
0368 if (led->bank >= 0) {
0369 struct bank *b = tca->bank + led->bank;
0370 if (led->blink)
0371 b->time_use--;
0372 b->level_use--;
0373 }
0374 led->blink = 0;
0375 led->bank = -1;
0376 }
0377
0378 static int led_prepare(struct tca6507_led *led)
0379 {
0380
0381
0382 int level = TO_LEVEL(led->led_cdev.brightness);
0383 struct tca6507_chip *tca = led->chip;
0384 int c1, c2;
0385 int i;
0386 struct bank *b;
0387 int need_init = 0;
0388
0389 led->led_cdev.brightness = TO_BRIGHT(level);
0390 if (level == 0) {
0391 set_select(tca, led->num, TCA6507_LS_LED_OFF);
0392 return 0;
0393 }
0394
0395 if (led->ontime == 0 || led->offtime == 0) {
0396
0397
0398
0399
0400
0401
0402 int best = -1;
0403 int diff = 15-level;
0404
0405 if (level == 15) {
0406 set_select(tca, led->num, TCA6507_LS_LED_ON);
0407 return 0;
0408 }
0409
0410 for (i = MASTER; i >= BANK0; i--) {
0411 int d;
0412 if (tca->bank[i].level == level ||
0413 tca->bank[i].level_use == 0) {
0414 best = i;
0415 break;
0416 }
0417 d = abs(level - tca->bank[i].level);
0418 if (d < diff) {
0419 diff = d;
0420 best = i;
0421 }
0422 }
0423 if (best == -1) {
0424
0425 set_select(tca, led->num, TCA6507_LS_LED_ON);
0426 led->led_cdev.brightness = LED_FULL;
0427 return 0;
0428 }
0429
0430 if (!tca->bank[best].level_use)
0431 set_level(tca, best, level);
0432
0433 tca->bank[best].level_use++;
0434 led->bank = best;
0435 set_select(tca, led->num, bank_source[best]);
0436 led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level);
0437 return 0;
0438 }
0439
0440
0441
0442
0443
0444
0445 if (choose_times(led->ontime, &c1, &c2) < 0)
0446 return -EINVAL;
0447 if (choose_times(led->offtime, &c1, &c2) < 0)
0448 return -EINVAL;
0449
0450 for (i = BANK0; i <= BANK1; i++) {
0451 if (tca->bank[i].level_use == 0)
0452
0453 break;
0454 if (tca->bank[i].level != level)
0455
0456
0457
0458
0459 continue;
0460
0461 if (tca->bank[i].time_use == 0)
0462
0463 break;
0464
0465 if (!(tca->bank[i].on_dflt ||
0466 led->on_dflt ||
0467 tca->bank[i].ontime == led->ontime))
0468
0469 continue;
0470
0471 if (!(tca->bank[i].off_dflt ||
0472 led->off_dflt ||
0473 tca->bank[i].offtime == led->offtime))
0474
0475 continue;
0476
0477
0478 break;
0479 }
0480
0481 if (i > BANK1)
0482
0483 return -EINVAL;
0484
0485 b = &tca->bank[i];
0486 if (b->level_use == 0)
0487 set_level(tca, i, level);
0488 b->level_use++;
0489 led->bank = i;
0490
0491 if (b->on_dflt ||
0492 !led->on_dflt ||
0493 b->time_use == 0) {
0494 b->ontime = led->ontime;
0495 b->on_dflt = led->on_dflt;
0496 need_init = 1;
0497 }
0498
0499 if (b->off_dflt ||
0500 !led->off_dflt ||
0501 b->time_use == 0) {
0502 b->offtime = led->offtime;
0503 b->off_dflt = led->off_dflt;
0504 need_init = 1;
0505 }
0506
0507 if (need_init)
0508 set_times(tca, i);
0509
0510 led->ontime = b->ontime;
0511 led->offtime = b->offtime;
0512
0513 b->time_use++;
0514 led->blink = 1;
0515 led->led_cdev.brightness = TO_BRIGHT(b->level);
0516 set_select(tca, led->num, blink_source[i]);
0517 return 0;
0518 }
0519
0520 static int led_assign(struct tca6507_led *led)
0521 {
0522 struct tca6507_chip *tca = led->chip;
0523 int err;
0524 unsigned long flags;
0525
0526 spin_lock_irqsave(&tca->lock, flags);
0527 led_release(led);
0528 err = led_prepare(led);
0529 if (err) {
0530
0531
0532
0533
0534 led->ontime = 0;
0535 led->offtime = 0;
0536 led_prepare(led);
0537 }
0538 spin_unlock_irqrestore(&tca->lock, flags);
0539
0540 if (tca->reg_set)
0541 schedule_work(&tca->work);
0542 return err;
0543 }
0544
0545 static void tca6507_brightness_set(struct led_classdev *led_cdev,
0546 enum led_brightness brightness)
0547 {
0548 struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
0549 led_cdev);
0550 led->led_cdev.brightness = brightness;
0551 led->ontime = 0;
0552 led->offtime = 0;
0553 led_assign(led);
0554 }
0555
0556 static int tca6507_blink_set(struct led_classdev *led_cdev,
0557 unsigned long *delay_on,
0558 unsigned long *delay_off)
0559 {
0560 struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
0561 led_cdev);
0562
0563 if (*delay_on == 0)
0564 led->on_dflt = 1;
0565 else if (delay_on != &led_cdev->blink_delay_on)
0566 led->on_dflt = 0;
0567 led->ontime = *delay_on;
0568
0569 if (*delay_off == 0)
0570 led->off_dflt = 1;
0571 else if (delay_off != &led_cdev->blink_delay_off)
0572 led->off_dflt = 0;
0573 led->offtime = *delay_off;
0574
0575 if (led->ontime == 0)
0576 led->ontime = 512;
0577 if (led->offtime == 0)
0578 led->offtime = 512;
0579
0580 if (led->led_cdev.brightness == LED_OFF)
0581 led->led_cdev.brightness = LED_FULL;
0582 if (led_assign(led) < 0) {
0583 led->ontime = 0;
0584 led->offtime = 0;
0585 led->led_cdev.brightness = LED_OFF;
0586 return -EINVAL;
0587 }
0588 *delay_on = led->ontime;
0589 *delay_off = led->offtime;
0590 return 0;
0591 }
0592
0593 #ifdef CONFIG_GPIOLIB
0594 static void tca6507_gpio_set_value(struct gpio_chip *gc,
0595 unsigned offset, int val)
0596 {
0597 struct tca6507_chip *tca = gpiochip_get_data(gc);
0598 unsigned long flags;
0599
0600 spin_lock_irqsave(&tca->lock, flags);
0601
0602
0603
0604
0605 set_select(tca, tca->gpio_map[offset],
0606 val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON);
0607 spin_unlock_irqrestore(&tca->lock, flags);
0608 if (tca->reg_set)
0609 schedule_work(&tca->work);
0610 }
0611
0612 static int tca6507_gpio_direction_output(struct gpio_chip *gc,
0613 unsigned offset, int val)
0614 {
0615 tca6507_gpio_set_value(gc, offset, val);
0616 return 0;
0617 }
0618
0619 static int tca6507_probe_gpios(struct device *dev,
0620 struct tca6507_chip *tca,
0621 struct tca6507_platform_data *pdata)
0622 {
0623 int err;
0624 int i = 0;
0625 int gpios = 0;
0626
0627 for (i = 0; i < NUM_LEDS; i++)
0628 if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) {
0629
0630 tca->gpio_map[gpios] = i;
0631 gpios++;
0632 }
0633
0634 if (!gpios)
0635 return 0;
0636
0637 tca->gpio.label = "gpio-tca6507";
0638 tca->gpio.ngpio = gpios;
0639 tca->gpio.base = pdata->gpio_base;
0640 tca->gpio.owner = THIS_MODULE;
0641 tca->gpio.direction_output = tca6507_gpio_direction_output;
0642 tca->gpio.set = tca6507_gpio_set_value;
0643 tca->gpio.parent = dev;
0644 err = gpiochip_add_data(&tca->gpio, tca);
0645 if (err) {
0646 tca->gpio.ngpio = 0;
0647 return err;
0648 }
0649 return 0;
0650 }
0651
0652 static void tca6507_remove_gpio(struct tca6507_chip *tca)
0653 {
0654 if (tca->gpio.ngpio)
0655 gpiochip_remove(&tca->gpio);
0656 }
0657 #else
0658 static int tca6507_probe_gpios(struct device *dev,
0659 struct tca6507_chip *tca,
0660 struct tca6507_platform_data *pdata)
0661 {
0662 return 0;
0663 }
0664 static void tca6507_remove_gpio(struct tca6507_chip *tca)
0665 {
0666 }
0667 #endif
0668
0669 static struct tca6507_platform_data *
0670 tca6507_led_dt_init(struct device *dev)
0671 {
0672 struct tca6507_platform_data *pdata;
0673 struct fwnode_handle *child;
0674 struct led_info *tca_leds;
0675 int count;
0676
0677 count = device_get_child_node_count(dev);
0678 if (!count || count > NUM_LEDS)
0679 return ERR_PTR(-ENODEV);
0680
0681 tca_leds = devm_kcalloc(dev, NUM_LEDS, sizeof(struct led_info),
0682 GFP_KERNEL);
0683 if (!tca_leds)
0684 return ERR_PTR(-ENOMEM);
0685
0686 device_for_each_child_node(dev, child) {
0687 struct led_info led;
0688 u32 reg;
0689 int ret;
0690
0691 if (fwnode_property_read_string(child, "label", &led.name))
0692 led.name = fwnode_get_name(child);
0693
0694 fwnode_property_read_string(child, "linux,default-trigger",
0695 &led.default_trigger);
0696
0697 led.flags = 0;
0698 if (fwnode_property_match_string(child, "compatible",
0699 "gpio") >= 0)
0700 led.flags |= TCA6507_MAKE_GPIO;
0701
0702 ret = fwnode_property_read_u32(child, "reg", ®);
0703 if (ret || reg >= NUM_LEDS) {
0704 fwnode_handle_put(child);
0705 return ERR_PTR(ret ? : -EINVAL);
0706 }
0707
0708 tca_leds[reg] = led;
0709 }
0710
0711 pdata = devm_kzalloc(dev, sizeof(struct tca6507_platform_data),
0712 GFP_KERNEL);
0713 if (!pdata)
0714 return ERR_PTR(-ENOMEM);
0715
0716 pdata->leds.leds = tca_leds;
0717 pdata->leds.num_leds = NUM_LEDS;
0718 #ifdef CONFIG_GPIOLIB
0719 pdata->gpio_base = -1;
0720 #endif
0721
0722 return pdata;
0723 }
0724
0725 static const struct of_device_id __maybe_unused of_tca6507_leds_match[] = {
0726 { .compatible = "ti,tca6507", },
0727 {},
0728 };
0729 MODULE_DEVICE_TABLE(of, of_tca6507_leds_match);
0730
0731 static int tca6507_probe(struct i2c_client *client,
0732 const struct i2c_device_id *id)
0733 {
0734 struct device *dev = &client->dev;
0735 struct i2c_adapter *adapter;
0736 struct tca6507_chip *tca;
0737 struct tca6507_platform_data *pdata;
0738 int err;
0739 int i = 0;
0740
0741 adapter = client->adapter;
0742
0743 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
0744 return -EIO;
0745
0746 pdata = tca6507_led_dt_init(dev);
0747 if (IS_ERR(pdata)) {
0748 dev_err(dev, "Need %d entries in platform-data list\n", NUM_LEDS);
0749 return PTR_ERR(pdata);
0750 }
0751 tca = devm_kzalloc(dev, sizeof(*tca), GFP_KERNEL);
0752 if (!tca)
0753 return -ENOMEM;
0754
0755 tca->client = client;
0756 INIT_WORK(&tca->work, tca6507_work);
0757 spin_lock_init(&tca->lock);
0758 i2c_set_clientdata(client, tca);
0759
0760 for (i = 0; i < NUM_LEDS; i++) {
0761 struct tca6507_led *l = tca->leds + i;
0762
0763 l->chip = tca;
0764 l->num = i;
0765 if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) {
0766 l->led_cdev.name = pdata->leds.leds[i].name;
0767 l->led_cdev.default_trigger
0768 = pdata->leds.leds[i].default_trigger;
0769 l->led_cdev.brightness_set = tca6507_brightness_set;
0770 l->led_cdev.blink_set = tca6507_blink_set;
0771 l->bank = -1;
0772 err = led_classdev_register(dev, &l->led_cdev);
0773 if (err < 0)
0774 goto exit;
0775 }
0776 }
0777 err = tca6507_probe_gpios(dev, tca, pdata);
0778 if (err)
0779 goto exit;
0780
0781 tca->reg_set = 0x7f;
0782 schedule_work(&tca->work);
0783
0784 return 0;
0785 exit:
0786 while (i--) {
0787 if (tca->leds[i].led_cdev.name)
0788 led_classdev_unregister(&tca->leds[i].led_cdev);
0789 }
0790 return err;
0791 }
0792
0793 static int tca6507_remove(struct i2c_client *client)
0794 {
0795 int i;
0796 struct tca6507_chip *tca = i2c_get_clientdata(client);
0797 struct tca6507_led *tca_leds = tca->leds;
0798
0799 for (i = 0; i < NUM_LEDS; i++) {
0800 if (tca_leds[i].led_cdev.name)
0801 led_classdev_unregister(&tca_leds[i].led_cdev);
0802 }
0803 tca6507_remove_gpio(tca);
0804 cancel_work_sync(&tca->work);
0805
0806 return 0;
0807 }
0808
0809 static struct i2c_driver tca6507_driver = {
0810 .driver = {
0811 .name = "leds-tca6507",
0812 .of_match_table = of_match_ptr(of_tca6507_leds_match),
0813 },
0814 .probe = tca6507_probe,
0815 .remove = tca6507_remove,
0816 .id_table = tca6507_id,
0817 };
0818
0819 module_i2c_driver(tca6507_driver);
0820
0821 MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
0822 MODULE_DESCRIPTION("TCA6507 LED/GPO driver");
0823 MODULE_LICENSE("GPL v2");