109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2a6d511e5SNeilBrown /* 3a6d511e5SNeilBrown * leds-tca6507 4a6d511e5SNeilBrown * 5a6d511e5SNeilBrown * The TCA6507 is a programmable LED controller that can drive 7 6a6d511e5SNeilBrown * separate lines either by holding them low, or by pulsing them 7a6d511e5SNeilBrown * with modulated width. 81f431afdSNeilBrown * The modulation can be varied in a simple pattern to produce a 91f431afdSNeilBrown * blink or double-blink. 10a6d511e5SNeilBrown * 111f431afdSNeilBrown * This driver can configure each line either as a 'GPIO' which is 121f431afdSNeilBrown * out-only (pull-up resistor required) or as an LED with variable 131f431afdSNeilBrown * brightness and hardware-assisted blinking. 14a6d511e5SNeilBrown * 151f431afdSNeilBrown * Apart from OFF and ON there are three programmable brightness 161f431afdSNeilBrown * levels which can be programmed from 0 to 15 and indicate how many 171f431afdSNeilBrown * 500usec intervals in each 8msec that the led is 'on'. The levels 181f431afdSNeilBrown * are named MASTER, BANK0 and BANK1. 19a6d511e5SNeilBrown * 201f431afdSNeilBrown * There are two different blink rates that can be programmed, each 211f431afdSNeilBrown * with separate time for rise, on, fall, off and second-off. Thus if 221f431afdSNeilBrown * 3 or more different non-trivial rates are required, software must 231f431afdSNeilBrown * be used for the extra rates. The two different blink rates must 241f431afdSNeilBrown * align with the two levels BANK0 and BANK1. This driver does not 251f431afdSNeilBrown * support double-blink so 'second-off' always matches 'off'. 26a6d511e5SNeilBrown * 271f431afdSNeilBrown * Only 16 different times can be programmed in a roughly logarithmic 281f431afdSNeilBrown * scale from 64ms to 16320ms. To be precise the possible times are: 29a6d511e5SNeilBrown * 0, 64, 128, 192, 256, 384, 512, 768, 30a6d511e5SNeilBrown * 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320 31a6d511e5SNeilBrown * 321f431afdSNeilBrown * Times that cannot be closely matched with these must be handled in 331f431afdSNeilBrown * software. This driver allows 12.5% error in matching. 34a6d511e5SNeilBrown * 351f431afdSNeilBrown * This driver does not allow rise/fall rates to be set explicitly. 361f431afdSNeilBrown * When trying to match a given 'on' or 'off' period, an appropriate 371f431afdSNeilBrown * pair of 'change' and 'hold' times are chosen to get a close match. 381f431afdSNeilBrown * If the target delay is even, the 'change' number will be the 391f431afdSNeilBrown * smaller; if odd, the 'hold' number will be the smaller. 40a6d511e5SNeilBrown 411f431afdSNeilBrown * Choosing pairs of delays with 12.5% errors allows us to match 421f431afdSNeilBrown * delays in the ranges: 56-72, 112-144, 168-216, 224-27504, 431f431afdSNeilBrown * 28560-36720. 441f431afdSNeilBrown * 26% of the achievable sums can be matched by multiple pairings. 451f431afdSNeilBrown * For example 1536 == 1536+0, 1024+512, or 768+768. 461f431afdSNeilBrown * This driver will always choose the pairing with the least 471f431afdSNeilBrown * maximum - 768+768 in this case. Other pairings are not available. 48a6d511e5SNeilBrown * 491f431afdSNeilBrown * Access to the 3 levels and 2 blinks are on a first-come, 501f431afdSNeilBrown * first-served basis. Access can be shared by multiple leds if they 511f431afdSNeilBrown * have the same level and either same blink rates, or some don't 521f431afdSNeilBrown * blink. When a led changes, it relinquishes access and tries again, 531f431afdSNeilBrown * so it might lose access to hardware blink. 54a6d511e5SNeilBrown * 551f431afdSNeilBrown * If a blink engine cannot be allocated, software blink is used. If 561f431afdSNeilBrown * the desired brightness cannot be allocated, the closest available 571f431afdSNeilBrown * non-zero brightness is used. As 'full' is always available, the 581f431afdSNeilBrown * worst case would be to have two different blink rates at '1', with 591f431afdSNeilBrown * Max at '2', then other leds will have to choose between '2' and 601f431afdSNeilBrown * '16'. Hopefully this is not likely. 61a6d511e5SNeilBrown * 621f431afdSNeilBrown * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the 631f431afdSNeilBrown * brightness and LEDs using the blink. It can only be reprogrammed 641f431afdSNeilBrown * when the appropriate counter is zero. The MASTER level has a 651f431afdSNeilBrown * single usage count. 661f431afdSNeilBrown * 671f431afdSNeilBrown * Each LED has programmable 'on' and 'off' time as milliseconds. 681f431afdSNeilBrown * With each there is a flag saying if it was explicitly requested or 691f431afdSNeilBrown * defaulted. Similarly the banks know if each time was explicit or a 701f431afdSNeilBrown * default. Defaults are permitted to be changed freely - they are 711f431afdSNeilBrown * not recognised when matching. 72a6d511e5SNeilBrown * 73a6d511e5SNeilBrown * 741f431afdSNeilBrown * An led-tca6507 device must be provided with platform data or 751f431afdSNeilBrown * configured via devicetree. 76a6d511e5SNeilBrown * 771f431afdSNeilBrown * The platform-data lists for each output: the name, default trigger, 781f431afdSNeilBrown * and whether the signal is being used as a GPIO rather than an LED. 791f431afdSNeilBrown * 'struct led_plaform_data' is used for this. If 'name' is NULL, the 801f431afdSNeilBrown * output isn't used. If 'flags' is TCA6507_MAKE_GPIO, the output is 811f431afdSNeilBrown * a GPO. The "struct led_platform_data" can be embedded in a "struct 821f431afdSNeilBrown * tca6507_platform_data" which adds a 'gpio_base' for the GPIOs, and 831f431afdSNeilBrown * a 'setup' callback which is called once the GPIOs are available. 841f431afdSNeilBrown * 851f431afdSNeilBrown * When configured via devicetree there is one child for each output. 861f431afdSNeilBrown * The "reg" determines the output number and "compatible" determines 871f431afdSNeilBrown * whether it is an LED or a GPIO. "linux,default-trigger" can set a 881f431afdSNeilBrown * default trigger. 89a6d511e5SNeilBrown */ 90a6d511e5SNeilBrown 91a6d511e5SNeilBrown #include <linux/module.h> 92a6d511e5SNeilBrown #include <linux/slab.h> 93a6d511e5SNeilBrown #include <linux/leds.h> 94a6d511e5SNeilBrown #include <linux/err.h> 95a6d511e5SNeilBrown #include <linux/i2c.h> 96ca995226SLinus Walleij #include <linux/gpio/driver.h> 9796f52410SMarek Behún #include <linux/property.h> 98a6d511e5SNeilBrown #include <linux/workqueue.h> 99a6d511e5SNeilBrown 100a6d511e5SNeilBrown /* LED select registers determine the source that drives LED outputs */ 101a6d511e5SNeilBrown #define TCA6507_LS_LED_OFF 0x0 /* Output HI-Z (off) */ 102a6d511e5SNeilBrown #define TCA6507_LS_LED_OFF1 0x1 /* Output HI-Z (off) - not used */ 103a6d511e5SNeilBrown #define TCA6507_LS_LED_PWM0 0x2 /* Output LOW with Bank0 rate */ 104a6d511e5SNeilBrown #define TCA6507_LS_LED_PWM1 0x3 /* Output LOW with Bank1 rate */ 105a6d511e5SNeilBrown #define TCA6507_LS_LED_ON 0x4 /* Output LOW (on) */ 106a6d511e5SNeilBrown #define TCA6507_LS_LED_MIR 0x5 /* Output LOW with Master Intensity */ 107a6d511e5SNeilBrown #define TCA6507_LS_BLINK0 0x6 /* Blink at Bank0 rate */ 108a6d511e5SNeilBrown #define TCA6507_LS_BLINK1 0x7 /* Blink at Bank1 rate */ 109a6d511e5SNeilBrown 11038b393feSMarek Behún struct tca6507_platform_data { 11138b393feSMarek Behún struct led_platform_data leds; 11238b393feSMarek Behún #ifdef CONFIG_GPIOLIB 11338b393feSMarek Behún int gpio_base; 11438b393feSMarek Behún #endif 11538b393feSMarek Behún }; 11638b393feSMarek Behún 11738b393feSMarek Behún #define TCA6507_MAKE_GPIO 1 11838b393feSMarek Behún 119a6d511e5SNeilBrown enum { 120a6d511e5SNeilBrown BANK0, 121a6d511e5SNeilBrown BANK1, 122a6d511e5SNeilBrown MASTER, 123a6d511e5SNeilBrown }; 124a6d511e5SNeilBrown static int bank_source[3] = { 125a6d511e5SNeilBrown TCA6507_LS_LED_PWM0, 126a6d511e5SNeilBrown TCA6507_LS_LED_PWM1, 127a6d511e5SNeilBrown TCA6507_LS_LED_MIR, 128a6d511e5SNeilBrown }; 129a6d511e5SNeilBrown static int blink_source[2] = { 130a6d511e5SNeilBrown TCA6507_LS_BLINK0, 131a6d511e5SNeilBrown TCA6507_LS_BLINK1, 132a6d511e5SNeilBrown }; 133a6d511e5SNeilBrown 134a6d511e5SNeilBrown /* PWM registers */ 135a6d511e5SNeilBrown #define TCA6507_REG_CNT 11 136a6d511e5SNeilBrown 137a6d511e5SNeilBrown /* 138a6d511e5SNeilBrown * 0x00, 0x01, 0x02 encode the TCA6507_LS_* values, each output 139a6d511e5SNeilBrown * owns one bit in each register 140a6d511e5SNeilBrown */ 141a6d511e5SNeilBrown #define TCA6507_FADE_ON 0x03 142a6d511e5SNeilBrown #define TCA6507_FULL_ON 0x04 143a6d511e5SNeilBrown #define TCA6507_FADE_OFF 0x05 144a6d511e5SNeilBrown #define TCA6507_FIRST_OFF 0x06 145a6d511e5SNeilBrown #define TCA6507_SECOND_OFF 0x07 146a6d511e5SNeilBrown #define TCA6507_MAX_INTENSITY 0x08 147a6d511e5SNeilBrown #define TCA6507_MASTER_INTENSITY 0x09 148a6d511e5SNeilBrown #define TCA6507_INITIALIZE 0x0A 149a6d511e5SNeilBrown 150a6d511e5SNeilBrown #define INIT_CODE 0x8 151a6d511e5SNeilBrown 152a6d511e5SNeilBrown #define TIMECODES 16 153a6d511e5SNeilBrown static int time_codes[TIMECODES] = { 154a6d511e5SNeilBrown 0, 64, 128, 192, 256, 384, 512, 768, 155a6d511e5SNeilBrown 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320 156a6d511e5SNeilBrown }; 157a6d511e5SNeilBrown 158a6d511e5SNeilBrown /* Convert an led.brightness level (0..255) to a TCA6507 level (0..15) */ 159a6d511e5SNeilBrown static inline int TO_LEVEL(int brightness) 160a6d511e5SNeilBrown { 161a6d511e5SNeilBrown return brightness >> 4; 162a6d511e5SNeilBrown } 163a6d511e5SNeilBrown 164a6d511e5SNeilBrown /* ...and convert back */ 165a6d511e5SNeilBrown static inline int TO_BRIGHT(int level) 166a6d511e5SNeilBrown { 167a6d511e5SNeilBrown if (level) 168a6d511e5SNeilBrown return (level << 4) | 0xf; 169a6d511e5SNeilBrown return 0; 170a6d511e5SNeilBrown } 171a6d511e5SNeilBrown 172a6d511e5SNeilBrown #define NUM_LEDS 7 173a6d511e5SNeilBrown struct tca6507_chip { 174a6d511e5SNeilBrown int reg_set; /* One bit per register where 175a6d511e5SNeilBrown * a '1' means the register 176a6d511e5SNeilBrown * should be written */ 177a6d511e5SNeilBrown u8 reg_file[TCA6507_REG_CNT]; 178a6d511e5SNeilBrown /* Bank 2 is Master Intensity and doesn't use times */ 179a6d511e5SNeilBrown struct bank { 180a6d511e5SNeilBrown int level; 181a6d511e5SNeilBrown int ontime, offtime; 182a6d511e5SNeilBrown int on_dflt, off_dflt; 183a6d511e5SNeilBrown int time_use, level_use; 184a6d511e5SNeilBrown } bank[3]; 185a6d511e5SNeilBrown struct i2c_client *client; 186a6d511e5SNeilBrown struct work_struct work; 187a6d511e5SNeilBrown spinlock_t lock; 188a6d511e5SNeilBrown 189a6d511e5SNeilBrown struct tca6507_led { 190a6d511e5SNeilBrown struct tca6507_chip *chip; 191a6d511e5SNeilBrown struct led_classdev led_cdev; 192a6d511e5SNeilBrown int num; 193a6d511e5SNeilBrown int ontime, offtime; 194a6d511e5SNeilBrown int on_dflt, off_dflt; 195a6d511e5SNeilBrown int bank; /* Bank used, or -1 */ 196a6d511e5SNeilBrown int blink; /* Set if hardware-blinking */ 197a6d511e5SNeilBrown } leds[NUM_LEDS]; 198a6d511e5SNeilBrown #ifdef CONFIG_GPIOLIB 199a6d511e5SNeilBrown struct gpio_chip gpio; 200a6d511e5SNeilBrown const char *gpio_name[NUM_LEDS]; 201a6d511e5SNeilBrown int gpio_map[NUM_LEDS]; 202a6d511e5SNeilBrown #endif 203a6d511e5SNeilBrown }; 204a6d511e5SNeilBrown 205a6d511e5SNeilBrown static const struct i2c_device_id tca6507_id[] = { 206a6d511e5SNeilBrown { "tca6507" }, 207a6d511e5SNeilBrown { } 208a6d511e5SNeilBrown }; 209a6d511e5SNeilBrown MODULE_DEVICE_TABLE(i2c, tca6507_id); 210a6d511e5SNeilBrown 211a6d511e5SNeilBrown static int choose_times(int msec, int *c1p, int *c2p) 212a6d511e5SNeilBrown { 213a6d511e5SNeilBrown /* 2141f431afdSNeilBrown * Choose two timecodes which add to 'msec' as near as 2151f431afdSNeilBrown * possible. The first returned is the 'on' or 'off' time. 2161f431afdSNeilBrown * The second is to be used as a 'fade-on' or 'fade-off' time. 2171f431afdSNeilBrown * If 'msec' is even, the first will not be smaller than the 2181f431afdSNeilBrown * second. If 'msec' is odd, the first will not be larger 2191f431afdSNeilBrown * than the second. 2201f431afdSNeilBrown * If we cannot get a sum within 1/8 of 'msec' fail with 2211f431afdSNeilBrown * -EINVAL, otherwise return the sum that was achieved, plus 1 2221f431afdSNeilBrown * if the first is smaller. 2231f431afdSNeilBrown * If two possibilities are equally good (e.g. 512+0, 2241f431afdSNeilBrown * 256+256), choose the first pair so there is more 2251f431afdSNeilBrown * change-time visible (i.e. it is softer). 226a6d511e5SNeilBrown */ 227a6d511e5SNeilBrown int c1, c2; 228a6d511e5SNeilBrown int tmax = msec * 9 / 8; 229a6d511e5SNeilBrown int tmin = msec * 7 / 8; 230a6d511e5SNeilBrown int diff = 65536; 231a6d511e5SNeilBrown 232a6d511e5SNeilBrown /* We start at '1' to ensure we never even think of choosing a 233a6d511e5SNeilBrown * total time of '0'. 234a6d511e5SNeilBrown */ 235a6d511e5SNeilBrown for (c1 = 1; c1 < TIMECODES; c1++) { 236a6d511e5SNeilBrown int t = time_codes[c1]; 237a6d511e5SNeilBrown if (t*2 < tmin) 238a6d511e5SNeilBrown continue; 239a6d511e5SNeilBrown if (t > tmax) 240a6d511e5SNeilBrown break; 241a6d511e5SNeilBrown for (c2 = 0; c2 <= c1; c2++) { 242a6d511e5SNeilBrown int tt = t + time_codes[c2]; 243a6d511e5SNeilBrown int d; 244a6d511e5SNeilBrown if (tt < tmin) 245a6d511e5SNeilBrown continue; 246a6d511e5SNeilBrown if (tt > tmax) 247a6d511e5SNeilBrown break; 248a6d511e5SNeilBrown /* This works! */ 249a6d511e5SNeilBrown d = abs(msec - tt); 250a6d511e5SNeilBrown if (d >= diff) 251a6d511e5SNeilBrown continue; 252a6d511e5SNeilBrown /* Best yet */ 253a6d511e5SNeilBrown *c1p = c1; 254a6d511e5SNeilBrown *c2p = c2; 255a6d511e5SNeilBrown diff = d; 256a6d511e5SNeilBrown if (d == 0) 257a6d511e5SNeilBrown return msec; 258a6d511e5SNeilBrown } 259a6d511e5SNeilBrown } 260a6d511e5SNeilBrown if (diff < 65536) { 261a6d511e5SNeilBrown int actual; 262a6d511e5SNeilBrown if (msec & 1) { 263a6d511e5SNeilBrown c1 = *c2p; 264a6d511e5SNeilBrown *c2p = *c1p; 265a6d511e5SNeilBrown *c1p = c1; 266a6d511e5SNeilBrown } 267a6d511e5SNeilBrown actual = time_codes[*c1p] + time_codes[*c2p]; 268a6d511e5SNeilBrown if (*c1p < *c2p) 269a6d511e5SNeilBrown return actual + 1; 270a6d511e5SNeilBrown else 271a6d511e5SNeilBrown return actual; 272a6d511e5SNeilBrown } 273a6d511e5SNeilBrown /* No close match */ 274a6d511e5SNeilBrown return -EINVAL; 275a6d511e5SNeilBrown } 276a6d511e5SNeilBrown 277a6d511e5SNeilBrown /* 2781f431afdSNeilBrown * Update the register file with the appropriate 3-bit state for the 2791f431afdSNeilBrown * given led. 280a6d511e5SNeilBrown */ 281a6d511e5SNeilBrown static void set_select(struct tca6507_chip *tca, int led, int val) 282a6d511e5SNeilBrown { 283a6d511e5SNeilBrown int mask = (1 << led); 284a6d511e5SNeilBrown int bit; 285a6d511e5SNeilBrown 286a6d511e5SNeilBrown for (bit = 0; bit < 3; bit++) { 287a6d511e5SNeilBrown int n = tca->reg_file[bit] & ~mask; 288a6d511e5SNeilBrown if (val & (1 << bit)) 289a6d511e5SNeilBrown n |= mask; 290a6d511e5SNeilBrown if (tca->reg_file[bit] != n) { 291a6d511e5SNeilBrown tca->reg_file[bit] = n; 292a6d511e5SNeilBrown tca->reg_set |= (1 << bit); 293a6d511e5SNeilBrown } 294a6d511e5SNeilBrown } 295a6d511e5SNeilBrown } 296a6d511e5SNeilBrown 2971f431afdSNeilBrown /* Update the register file with the appropriate 4-bit code for one 2981f431afdSNeilBrown * bank or other. This can be used for timers, for levels, or for 2991f431afdSNeilBrown * initialization. 300a6d511e5SNeilBrown */ 301a6d511e5SNeilBrown static void set_code(struct tca6507_chip *tca, int reg, int bank, int new) 302a6d511e5SNeilBrown { 303a6d511e5SNeilBrown int mask = 0xF; 304a6d511e5SNeilBrown int n; 305a6d511e5SNeilBrown if (bank) { 306a6d511e5SNeilBrown mask <<= 4; 307a6d511e5SNeilBrown new <<= 4; 308a6d511e5SNeilBrown } 309a6d511e5SNeilBrown n = tca->reg_file[reg] & ~mask; 310a6d511e5SNeilBrown n |= new; 311a6d511e5SNeilBrown if (tca->reg_file[reg] != n) { 312a6d511e5SNeilBrown tca->reg_file[reg] = n; 313a6d511e5SNeilBrown tca->reg_set |= 1 << reg; 314a6d511e5SNeilBrown } 315a6d511e5SNeilBrown } 316a6d511e5SNeilBrown 317a6d511e5SNeilBrown /* Update brightness level. */ 318a6d511e5SNeilBrown static void set_level(struct tca6507_chip *tca, int bank, int level) 319a6d511e5SNeilBrown { 320a6d511e5SNeilBrown switch (bank) { 321a6d511e5SNeilBrown case BANK0: 322a6d511e5SNeilBrown case BANK1: 323a6d511e5SNeilBrown set_code(tca, TCA6507_MAX_INTENSITY, bank, level); 324a6d511e5SNeilBrown break; 325a6d511e5SNeilBrown case MASTER: 326a6d511e5SNeilBrown set_code(tca, TCA6507_MASTER_INTENSITY, 0, level); 327a6d511e5SNeilBrown break; 328a6d511e5SNeilBrown } 329a6d511e5SNeilBrown tca->bank[bank].level = level; 330a6d511e5SNeilBrown } 331a6d511e5SNeilBrown 3321f431afdSNeilBrown /* Record all relevant time codes for a given bank */ 333a6d511e5SNeilBrown static void set_times(struct tca6507_chip *tca, int bank) 334a6d511e5SNeilBrown { 335a6d511e5SNeilBrown int c1, c2; 336a6d511e5SNeilBrown int result; 337a6d511e5SNeilBrown 338a6d511e5SNeilBrown result = choose_times(tca->bank[bank].ontime, &c1, &c2); 3394a91c45eSDan Carpenter if (result < 0) 3404a91c45eSDan Carpenter return; 341a6d511e5SNeilBrown dev_dbg(&tca->client->dev, 3421f431afdSNeilBrown "Chose on times %d(%d) %d(%d) for %dms\n", 3431f431afdSNeilBrown c1, time_codes[c1], 344a6d511e5SNeilBrown c2, time_codes[c2], tca->bank[bank].ontime); 345a6d511e5SNeilBrown set_code(tca, TCA6507_FADE_ON, bank, c2); 346a6d511e5SNeilBrown set_code(tca, TCA6507_FULL_ON, bank, c1); 347a6d511e5SNeilBrown tca->bank[bank].ontime = result; 348a6d511e5SNeilBrown 349a6d511e5SNeilBrown result = choose_times(tca->bank[bank].offtime, &c1, &c2); 350a6d511e5SNeilBrown dev_dbg(&tca->client->dev, 3511f431afdSNeilBrown "Chose off times %d(%d) %d(%d) for %dms\n", 3521f431afdSNeilBrown c1, time_codes[c1], 353a6d511e5SNeilBrown c2, time_codes[c2], tca->bank[bank].offtime); 354a6d511e5SNeilBrown set_code(tca, TCA6507_FADE_OFF, bank, c2); 355a6d511e5SNeilBrown set_code(tca, TCA6507_FIRST_OFF, bank, c1); 356a6d511e5SNeilBrown set_code(tca, TCA6507_SECOND_OFF, bank, c1); 357a6d511e5SNeilBrown tca->bank[bank].offtime = result; 358a6d511e5SNeilBrown 359a6d511e5SNeilBrown set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE); 360a6d511e5SNeilBrown } 361a6d511e5SNeilBrown 362a6d511e5SNeilBrown /* Write all needed register of tca6507 */ 363a6d511e5SNeilBrown 364a6d511e5SNeilBrown static void tca6507_work(struct work_struct *work) 365a6d511e5SNeilBrown { 366a6d511e5SNeilBrown struct tca6507_chip *tca = container_of(work, struct tca6507_chip, 367a6d511e5SNeilBrown work); 368a6d511e5SNeilBrown struct i2c_client *cl = tca->client; 369a6d511e5SNeilBrown int set; 370a6d511e5SNeilBrown u8 file[TCA6507_REG_CNT]; 371a6d511e5SNeilBrown int r; 372a6d511e5SNeilBrown 373a6d511e5SNeilBrown spin_lock_irq(&tca->lock); 374a6d511e5SNeilBrown set = tca->reg_set; 375a6d511e5SNeilBrown memcpy(file, tca->reg_file, TCA6507_REG_CNT); 376a6d511e5SNeilBrown tca->reg_set = 0; 377a6d511e5SNeilBrown spin_unlock_irq(&tca->lock); 378a6d511e5SNeilBrown 379a6d511e5SNeilBrown for (r = 0; r < TCA6507_REG_CNT; r++) 380a6d511e5SNeilBrown if (set & (1<<r)) 381a6d511e5SNeilBrown i2c_smbus_write_byte_data(cl, r, file[r]); 382a6d511e5SNeilBrown } 383a6d511e5SNeilBrown 384a6d511e5SNeilBrown static void led_release(struct tca6507_led *led) 385a6d511e5SNeilBrown { 386a6d511e5SNeilBrown /* If led owns any resource, release it. */ 387a6d511e5SNeilBrown struct tca6507_chip *tca = led->chip; 388a6d511e5SNeilBrown if (led->bank >= 0) { 389a6d511e5SNeilBrown struct bank *b = tca->bank + led->bank; 390a6d511e5SNeilBrown if (led->blink) 391a6d511e5SNeilBrown b->time_use--; 392a6d511e5SNeilBrown b->level_use--; 393a6d511e5SNeilBrown } 394a6d511e5SNeilBrown led->blink = 0; 395a6d511e5SNeilBrown led->bank = -1; 396a6d511e5SNeilBrown } 397a6d511e5SNeilBrown 398a6d511e5SNeilBrown static int led_prepare(struct tca6507_led *led) 399a6d511e5SNeilBrown { 4001f431afdSNeilBrown /* Assign this led to a bank, configuring that bank if 4011f431afdSNeilBrown * necessary. */ 402a6d511e5SNeilBrown int level = TO_LEVEL(led->led_cdev.brightness); 403a6d511e5SNeilBrown struct tca6507_chip *tca = led->chip; 404a6d511e5SNeilBrown int c1, c2; 405a6d511e5SNeilBrown int i; 406a6d511e5SNeilBrown struct bank *b; 407a6d511e5SNeilBrown int need_init = 0; 408a6d511e5SNeilBrown 409a6d511e5SNeilBrown led->led_cdev.brightness = TO_BRIGHT(level); 410a6d511e5SNeilBrown if (level == 0) { 411a6d511e5SNeilBrown set_select(tca, led->num, TCA6507_LS_LED_OFF); 412a6d511e5SNeilBrown return 0; 413a6d511e5SNeilBrown } 414a6d511e5SNeilBrown 415a6d511e5SNeilBrown if (led->ontime == 0 || led->offtime == 0) { 416a6d511e5SNeilBrown /* 4171f431afdSNeilBrown * Just set the brightness, choosing first usable 4181f431afdSNeilBrown * bank. If none perfect, choose best. Count 4191f431afdSNeilBrown * backwards so we check MASTER bank first to avoid 4201f431afdSNeilBrown * wasting a timer. 421a6d511e5SNeilBrown */ 422a6d511e5SNeilBrown int best = -1;/* full-on */ 423a6d511e5SNeilBrown int diff = 15-level; 424a6d511e5SNeilBrown 425a6d511e5SNeilBrown if (level == 15) { 426a6d511e5SNeilBrown set_select(tca, led->num, TCA6507_LS_LED_ON); 427a6d511e5SNeilBrown return 0; 428a6d511e5SNeilBrown } 429a6d511e5SNeilBrown 430a6d511e5SNeilBrown for (i = MASTER; i >= BANK0; i--) { 431a6d511e5SNeilBrown int d; 432a6d511e5SNeilBrown if (tca->bank[i].level == level || 433a6d511e5SNeilBrown tca->bank[i].level_use == 0) { 434a6d511e5SNeilBrown best = i; 435a6d511e5SNeilBrown break; 436a6d511e5SNeilBrown } 437a6d511e5SNeilBrown d = abs(level - tca->bank[i].level); 438a6d511e5SNeilBrown if (d < diff) { 439a6d511e5SNeilBrown diff = d; 440a6d511e5SNeilBrown best = i; 441a6d511e5SNeilBrown } 442a6d511e5SNeilBrown } 443a6d511e5SNeilBrown if (best == -1) { 444a6d511e5SNeilBrown /* Best brightness is full-on */ 445a6d511e5SNeilBrown set_select(tca, led->num, TCA6507_LS_LED_ON); 446a6d511e5SNeilBrown led->led_cdev.brightness = LED_FULL; 447a6d511e5SNeilBrown return 0; 448a6d511e5SNeilBrown } 449a6d511e5SNeilBrown 450a6d511e5SNeilBrown if (!tca->bank[best].level_use) 451a6d511e5SNeilBrown set_level(tca, best, level); 452a6d511e5SNeilBrown 453a6d511e5SNeilBrown tca->bank[best].level_use++; 454a6d511e5SNeilBrown led->bank = best; 455a6d511e5SNeilBrown set_select(tca, led->num, bank_source[best]); 456a6d511e5SNeilBrown led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level); 457a6d511e5SNeilBrown return 0; 458a6d511e5SNeilBrown } 459a6d511e5SNeilBrown 460a6d511e5SNeilBrown /* 4611f431afdSNeilBrown * We have on/off time so we need to try to allocate a timing 4621f431afdSNeilBrown * bank. First check if times are compatible with hardware 4631f431afdSNeilBrown * and give up if not. 464a6d511e5SNeilBrown */ 465a6d511e5SNeilBrown if (choose_times(led->ontime, &c1, &c2) < 0) 466a6d511e5SNeilBrown return -EINVAL; 467a6d511e5SNeilBrown if (choose_times(led->offtime, &c1, &c2) < 0) 468a6d511e5SNeilBrown return -EINVAL; 469a6d511e5SNeilBrown 470a6d511e5SNeilBrown for (i = BANK0; i <= BANK1; i++) { 471a6d511e5SNeilBrown if (tca->bank[i].level_use == 0) 472a6d511e5SNeilBrown /* not in use - it is ours! */ 473a6d511e5SNeilBrown break; 474a6d511e5SNeilBrown if (tca->bank[i].level != level) 475a6d511e5SNeilBrown /* Incompatible level - skip */ 476a6d511e5SNeilBrown /* FIX: if timer matches we maybe should consider 477a6d511e5SNeilBrown * this anyway... 478a6d511e5SNeilBrown */ 479a6d511e5SNeilBrown continue; 480a6d511e5SNeilBrown 481a6d511e5SNeilBrown if (tca->bank[i].time_use == 0) 482a6d511e5SNeilBrown /* Timer not in use, and level matches - use it */ 483a6d511e5SNeilBrown break; 484a6d511e5SNeilBrown 485a6d511e5SNeilBrown if (!(tca->bank[i].on_dflt || 486a6d511e5SNeilBrown led->on_dflt || 487a6d511e5SNeilBrown tca->bank[i].ontime == led->ontime)) 488a6d511e5SNeilBrown /* on time is incompatible */ 489a6d511e5SNeilBrown continue; 490a6d511e5SNeilBrown 491a6d511e5SNeilBrown if (!(tca->bank[i].off_dflt || 492a6d511e5SNeilBrown led->off_dflt || 493a6d511e5SNeilBrown tca->bank[i].offtime == led->offtime)) 494a6d511e5SNeilBrown /* off time is incompatible */ 495a6d511e5SNeilBrown continue; 496a6d511e5SNeilBrown 497a6d511e5SNeilBrown /* looks like a suitable match */ 498a6d511e5SNeilBrown break; 499a6d511e5SNeilBrown } 500a6d511e5SNeilBrown 501a6d511e5SNeilBrown if (i > BANK1) 502a6d511e5SNeilBrown /* Nothing matches - how sad */ 503a6d511e5SNeilBrown return -EINVAL; 504a6d511e5SNeilBrown 505a6d511e5SNeilBrown b = &tca->bank[i]; 506a6d511e5SNeilBrown if (b->level_use == 0) 507a6d511e5SNeilBrown set_level(tca, i, level); 508a6d511e5SNeilBrown b->level_use++; 509a6d511e5SNeilBrown led->bank = i; 510a6d511e5SNeilBrown 511a6d511e5SNeilBrown if (b->on_dflt || 512a6d511e5SNeilBrown !led->on_dflt || 513a6d511e5SNeilBrown b->time_use == 0) { 514a6d511e5SNeilBrown b->ontime = led->ontime; 515a6d511e5SNeilBrown b->on_dflt = led->on_dflt; 516a6d511e5SNeilBrown need_init = 1; 517a6d511e5SNeilBrown } 518a6d511e5SNeilBrown 519a6d511e5SNeilBrown if (b->off_dflt || 520a6d511e5SNeilBrown !led->off_dflt || 521a6d511e5SNeilBrown b->time_use == 0) { 522a6d511e5SNeilBrown b->offtime = led->offtime; 523a6d511e5SNeilBrown b->off_dflt = led->off_dflt; 524a6d511e5SNeilBrown need_init = 1; 525a6d511e5SNeilBrown } 526a6d511e5SNeilBrown 527a6d511e5SNeilBrown if (need_init) 528a6d511e5SNeilBrown set_times(tca, i); 529a6d511e5SNeilBrown 530a6d511e5SNeilBrown led->ontime = b->ontime; 531a6d511e5SNeilBrown led->offtime = b->offtime; 532a6d511e5SNeilBrown 533a6d511e5SNeilBrown b->time_use++; 534a6d511e5SNeilBrown led->blink = 1; 535a6d511e5SNeilBrown led->led_cdev.brightness = TO_BRIGHT(b->level); 536a6d511e5SNeilBrown set_select(tca, led->num, blink_source[i]); 537a6d511e5SNeilBrown return 0; 538a6d511e5SNeilBrown } 539a6d511e5SNeilBrown 540a6d511e5SNeilBrown static int led_assign(struct tca6507_led *led) 541a6d511e5SNeilBrown { 542a6d511e5SNeilBrown struct tca6507_chip *tca = led->chip; 543a6d511e5SNeilBrown int err; 544a6d511e5SNeilBrown unsigned long flags; 545a6d511e5SNeilBrown 546a6d511e5SNeilBrown spin_lock_irqsave(&tca->lock, flags); 547a6d511e5SNeilBrown led_release(led); 548a6d511e5SNeilBrown err = led_prepare(led); 549a6d511e5SNeilBrown if (err) { 550a6d511e5SNeilBrown /* 5511f431afdSNeilBrown * Can only fail on timer setup. In that case we need 5521f431afdSNeilBrown * to re-establish as steady level. 553a6d511e5SNeilBrown */ 554a6d511e5SNeilBrown led->ontime = 0; 555a6d511e5SNeilBrown led->offtime = 0; 556a6d511e5SNeilBrown led_prepare(led); 557a6d511e5SNeilBrown } 558a6d511e5SNeilBrown spin_unlock_irqrestore(&tca->lock, flags); 559a6d511e5SNeilBrown 560a6d511e5SNeilBrown if (tca->reg_set) 561a6d511e5SNeilBrown schedule_work(&tca->work); 562a6d511e5SNeilBrown return err; 563a6d511e5SNeilBrown } 564a6d511e5SNeilBrown 565a6d511e5SNeilBrown static void tca6507_brightness_set(struct led_classdev *led_cdev, 566a6d511e5SNeilBrown enum led_brightness brightness) 567a6d511e5SNeilBrown { 568a6d511e5SNeilBrown struct tca6507_led *led = container_of(led_cdev, struct tca6507_led, 569a6d511e5SNeilBrown led_cdev); 570a6d511e5SNeilBrown led->led_cdev.brightness = brightness; 571a6d511e5SNeilBrown led->ontime = 0; 572a6d511e5SNeilBrown led->offtime = 0; 573a6d511e5SNeilBrown led_assign(led); 574a6d511e5SNeilBrown } 575a6d511e5SNeilBrown 576a6d511e5SNeilBrown static int tca6507_blink_set(struct led_classdev *led_cdev, 577a6d511e5SNeilBrown unsigned long *delay_on, 578a6d511e5SNeilBrown unsigned long *delay_off) 579a6d511e5SNeilBrown { 580a6d511e5SNeilBrown struct tca6507_led *led = container_of(led_cdev, struct tca6507_led, 581a6d511e5SNeilBrown led_cdev); 582a6d511e5SNeilBrown 583a6d511e5SNeilBrown if (*delay_on == 0) 584a6d511e5SNeilBrown led->on_dflt = 1; 585a6d511e5SNeilBrown else if (delay_on != &led_cdev->blink_delay_on) 586a6d511e5SNeilBrown led->on_dflt = 0; 587a6d511e5SNeilBrown led->ontime = *delay_on; 588a6d511e5SNeilBrown 589a6d511e5SNeilBrown if (*delay_off == 0) 590a6d511e5SNeilBrown led->off_dflt = 1; 591a6d511e5SNeilBrown else if (delay_off != &led_cdev->blink_delay_off) 592a6d511e5SNeilBrown led->off_dflt = 0; 593a6d511e5SNeilBrown led->offtime = *delay_off; 594a6d511e5SNeilBrown 595a6d511e5SNeilBrown if (led->ontime == 0) 596a6d511e5SNeilBrown led->ontime = 512; 597a6d511e5SNeilBrown if (led->offtime == 0) 598a6d511e5SNeilBrown led->offtime = 512; 599a6d511e5SNeilBrown 600a6d511e5SNeilBrown if (led->led_cdev.brightness == LED_OFF) 601a6d511e5SNeilBrown led->led_cdev.brightness = LED_FULL; 602a6d511e5SNeilBrown if (led_assign(led) < 0) { 603a6d511e5SNeilBrown led->ontime = 0; 604a6d511e5SNeilBrown led->offtime = 0; 605a6d511e5SNeilBrown led->led_cdev.brightness = LED_OFF; 606a6d511e5SNeilBrown return -EINVAL; 607a6d511e5SNeilBrown } 608a6d511e5SNeilBrown *delay_on = led->ontime; 609a6d511e5SNeilBrown *delay_off = led->offtime; 610a6d511e5SNeilBrown return 0; 611a6d511e5SNeilBrown } 612a6d511e5SNeilBrown 613a6d511e5SNeilBrown #ifdef CONFIG_GPIOLIB 614a6d511e5SNeilBrown static void tca6507_gpio_set_value(struct gpio_chip *gc, 615a6d511e5SNeilBrown unsigned offset, int val) 616a6d511e5SNeilBrown { 6172a664343SLinus Walleij struct tca6507_chip *tca = gpiochip_get_data(gc); 618a6d511e5SNeilBrown unsigned long flags; 619a6d511e5SNeilBrown 620a6d511e5SNeilBrown spin_lock_irqsave(&tca->lock, flags); 621a6d511e5SNeilBrown /* 6221f431afdSNeilBrown * 'OFF' is floating high, and 'ON' is pulled down, so it has 6231f431afdSNeilBrown * the inverse sense of 'val'. 624a6d511e5SNeilBrown */ 625a6d511e5SNeilBrown set_select(tca, tca->gpio_map[offset], 626a6d511e5SNeilBrown val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON); 627a6d511e5SNeilBrown spin_unlock_irqrestore(&tca->lock, flags); 628a6d511e5SNeilBrown if (tca->reg_set) 629a6d511e5SNeilBrown schedule_work(&tca->work); 630a6d511e5SNeilBrown } 631a6d511e5SNeilBrown 632a6d511e5SNeilBrown static int tca6507_gpio_direction_output(struct gpio_chip *gc, 633a6d511e5SNeilBrown unsigned offset, int val) 634a6d511e5SNeilBrown { 635a6d511e5SNeilBrown tca6507_gpio_set_value(gc, offset, val); 636a6d511e5SNeilBrown return 0; 637a6d511e5SNeilBrown } 638a6d511e5SNeilBrown 639a6d511e5SNeilBrown static int tca6507_probe_gpios(struct i2c_client *client, 640a6d511e5SNeilBrown struct tca6507_chip *tca, 641a6d511e5SNeilBrown struct tca6507_platform_data *pdata) 642a6d511e5SNeilBrown { 643a6d511e5SNeilBrown int err; 644a6d511e5SNeilBrown int i = 0; 645a6d511e5SNeilBrown int gpios = 0; 646a6d511e5SNeilBrown 647a6d511e5SNeilBrown for (i = 0; i < NUM_LEDS; i++) 648a6d511e5SNeilBrown if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) { 649a6d511e5SNeilBrown /* Configure as a gpio */ 650a6d511e5SNeilBrown tca->gpio_name[gpios] = pdata->leds.leds[i].name; 651a6d511e5SNeilBrown tca->gpio_map[gpios] = i; 652a6d511e5SNeilBrown gpios++; 653a6d511e5SNeilBrown } 654a6d511e5SNeilBrown 655a6d511e5SNeilBrown if (!gpios) 656a6d511e5SNeilBrown return 0; 657a6d511e5SNeilBrown 658a6d511e5SNeilBrown tca->gpio.label = "gpio-tca6507"; 659a6d511e5SNeilBrown tca->gpio.names = tca->gpio_name; 660a6d511e5SNeilBrown tca->gpio.ngpio = gpios; 661a6d511e5SNeilBrown tca->gpio.base = pdata->gpio_base; 662a6d511e5SNeilBrown tca->gpio.owner = THIS_MODULE; 663a6d511e5SNeilBrown tca->gpio.direction_output = tca6507_gpio_direction_output; 664a6d511e5SNeilBrown tca->gpio.set = tca6507_gpio_set_value; 66558383c78SLinus Walleij tca->gpio.parent = &client->dev; 66610ead6e5SNeilBrown #ifdef CONFIG_OF_GPIO 6678853c95eSMarek Behún tca->gpio.of_node = of_node_get(dev_of_node(&client->dev)); 66810ead6e5SNeilBrown #endif 6692a664343SLinus Walleij err = gpiochip_add_data(&tca->gpio, tca); 670a6d511e5SNeilBrown if (err) { 671a6d511e5SNeilBrown tca->gpio.ngpio = 0; 672a6d511e5SNeilBrown return err; 673a6d511e5SNeilBrown } 674a6d511e5SNeilBrown return 0; 675a6d511e5SNeilBrown } 676a6d511e5SNeilBrown 677a6d511e5SNeilBrown static void tca6507_remove_gpio(struct tca6507_chip *tca) 678a6d511e5SNeilBrown { 67988d5e520Sabdoulaye berthe if (tca->gpio.ngpio) 68088d5e520Sabdoulaye berthe gpiochip_remove(&tca->gpio); 681a6d511e5SNeilBrown } 682a6d511e5SNeilBrown #else /* CONFIG_GPIOLIB */ 683a6d511e5SNeilBrown static int tca6507_probe_gpios(struct i2c_client *client, 684a6d511e5SNeilBrown struct tca6507_chip *tca, 685a6d511e5SNeilBrown struct tca6507_platform_data *pdata) 686a6d511e5SNeilBrown { 687a6d511e5SNeilBrown return 0; 688a6d511e5SNeilBrown } 689a6d511e5SNeilBrown static void tca6507_remove_gpio(struct tca6507_chip *tca) 690a6d511e5SNeilBrown { 691a6d511e5SNeilBrown } 692a6d511e5SNeilBrown #endif /* CONFIG_GPIOLIB */ 693a6d511e5SNeilBrown 6940c596a7eSMarek Belisko static struct tca6507_platform_data * 6950c596a7eSMarek Belisko tca6507_led_dt_init(struct i2c_client *client) 6960c596a7eSMarek Belisko { 6970c596a7eSMarek Belisko struct tca6507_platform_data *pdata; 69896f52410SMarek Behún struct fwnode_handle *child; 6990c596a7eSMarek Belisko struct led_info *tca_leds; 700ef754e88SAxel Lin int count; 7010c596a7eSMarek Belisko 70296f52410SMarek Behún count = device_get_child_node_count(&client->dev); 703ef754e88SAxel Lin if (!count || count > NUM_LEDS) 7040c596a7eSMarek Belisko return ERR_PTR(-ENODEV); 7050c596a7eSMarek Belisko 70696f52410SMarek Behún tca_leds = devm_kcalloc(&client->dev, NUM_LEDS, sizeof(struct led_info), 70796f52410SMarek Behún GFP_KERNEL); 7080c596a7eSMarek Belisko if (!tca_leds) 7090c596a7eSMarek Belisko return ERR_PTR(-ENOMEM); 7100c596a7eSMarek Belisko 71196f52410SMarek Behún device_for_each_child_node(&client->dev, child) { 7120c596a7eSMarek Belisko struct led_info led; 7130c596a7eSMarek Belisko u32 reg; 7140c596a7eSMarek Belisko int ret; 7150c596a7eSMarek Belisko 71696f52410SMarek Behún if (fwnode_property_read_string(child, "label", &led.name)) 71796f52410SMarek Behún led.name = fwnode_get_name(child); 71896f52410SMarek Behún 71996f52410SMarek Behún fwnode_property_read_string(child, "linux,default-trigger", 72096f52410SMarek Behún &led.default_trigger); 72196f52410SMarek Behún 7229334129eSNeilBrown led.flags = 0; 72396f52410SMarek Behún if (fwnode_property_match_string(child, "compatible", 72496f52410SMarek Behún "gpio") >= 0) 72510ead6e5SNeilBrown led.flags |= TCA6507_MAKE_GPIO; 72696f52410SMarek Behún 72796f52410SMarek Behún ret = fwnode_property_read_u32(child, "reg", ®); 72896f52410SMarek Behún if (ret || reg >= NUM_LEDS) { 72996f52410SMarek Behún fwnode_handle_put(child); 73096f52410SMarek Behún return ERR_PTR(ret); 73196f52410SMarek Behún } 7320c596a7eSMarek Belisko 7330c596a7eSMarek Belisko tca_leds[reg] = led; 7340c596a7eSMarek Belisko } 73596f52410SMarek Behún 73696f52410SMarek Behún pdata = devm_kzalloc(&client->dev, sizeof(struct tca6507_platform_data), 73796f52410SMarek Behún GFP_KERNEL); 7380c596a7eSMarek Belisko if (!pdata) 7390c596a7eSMarek Belisko return ERR_PTR(-ENOMEM); 7400c596a7eSMarek Belisko 7410c596a7eSMarek Belisko pdata->leds.leds = tca_leds; 7429334129eSNeilBrown pdata->leds.num_leds = NUM_LEDS; 74333ca1532SChen Gang #ifdef CONFIG_GPIOLIB 74410ead6e5SNeilBrown pdata->gpio_base = -1; 74533ca1532SChen Gang #endif 74696f52410SMarek Behún 7470c596a7eSMarek Belisko return pdata; 7480c596a7eSMarek Belisko } 7490c596a7eSMarek Belisko 750*e8b7dabcSPavel Machek static const struct of_device_id __maybe_unused of_tca6507_leds_match[] = { 7510c596a7eSMarek Belisko { .compatible = "ti,tca6507", }, 7520c596a7eSMarek Belisko {}, 7530c596a7eSMarek Belisko }; 7544d59ed85SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, of_tca6507_leds_match); 7550c596a7eSMarek Belisko 75698ea1ea2SBill Pemberton static int tca6507_probe(struct i2c_client *client, 757a6d511e5SNeilBrown const struct i2c_device_id *id) 758a6d511e5SNeilBrown { 759a6d511e5SNeilBrown struct tca6507_chip *tca; 760a6d511e5SNeilBrown struct i2c_adapter *adapter; 761a6d511e5SNeilBrown struct tca6507_platform_data *pdata; 762a6d511e5SNeilBrown int err; 763a6d511e5SNeilBrown int i = 0; 764a6d511e5SNeilBrown 76509bfa5f6SWolfram Sang adapter = client->adapter; 766a6d511e5SNeilBrown 767a6d511e5SNeilBrown if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) 768a6d511e5SNeilBrown return -EIO; 769a6d511e5SNeilBrown 7700c596a7eSMarek Belisko pdata = tca6507_led_dt_init(client); 7710c596a7eSMarek Belisko if (IS_ERR(pdata)) { 772a6d511e5SNeilBrown dev_err(&client->dev, "Need %d entries in platform-data list\n", 773a6d511e5SNeilBrown NUM_LEDS); 7740c596a7eSMarek Belisko return PTR_ERR(pdata); 7750c596a7eSMarek Belisko } 7766770fc60SBryan Wu tca = devm_kzalloc(&client->dev, sizeof(*tca), GFP_KERNEL); 777a6d511e5SNeilBrown if (!tca) 778920c4f4cSDan Carpenter return -ENOMEM; 779a6d511e5SNeilBrown 780a6d511e5SNeilBrown tca->client = client; 781a6d511e5SNeilBrown INIT_WORK(&tca->work, tca6507_work); 782a6d511e5SNeilBrown spin_lock_init(&tca->lock); 783a6d511e5SNeilBrown i2c_set_clientdata(client, tca); 784a6d511e5SNeilBrown 785a6d511e5SNeilBrown for (i = 0; i < NUM_LEDS; i++) { 786a6d511e5SNeilBrown struct tca6507_led *l = tca->leds + i; 787a6d511e5SNeilBrown 788a6d511e5SNeilBrown l->chip = tca; 789a6d511e5SNeilBrown l->num = i; 790a6d511e5SNeilBrown if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) { 791a6d511e5SNeilBrown l->led_cdev.name = pdata->leds.leds[i].name; 792a6d511e5SNeilBrown l->led_cdev.default_trigger 793a6d511e5SNeilBrown = pdata->leds.leds[i].default_trigger; 794a6d511e5SNeilBrown l->led_cdev.brightness_set = tca6507_brightness_set; 795a6d511e5SNeilBrown l->led_cdev.blink_set = tca6507_blink_set; 796a6d511e5SNeilBrown l->bank = -1; 797a6d511e5SNeilBrown err = led_classdev_register(&client->dev, 798a6d511e5SNeilBrown &l->led_cdev); 799a6d511e5SNeilBrown if (err < 0) 800a6d511e5SNeilBrown goto exit; 801a6d511e5SNeilBrown } 802a6d511e5SNeilBrown } 803a6d511e5SNeilBrown err = tca6507_probe_gpios(client, tca, pdata); 804a6d511e5SNeilBrown if (err) 805a6d511e5SNeilBrown goto exit; 806a6d511e5SNeilBrown /* set all registers to known state - zero */ 807a6d511e5SNeilBrown tca->reg_set = 0x7f; 808a6d511e5SNeilBrown schedule_work(&tca->work); 809a6d511e5SNeilBrown 810a6d511e5SNeilBrown return 0; 811a6d511e5SNeilBrown exit: 812920c4f4cSDan Carpenter while (i--) { 813a6d511e5SNeilBrown if (tca->leds[i].led_cdev.name) 814a6d511e5SNeilBrown led_classdev_unregister(&tca->leds[i].led_cdev); 815920c4f4cSDan Carpenter } 816a6d511e5SNeilBrown return err; 817a6d511e5SNeilBrown } 818a6d511e5SNeilBrown 819678e8a6bSBill Pemberton static int tca6507_remove(struct i2c_client *client) 820a6d511e5SNeilBrown { 821a6d511e5SNeilBrown int i; 822a6d511e5SNeilBrown struct tca6507_chip *tca = i2c_get_clientdata(client); 823a6d511e5SNeilBrown struct tca6507_led *tca_leds = tca->leds; 824a6d511e5SNeilBrown 825a6d511e5SNeilBrown for (i = 0; i < NUM_LEDS; i++) { 826a6d511e5SNeilBrown if (tca_leds[i].led_cdev.name) 827a6d511e5SNeilBrown led_classdev_unregister(&tca_leds[i].led_cdev); 828a6d511e5SNeilBrown } 829a6d511e5SNeilBrown tca6507_remove_gpio(tca); 830a6d511e5SNeilBrown cancel_work_sync(&tca->work); 831a6d511e5SNeilBrown 832a6d511e5SNeilBrown return 0; 833a6d511e5SNeilBrown } 834a6d511e5SNeilBrown 835a6d511e5SNeilBrown static struct i2c_driver tca6507_driver = { 836a6d511e5SNeilBrown .driver = { 837a6d511e5SNeilBrown .name = "leds-tca6507", 838fbd9df28SSachin Kamat .of_match_table = of_match_ptr(of_tca6507_leds_match), 839a6d511e5SNeilBrown }, 840a6d511e5SNeilBrown .probe = tca6507_probe, 841df07cf81SBill Pemberton .remove = tca6507_remove, 842a6d511e5SNeilBrown .id_table = tca6507_id, 843a6d511e5SNeilBrown }; 844a6d511e5SNeilBrown 8452e911767SPeter Meerwald module_i2c_driver(tca6507_driver); 846a6d511e5SNeilBrown 847a6d511e5SNeilBrown MODULE_AUTHOR("NeilBrown <neilb@suse.de>"); 848a6d511e5SNeilBrown MODULE_DESCRIPTION("TCA6507 LED/GPO driver"); 849a6d511e5SNeilBrown MODULE_LICENSE("GPL v2"); 850