136edc939SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 256a1740cSRicardo Ribalda Delgado /* 356a1740cSRicardo Ribalda Delgado * Copyright 2011 bct electronic GmbH 456a1740cSRicardo Ribalda Delgado * Copyright 2013 Qtechnology/AS 556a1740cSRicardo Ribalda Delgado * 656a1740cSRicardo Ribalda Delgado * Author: Peter Meerwald <p.meerwald@bct-electronic.com> 7cea0fad0SRicardo Ribalda Delgado * Author: Ricardo Ribalda <ribalda@kernel.org> 856a1740cSRicardo Ribalda Delgado * 956a1740cSRicardo Ribalda Delgado * Based on leds-pca955x.c 1056a1740cSRicardo Ribalda Delgado * 1156a1740cSRicardo Ribalda Delgado * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62) 123dfedb9dSPeter Meerwald * LED driver for the PCA9634/5 I2C LED driver (7-bit slave address set by hw.) 1356a1740cSRicardo Ribalda Delgado * 1456a1740cSRicardo Ribalda Delgado * Note that hardware blinking violates the leds infrastructure driver 1556a1740cSRicardo Ribalda Delgado * interface since the hardware only supports blinking all LEDs with the 1656a1740cSRicardo Ribalda Delgado * same delay_on/delay_off rates. That is, only the LEDs that are set to 1756a1740cSRicardo Ribalda Delgado * blink will actually blink but all LEDs that are set to blink will blink 1856a1740cSRicardo Ribalda Delgado * in identical fashion. The delay_on/delay_off values of the last LED 1956a1740cSRicardo Ribalda Delgado * that is set to blink will be used for all of the blinking LEDs. 2056a1740cSRicardo Ribalda Delgado * Hardware blinking is disabled by default but can be enabled by setting 2156a1740cSRicardo Ribalda Delgado * the 'blink_type' member in the platform_data struct to 'PCA963X_HW_BLINK' 2256a1740cSRicardo Ribalda Delgado * or by adding the 'nxp,hw-blink' property to the DTS. 2356a1740cSRicardo Ribalda Delgado */ 2456a1740cSRicardo Ribalda Delgado 2556a1740cSRicardo Ribalda Delgado #include <linux/module.h> 2656a1740cSRicardo Ribalda Delgado #include <linux/delay.h> 2756a1740cSRicardo Ribalda Delgado #include <linux/string.h> 2856a1740cSRicardo Ribalda Delgado #include <linux/ctype.h> 2956a1740cSRicardo Ribalda Delgado #include <linux/leds.h> 3056a1740cSRicardo Ribalda Delgado #include <linux/err.h> 3156a1740cSRicardo Ribalda Delgado #include <linux/i2c.h> 320b6034d8SAndy Shevchenko #include <linux/property.h> 3356a1740cSRicardo Ribalda Delgado #include <linux/slab.h> 3456a1740cSRicardo Ribalda Delgado #include <linux/of.h> 3556a1740cSRicardo Ribalda Delgado 3656a1740cSRicardo Ribalda Delgado /* LED select registers determine the source that drives LED outputs */ 3756a1740cSRicardo Ribalda Delgado #define PCA963X_LED_OFF 0x0 /* LED driver off */ 3856a1740cSRicardo Ribalda Delgado #define PCA963X_LED_ON 0x1 /* LED driver on */ 3956a1740cSRicardo Ribalda Delgado #define PCA963X_LED_PWM 0x2 /* Controlled through PWM */ 4056a1740cSRicardo Ribalda Delgado #define PCA963X_LED_GRP_PWM 0x3 /* Controlled through PWM/GRPPWM */ 4156a1740cSRicardo Ribalda Delgado 4269752909SZahari Petkov #define PCA963X_MODE2_OUTDRV 0x04 /* Open-drain or totem pole */ 4369752909SZahari Petkov #define PCA963X_MODE2_INVRT 0x10 /* Normal or inverted direction */ 4456a1740cSRicardo Ribalda Delgado #define PCA963X_MODE2_DMBLNK 0x20 /* Enable blinking */ 4556a1740cSRicardo Ribalda Delgado 4656a1740cSRicardo Ribalda Delgado #define PCA963X_MODE1 0x00 4756a1740cSRicardo Ribalda Delgado #define PCA963X_MODE2 0x01 4856a1740cSRicardo Ribalda Delgado #define PCA963X_PWM_BASE 0x02 4956a1740cSRicardo Ribalda Delgado 5056a1740cSRicardo Ribalda Delgado enum pca963x_type { 5156a1740cSRicardo Ribalda Delgado pca9633, 5256a1740cSRicardo Ribalda Delgado pca9634, 533dfedb9dSPeter Meerwald pca9635, 5456a1740cSRicardo Ribalda Delgado }; 5556a1740cSRicardo Ribalda Delgado 5656a1740cSRicardo Ribalda Delgado struct pca963x_chipdef { 5756a1740cSRicardo Ribalda Delgado u8 grppwm; 5856a1740cSRicardo Ribalda Delgado u8 grpfreq; 5956a1740cSRicardo Ribalda Delgado u8 ledout_base; 6056a1740cSRicardo Ribalda Delgado int n_leds; 6135c7d301SMatt Ranostay unsigned int scaling; 6256a1740cSRicardo Ribalda Delgado }; 6356a1740cSRicardo Ribalda Delgado 6456a1740cSRicardo Ribalda Delgado static struct pca963x_chipdef pca963x_chipdefs[] = { 6556a1740cSRicardo Ribalda Delgado [pca9633] = { 6656a1740cSRicardo Ribalda Delgado .grppwm = 0x6, 6756a1740cSRicardo Ribalda Delgado .grpfreq = 0x7, 6856a1740cSRicardo Ribalda Delgado .ledout_base = 0x8, 6956a1740cSRicardo Ribalda Delgado .n_leds = 4, 7056a1740cSRicardo Ribalda Delgado }, 7156a1740cSRicardo Ribalda Delgado [pca9634] = { 7256a1740cSRicardo Ribalda Delgado .grppwm = 0xa, 7356a1740cSRicardo Ribalda Delgado .grpfreq = 0xb, 7456a1740cSRicardo Ribalda Delgado .ledout_base = 0xc, 7556a1740cSRicardo Ribalda Delgado .n_leds = 8, 7656a1740cSRicardo Ribalda Delgado }, 773dfedb9dSPeter Meerwald [pca9635] = { 783dfedb9dSPeter Meerwald .grppwm = 0x12, 793dfedb9dSPeter Meerwald .grpfreq = 0x13, 803dfedb9dSPeter Meerwald .ledout_base = 0x14, 813dfedb9dSPeter Meerwald .n_leds = 16, 823dfedb9dSPeter Meerwald }, 8356a1740cSRicardo Ribalda Delgado }; 8456a1740cSRicardo Ribalda Delgado 8556a1740cSRicardo Ribalda Delgado /* Total blink period in milliseconds */ 8656a1740cSRicardo Ribalda Delgado #define PCA963X_BLINK_PERIOD_MIN 42 8756a1740cSRicardo Ribalda Delgado #define PCA963X_BLINK_PERIOD_MAX 10667 8856a1740cSRicardo Ribalda Delgado 8956a1740cSRicardo Ribalda Delgado static const struct i2c_device_id pca963x_id[] = { 9056a1740cSRicardo Ribalda Delgado { "pca9632", pca9633 }, 9156a1740cSRicardo Ribalda Delgado { "pca9633", pca9633 }, 9256a1740cSRicardo Ribalda Delgado { "pca9634", pca9634 }, 933dfedb9dSPeter Meerwald { "pca9635", pca9635 }, 9456a1740cSRicardo Ribalda Delgado { } 9556a1740cSRicardo Ribalda Delgado }; 9656a1740cSRicardo Ribalda Delgado MODULE_DEVICE_TABLE(i2c, pca963x_id); 9756a1740cSRicardo Ribalda Delgado 98b5a3b44fSMarek Behún struct pca963x; 9956a1740cSRicardo Ribalda Delgado 10056a1740cSRicardo Ribalda Delgado struct pca963x_led { 10156a1740cSRicardo Ribalda Delgado struct pca963x *chip; 10256a1740cSRicardo Ribalda Delgado struct led_classdev led_cdev; 1033dfedb9dSPeter Meerwald int led_num; /* 0 .. 15 potentially */ 10456a1740cSRicardo Ribalda Delgado u8 gdc; 10556a1740cSRicardo Ribalda Delgado u8 gfrq; 10656a1740cSRicardo Ribalda Delgado }; 10756a1740cSRicardo Ribalda Delgado 108b5a3b44fSMarek Behún struct pca963x { 109b5a3b44fSMarek Behún struct pca963x_chipdef *chipdef; 110b5a3b44fSMarek Behún struct mutex mutex; 111b5a3b44fSMarek Behún struct i2c_client *client; 112b5a3b44fSMarek Behún unsigned long leds_on; 113b5a3b44fSMarek Behún struct pca963x_led leds[]; 114b5a3b44fSMarek Behún }; 115b5a3b44fSMarek Behún 1165db85093SMarek Behún static int pca963x_brightness(struct pca963x_led *led, 1175029a2e3SAndrew Lunn enum led_brightness brightness) 11856a1740cSRicardo Ribalda Delgado { 1195db85093SMarek Behún struct i2c_client *client = led->chip->client; 1205db85093SMarek Behún struct pca963x_chipdef *chipdef = led->chip->chipdef; 12139118499SMarek Behún u8 ledout_addr, ledout, mask, val; 12239118499SMarek Behún int shift; 1235029a2e3SAndrew Lunn int ret; 12456a1740cSRicardo Ribalda Delgado 1255db85093SMarek Behún ledout_addr = chipdef->ledout_base + (led->led_num / 4); 1265db85093SMarek Behún shift = 2 * (led->led_num % 4); 12739118499SMarek Behún mask = 0x3 << shift; 12839118499SMarek Behún ledout = i2c_smbus_read_byte_data(client, ledout_addr); 12939118499SMarek Behún 1305029a2e3SAndrew Lunn switch (brightness) { 13156a1740cSRicardo Ribalda Delgado case LED_FULL: 13239118499SMarek Behún val = (ledout & ~mask) | (PCA963X_LED_ON << shift); 13339118499SMarek Behún ret = i2c_smbus_write_byte_data(client, ledout_addr, val); 13456a1740cSRicardo Ribalda Delgado break; 13556a1740cSRicardo Ribalda Delgado case LED_OFF: 13639118499SMarek Behún val = ledout & ~mask; 13739118499SMarek Behún ret = i2c_smbus_write_byte_data(client, ledout_addr, val); 13856a1740cSRicardo Ribalda Delgado break; 13956a1740cSRicardo Ribalda Delgado default: 14039118499SMarek Behún ret = i2c_smbus_write_byte_data(client, 14139118499SMarek Behún PCA963X_PWM_BASE + 1425db85093SMarek Behún led->led_num, 1435029a2e3SAndrew Lunn brightness); 1445029a2e3SAndrew Lunn if (ret < 0) 145a8c170b0SMatt Ranostay return ret; 14639118499SMarek Behún 14739118499SMarek Behún val = (ledout & ~mask) | (PCA963X_LED_PWM << shift); 14839118499SMarek Behún ret = i2c_smbus_write_byte_data(client, ledout_addr, val); 14956a1740cSRicardo Ribalda Delgado break; 15056a1740cSRicardo Ribalda Delgado } 151a8c170b0SMatt Ranostay 1525029a2e3SAndrew Lunn return ret; 15356a1740cSRicardo Ribalda Delgado } 15456a1740cSRicardo Ribalda Delgado 1555db85093SMarek Behún static void pca963x_blink(struct pca963x_led *led) 15656a1740cSRicardo Ribalda Delgado { 1575db85093SMarek Behún struct i2c_client *client = led->chip->client; 1585db85093SMarek Behún struct pca963x_chipdef *chipdef = led->chip->chipdef; 15939118499SMarek Behún u8 ledout_addr, ledout, mask, val, mode2; 16039118499SMarek Behún int shift; 16156a1740cSRicardo Ribalda Delgado 1625db85093SMarek Behún ledout_addr = chipdef->ledout_base + (led->led_num / 4); 1635db85093SMarek Behún shift = 2 * (led->led_num % 4); 16439118499SMarek Behún mask = 0x3 << shift; 16539118499SMarek Behún mode2 = i2c_smbus_read_byte_data(client, PCA963X_MODE2); 16656a1740cSRicardo Ribalda Delgado 1675db85093SMarek Behún i2c_smbus_write_byte_data(client, chipdef->grppwm, led->gdc); 16839118499SMarek Behún 1695db85093SMarek Behún i2c_smbus_write_byte_data(client, chipdef->grpfreq, led->gfrq); 17056a1740cSRicardo Ribalda Delgado 17156a1740cSRicardo Ribalda Delgado if (!(mode2 & PCA963X_MODE2_DMBLNK)) 17239118499SMarek Behún i2c_smbus_write_byte_data(client, PCA963X_MODE2, 17356a1740cSRicardo Ribalda Delgado mode2 | PCA963X_MODE2_DMBLNK); 17456a1740cSRicardo Ribalda Delgado 1755db85093SMarek Behún mutex_lock(&led->chip->mutex); 17639118499SMarek Behún 17739118499SMarek Behún ledout = i2c_smbus_read_byte_data(client, ledout_addr); 17839118499SMarek Behún if ((ledout & mask) != (PCA963X_LED_GRP_PWM << shift)) { 17939118499SMarek Behún val = (ledout & ~mask) | (PCA963X_LED_GRP_PWM << shift); 18039118499SMarek Behún i2c_smbus_write_byte_data(client, ledout_addr, val); 18139118499SMarek Behún } 18239118499SMarek Behún 1835db85093SMarek Behún mutex_unlock(&led->chip->mutex); 18456a1740cSRicardo Ribalda Delgado } 18556a1740cSRicardo Ribalda Delgado 1865db85093SMarek Behún static int pca963x_power_state(struct pca963x_led *led) 187a8c170b0SMatt Ranostay { 1885db85093SMarek Behún struct i2c_client *client = led->chip->client; 1895db85093SMarek Behún unsigned long *leds_on = &led->chip->leds_on; 19039118499SMarek Behún unsigned long cached_leds = *leds_on; 191a8c170b0SMatt Ranostay 1925db85093SMarek Behún if (led->led_cdev.brightness) 1935db85093SMarek Behún set_bit(led->led_num, leds_on); 194a8c170b0SMatt Ranostay else 1955db85093SMarek Behún clear_bit(led->led_num, leds_on); 196a8c170b0SMatt Ranostay 197a8c170b0SMatt Ranostay if (!(*leds_on) != !cached_leds) 19839118499SMarek Behún return i2c_smbus_write_byte_data(client, PCA963X_MODE1, 19939118499SMarek Behún *leds_on ? 0 : BIT(4)); 200a8c170b0SMatt Ranostay 201a8c170b0SMatt Ranostay return 0; 202a8c170b0SMatt Ranostay } 203a8c170b0SMatt Ranostay 2045029a2e3SAndrew Lunn static int pca963x_led_set(struct led_classdev *led_cdev, 20556a1740cSRicardo Ribalda Delgado enum led_brightness value) 20656a1740cSRicardo Ribalda Delgado { 2075db85093SMarek Behún struct pca963x_led *led; 208a8c170b0SMatt Ranostay int ret; 20956a1740cSRicardo Ribalda Delgado 2105db85093SMarek Behún led = container_of(led_cdev, struct pca963x_led, led_cdev); 21156a1740cSRicardo Ribalda Delgado 2125db85093SMarek Behún mutex_lock(&led->chip->mutex); 213a8c170b0SMatt Ranostay 2145db85093SMarek Behún ret = pca963x_brightness(led, value); 215a8c170b0SMatt Ranostay if (ret < 0) 216a8c170b0SMatt Ranostay goto unlock; 2175db85093SMarek Behún ret = pca963x_power_state(led); 218a8c170b0SMatt Ranostay 219a8c170b0SMatt Ranostay unlock: 2205db85093SMarek Behún mutex_unlock(&led->chip->mutex); 221a8c170b0SMatt Ranostay return ret; 22256a1740cSRicardo Ribalda Delgado } 22356a1740cSRicardo Ribalda Delgado 2245db85093SMarek Behún static unsigned int pca963x_period_scale(struct pca963x_led *led, 22535c7d301SMatt Ranostay unsigned int val) 22635c7d301SMatt Ranostay { 2275db85093SMarek Behún unsigned int scaling = led->chip->chipdef->scaling; 22835c7d301SMatt Ranostay 22935c7d301SMatt Ranostay return scaling ? DIV_ROUND_CLOSEST(val * scaling, 1000) : val; 23035c7d301SMatt Ranostay } 23135c7d301SMatt Ranostay 23256a1740cSRicardo Ribalda Delgado static int pca963x_blink_set(struct led_classdev *led_cdev, 23356a1740cSRicardo Ribalda Delgado unsigned long *delay_on, unsigned long *delay_off) 23456a1740cSRicardo Ribalda Delgado { 23556a1740cSRicardo Ribalda Delgado unsigned long time_on, time_off, period; 2365db85093SMarek Behún struct pca963x_led *led; 23756a1740cSRicardo Ribalda Delgado u8 gdc, gfrq; 23856a1740cSRicardo Ribalda Delgado 2395db85093SMarek Behún led = container_of(led_cdev, struct pca963x_led, led_cdev); 24056a1740cSRicardo Ribalda Delgado 24156a1740cSRicardo Ribalda Delgado time_on = *delay_on; 24256a1740cSRicardo Ribalda Delgado time_off = *delay_off; 24356a1740cSRicardo Ribalda Delgado 24456a1740cSRicardo Ribalda Delgado /* If both zero, pick reasonable defaults of 500ms each */ 24556a1740cSRicardo Ribalda Delgado if (!time_on && !time_off) { 24656a1740cSRicardo Ribalda Delgado time_on = 500; 24756a1740cSRicardo Ribalda Delgado time_off = 500; 24856a1740cSRicardo Ribalda Delgado } 24956a1740cSRicardo Ribalda Delgado 2505db85093SMarek Behún period = pca963x_period_scale(led, time_on + time_off); 25156a1740cSRicardo Ribalda Delgado 25256a1740cSRicardo Ribalda Delgado /* If period not supported by hardware, default to someting sane. */ 25356a1740cSRicardo Ribalda Delgado if ((period < PCA963X_BLINK_PERIOD_MIN) || 25456a1740cSRicardo Ribalda Delgado (period > PCA963X_BLINK_PERIOD_MAX)) { 25556a1740cSRicardo Ribalda Delgado time_on = 500; 25656a1740cSRicardo Ribalda Delgado time_off = 500; 2575db85093SMarek Behún period = pca963x_period_scale(led, 1000); 25856a1740cSRicardo Ribalda Delgado } 25956a1740cSRicardo Ribalda Delgado 26056a1740cSRicardo Ribalda Delgado /* 26156a1740cSRicardo Ribalda Delgado * From manual: duty cycle = (GDC / 256) -> 26256a1740cSRicardo Ribalda Delgado * (time_on / period) = (GDC / 256) -> 26356a1740cSRicardo Ribalda Delgado * GDC = ((time_on * 256) / period) 26456a1740cSRicardo Ribalda Delgado */ 2655db85093SMarek Behún gdc = (pca963x_period_scale(led, time_on) * 256) / period; 26656a1740cSRicardo Ribalda Delgado 26756a1740cSRicardo Ribalda Delgado /* 26856a1740cSRicardo Ribalda Delgado * From manual: period = ((GFRQ + 1) / 24) in seconds. 26956a1740cSRicardo Ribalda Delgado * So, period (in ms) = (((GFRQ + 1) / 24) * 1000) -> 27056a1740cSRicardo Ribalda Delgado * GFRQ = ((period * 24 / 1000) - 1) 27156a1740cSRicardo Ribalda Delgado */ 27256a1740cSRicardo Ribalda Delgado gfrq = (period * 24 / 1000) - 1; 27356a1740cSRicardo Ribalda Delgado 2745db85093SMarek Behún led->gdc = gdc; 2755db85093SMarek Behún led->gfrq = gfrq; 27656a1740cSRicardo Ribalda Delgado 2775db85093SMarek Behún pca963x_blink(led); 27856a1740cSRicardo Ribalda Delgado 27956a1740cSRicardo Ribalda Delgado *delay_on = time_on; 28056a1740cSRicardo Ribalda Delgado *delay_off = time_off; 28156a1740cSRicardo Ribalda Delgado 28256a1740cSRicardo Ribalda Delgado return 0; 28356a1740cSRicardo Ribalda Delgado } 28456a1740cSRicardo Ribalda Delgado 28585fc8efeSMarek Behún static int pca963x_register_leds(struct i2c_client *client, 28685fc8efeSMarek Behún struct pca963x *chip) 28756a1740cSRicardo Ribalda Delgado { 28885fc8efeSMarek Behún struct pca963x_chipdef *chipdef = chip->chipdef; 28985fc8efeSMarek Behún struct pca963x_led *led = chip->leds; 29085fc8efeSMarek Behún struct device *dev = &client->dev; 2910b6034d8SAndy Shevchenko struct fwnode_handle *child; 29285fc8efeSMarek Behún bool hw_blink; 29385fc8efeSMarek Behún s32 mode2; 29456a1740cSRicardo Ribalda Delgado u32 reg; 29585fc8efeSMarek Behún int ret; 29656a1740cSRicardo Ribalda Delgado 29739118499SMarek Behún if (device_property_read_u32(dev, "nxp,period-scale", 298fc0b1ecaSMarek Behún &chipdef->scaling)) 299fc0b1ecaSMarek Behún chipdef->scaling = 1000; 30035c7d301SMatt Ranostay 30185fc8efeSMarek Behún hw_blink = device_property_read_bool(dev, "nxp,hw-blink"); 30285fc8efeSMarek Behún 30385fc8efeSMarek Behún mode2 = i2c_smbus_read_byte_data(client, PCA963X_MODE2); 30485fc8efeSMarek Behún if (mode2 < 0) 30585fc8efeSMarek Behún return mode2; 30685fc8efeSMarek Behún 30785fc8efeSMarek Behún /* default to open-drain unless totem pole (push-pull) is specified */ 30885fc8efeSMarek Behún if (device_property_read_bool(dev, "nxp,totem-pole")) 30985fc8efeSMarek Behún mode2 |= PCA963X_MODE2_OUTDRV; 31085fc8efeSMarek Behún else 31185fc8efeSMarek Behún mode2 &= ~PCA963X_MODE2_OUTDRV; 31285fc8efeSMarek Behún 313bb29b9ccSAnders Darander /* default to non-inverted output, unless inverted is specified */ 31439118499SMarek Behún if (device_property_read_bool(dev, "nxp,inverted-out")) 31585fc8efeSMarek Behún mode2 |= PCA963X_MODE2_INVRT; 316bb29b9ccSAnders Darander else 31785fc8efeSMarek Behún mode2 &= ~PCA963X_MODE2_INVRT; 318bb29b9ccSAnders Darander 31985fc8efeSMarek Behún ret = i2c_smbus_write_byte_data(client, PCA963X_MODE2, mode2); 32085fc8efeSMarek Behún if (ret < 0) 32185fc8efeSMarek Behún return ret; 32285fc8efeSMarek Behún 32385fc8efeSMarek Behún device_for_each_child_node(dev, child) { 324564ead12SMarek Behún struct led_init_data init_data = {}; 325564ead12SMarek Behún char default_label[32]; 326564ead12SMarek Behún 32785fc8efeSMarek Behún ret = fwnode_property_read_u32(child, "reg", ®); 32885fc8efeSMarek Behún if (ret || reg >= chipdef->n_leds) { 32985fc8efeSMarek Behún dev_err(dev, "Invalid 'reg' property for node %pfw\n", 33085fc8efeSMarek Behún child); 33185fc8efeSMarek Behún ret = -EINVAL; 33285fc8efeSMarek Behún goto err; 33385fc8efeSMarek Behún } 33485fc8efeSMarek Behún 33585fc8efeSMarek Behún led->led_num = reg; 33685fc8efeSMarek Behún led->chip = chip; 33785fc8efeSMarek Behún led->led_cdev.brightness_set_blocking = pca963x_led_set; 33885fc8efeSMarek Behún if (hw_blink) 33985fc8efeSMarek Behún led->led_cdev.blink_set = pca963x_blink_set; 34085fc8efeSMarek Behún 341564ead12SMarek Behún init_data.fwnode = child; 342564ead12SMarek Behún /* for backwards compatibility */ 343564ead12SMarek Behún init_data.devicename = "pca963x"; 344564ead12SMarek Behún snprintf(default_label, sizeof(default_label), "%d:%.2x:%u", 345564ead12SMarek Behún client->adapter->nr, client->addr, reg); 346564ead12SMarek Behún init_data.default_label = default_label; 347564ead12SMarek Behún 348564ead12SMarek Behún ret = devm_led_classdev_register_ext(dev, &led->led_cdev, 349564ead12SMarek Behún &init_data); 35085fc8efeSMarek Behún if (ret) { 35185fc8efeSMarek Behún dev_err(dev, "Failed to register LED for node %pfw\n", 35285fc8efeSMarek Behún child); 35385fc8efeSMarek Behún goto err; 35485fc8efeSMarek Behún } 35585fc8efeSMarek Behún 35685fc8efeSMarek Behún ++led; 35785fc8efeSMarek Behún } 35885fc8efeSMarek Behún 35985fc8efeSMarek Behún return 0; 36085fc8efeSMarek Behún err: 36185fc8efeSMarek Behún fwnode_handle_put(child); 36285fc8efeSMarek Behún return ret; 36356a1740cSRicardo Ribalda Delgado } 36456a1740cSRicardo Ribalda Delgado 36556a1740cSRicardo Ribalda Delgado static const struct of_device_id of_pca963x_match[] = { 36656a1740cSRicardo Ribalda Delgado { .compatible = "nxp,pca9632", }, 36756a1740cSRicardo Ribalda Delgado { .compatible = "nxp,pca9633", }, 36856a1740cSRicardo Ribalda Delgado { .compatible = "nxp,pca9634", }, 3693dfedb9dSPeter Meerwald { .compatible = "nxp,pca9635", }, 37056a1740cSRicardo Ribalda Delgado {}, 37156a1740cSRicardo Ribalda Delgado }; 3724d59ed85SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, of_pca963x_match); 37356a1740cSRicardo Ribalda Delgado 37456a1740cSRicardo Ribalda Delgado static int pca963x_probe(struct i2c_client *client, 37556a1740cSRicardo Ribalda Delgado const struct i2c_device_id *id) 37656a1740cSRicardo Ribalda Delgado { 37739118499SMarek Behún struct device *dev = &client->dev; 378fc0b1ecaSMarek Behún struct pca963x_chipdef *chipdef; 379fc0b1ecaSMarek Behún struct pca963x *chip; 38085fc8efeSMarek Behún int i, count; 38156a1740cSRicardo Ribalda Delgado 382fc0b1ecaSMarek Behún chipdef = &pca963x_chipdefs[id->driver_data]; 38356a1740cSRicardo Ribalda Delgado 38485fc8efeSMarek Behún count = device_get_child_node_count(dev); 38585fc8efeSMarek Behún if (!count || count > chipdef->n_leds) { 38685fc8efeSMarek Behún dev_err(dev, "Node %pfw must define between 1 and %d LEDs\n", 38785fc8efeSMarek Behún dev_fwnode(dev), chipdef->n_leds); 38856a1740cSRicardo Ribalda Delgado return -EINVAL; 38956a1740cSRicardo Ribalda Delgado } 39056a1740cSRicardo Ribalda Delgado 39185fc8efeSMarek Behún chip = devm_kzalloc(dev, struct_size(chip, leds, count), GFP_KERNEL); 392fc0b1ecaSMarek Behún if (!chip) 39356a1740cSRicardo Ribalda Delgado return -ENOMEM; 39456a1740cSRicardo Ribalda Delgado 395fc0b1ecaSMarek Behún i2c_set_clientdata(client, chip); 39656a1740cSRicardo Ribalda Delgado 397fc0b1ecaSMarek Behún mutex_init(&chip->mutex); 398fc0b1ecaSMarek Behún chip->chipdef = chipdef; 399fc0b1ecaSMarek Behún chip->client = client; 40056a1740cSRicardo Ribalda Delgado 40156a1740cSRicardo Ribalda Delgado /* Turn off LEDs by default*/ 402fc0b1ecaSMarek Behún for (i = 0; i < chipdef->n_leds / 4; i++) 403fc0b1ecaSMarek Behún i2c_smbus_write_byte_data(client, chipdef->ledout_base + i, 0x00); 40456a1740cSRicardo Ribalda Delgado 405a8c170b0SMatt Ranostay /* Disable LED all-call address, and power down initially */ 406a8c170b0SMatt Ranostay i2c_smbus_write_byte_data(client, PCA963X_MODE1, BIT(4)); 40756a1740cSRicardo Ribalda Delgado 40885fc8efeSMarek Behún return pca963x_register_leds(client, chip); 40956a1740cSRicardo Ribalda Delgado } 41056a1740cSRicardo Ribalda Delgado 41156a1740cSRicardo Ribalda Delgado static struct i2c_driver pca963x_driver = { 41256a1740cSRicardo Ribalda Delgado .driver = { 41356a1740cSRicardo Ribalda Delgado .name = "leds-pca963x", 4140b6034d8SAndy Shevchenko .of_match_table = of_pca963x_match, 41556a1740cSRicardo Ribalda Delgado }, 41656a1740cSRicardo Ribalda Delgado .probe = pca963x_probe, 41756a1740cSRicardo Ribalda Delgado .id_table = pca963x_id, 41856a1740cSRicardo Ribalda Delgado }; 41956a1740cSRicardo Ribalda Delgado 42056a1740cSRicardo Ribalda Delgado module_i2c_driver(pca963x_driver); 42156a1740cSRicardo Ribalda Delgado 42256a1740cSRicardo Ribalda Delgado MODULE_AUTHOR("Peter Meerwald <p.meerwald@bct-electronic.com>"); 42356a1740cSRicardo Ribalda Delgado MODULE_DESCRIPTION("PCA963X LED driver"); 42456a1740cSRicardo Ribalda Delgado MODULE_LICENSE("GPL v2"); 425