156a1740cSRicardo Ribalda Delgado /* 256a1740cSRicardo Ribalda Delgado * Copyright 2011 bct electronic GmbH 356a1740cSRicardo Ribalda Delgado * Copyright 2013 Qtechnology/AS 456a1740cSRicardo Ribalda Delgado * 556a1740cSRicardo Ribalda Delgado * Author: Peter Meerwald <p.meerwald@bct-electronic.com> 656a1740cSRicardo Ribalda Delgado * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com> 756a1740cSRicardo Ribalda Delgado * 856a1740cSRicardo Ribalda Delgado * Based on leds-pca955x.c 956a1740cSRicardo Ribalda Delgado * 1056a1740cSRicardo Ribalda Delgado * This file is subject to the terms and conditions of version 2 of 1156a1740cSRicardo Ribalda Delgado * the GNU General Public License. See the file COPYING in the main 1256a1740cSRicardo Ribalda Delgado * directory of this archive for more details. 1356a1740cSRicardo Ribalda Delgado * 1456a1740cSRicardo Ribalda Delgado * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62) 153dfedb9dSPeter Meerwald * LED driver for the PCA9634/5 I2C LED driver (7-bit slave address set by hw.) 1656a1740cSRicardo Ribalda Delgado * 1756a1740cSRicardo Ribalda Delgado * Note that hardware blinking violates the leds infrastructure driver 1856a1740cSRicardo Ribalda Delgado * interface since the hardware only supports blinking all LEDs with the 1956a1740cSRicardo Ribalda Delgado * same delay_on/delay_off rates. That is, only the LEDs that are set to 2056a1740cSRicardo Ribalda Delgado * blink will actually blink but all LEDs that are set to blink will blink 2156a1740cSRicardo Ribalda Delgado * in identical fashion. The delay_on/delay_off values of the last LED 2256a1740cSRicardo Ribalda Delgado * that is set to blink will be used for all of the blinking LEDs. 2356a1740cSRicardo Ribalda Delgado * Hardware blinking is disabled by default but can be enabled by setting 2456a1740cSRicardo Ribalda Delgado * the 'blink_type' member in the platform_data struct to 'PCA963X_HW_BLINK' 2556a1740cSRicardo Ribalda Delgado * or by adding the 'nxp,hw-blink' property to the DTS. 2656a1740cSRicardo Ribalda Delgado */ 2756a1740cSRicardo Ribalda Delgado 2856a1740cSRicardo Ribalda Delgado #include <linux/module.h> 2956a1740cSRicardo Ribalda Delgado #include <linux/delay.h> 3056a1740cSRicardo Ribalda Delgado #include <linux/string.h> 3156a1740cSRicardo Ribalda Delgado #include <linux/ctype.h> 3256a1740cSRicardo Ribalda Delgado #include <linux/leds.h> 3356a1740cSRicardo Ribalda Delgado #include <linux/err.h> 3456a1740cSRicardo Ribalda Delgado #include <linux/i2c.h> 350b6034d8SAndy Shevchenko #include <linux/property.h> 3656a1740cSRicardo Ribalda Delgado #include <linux/slab.h> 3756a1740cSRicardo Ribalda Delgado #include <linux/of.h> 3856a1740cSRicardo Ribalda Delgado #include <linux/platform_data/leds-pca963x.h> 3956a1740cSRicardo Ribalda Delgado 4056a1740cSRicardo Ribalda Delgado /* LED select registers determine the source that drives LED outputs */ 4156a1740cSRicardo Ribalda Delgado #define PCA963X_LED_OFF 0x0 /* LED driver off */ 4256a1740cSRicardo Ribalda Delgado #define PCA963X_LED_ON 0x1 /* LED driver on */ 4356a1740cSRicardo Ribalda Delgado #define PCA963X_LED_PWM 0x2 /* Controlled through PWM */ 4456a1740cSRicardo Ribalda Delgado #define PCA963X_LED_GRP_PWM 0x3 /* Controlled through PWM/GRPPWM */ 4556a1740cSRicardo Ribalda Delgado 4656a1740cSRicardo Ribalda Delgado #define PCA963X_MODE2_DMBLNK 0x20 /* Enable blinking */ 4756a1740cSRicardo Ribalda Delgado 4856a1740cSRicardo Ribalda Delgado #define PCA963X_MODE1 0x00 4956a1740cSRicardo Ribalda Delgado #define PCA963X_MODE2 0x01 5056a1740cSRicardo Ribalda Delgado #define PCA963X_PWM_BASE 0x02 5156a1740cSRicardo Ribalda Delgado 5256a1740cSRicardo Ribalda Delgado enum pca963x_type { 5356a1740cSRicardo Ribalda Delgado pca9633, 5456a1740cSRicardo Ribalda Delgado pca9634, 553dfedb9dSPeter Meerwald pca9635, 5656a1740cSRicardo Ribalda Delgado }; 5756a1740cSRicardo Ribalda Delgado 5856a1740cSRicardo Ribalda Delgado struct pca963x_chipdef { 5956a1740cSRicardo Ribalda Delgado u8 grppwm; 6056a1740cSRicardo Ribalda Delgado u8 grpfreq; 6156a1740cSRicardo Ribalda Delgado u8 ledout_base; 6256a1740cSRicardo Ribalda Delgado int n_leds; 6335c7d301SMatt Ranostay unsigned int scaling; 6456a1740cSRicardo Ribalda Delgado }; 6556a1740cSRicardo Ribalda Delgado 6656a1740cSRicardo Ribalda Delgado static struct pca963x_chipdef pca963x_chipdefs[] = { 6756a1740cSRicardo Ribalda Delgado [pca9633] = { 6856a1740cSRicardo Ribalda Delgado .grppwm = 0x6, 6956a1740cSRicardo Ribalda Delgado .grpfreq = 0x7, 7056a1740cSRicardo Ribalda Delgado .ledout_base = 0x8, 7156a1740cSRicardo Ribalda Delgado .n_leds = 4, 7256a1740cSRicardo Ribalda Delgado }, 7356a1740cSRicardo Ribalda Delgado [pca9634] = { 7456a1740cSRicardo Ribalda Delgado .grppwm = 0xa, 7556a1740cSRicardo Ribalda Delgado .grpfreq = 0xb, 7656a1740cSRicardo Ribalda Delgado .ledout_base = 0xc, 7756a1740cSRicardo Ribalda Delgado .n_leds = 8, 7856a1740cSRicardo Ribalda Delgado }, 793dfedb9dSPeter Meerwald [pca9635] = { 803dfedb9dSPeter Meerwald .grppwm = 0x12, 813dfedb9dSPeter Meerwald .grpfreq = 0x13, 823dfedb9dSPeter Meerwald .ledout_base = 0x14, 833dfedb9dSPeter Meerwald .n_leds = 16, 843dfedb9dSPeter Meerwald }, 8556a1740cSRicardo Ribalda Delgado }; 8656a1740cSRicardo Ribalda Delgado 8756a1740cSRicardo Ribalda Delgado /* Total blink period in milliseconds */ 8856a1740cSRicardo Ribalda Delgado #define PCA963X_BLINK_PERIOD_MIN 42 8956a1740cSRicardo Ribalda Delgado #define PCA963X_BLINK_PERIOD_MAX 10667 9056a1740cSRicardo Ribalda Delgado 9156a1740cSRicardo Ribalda Delgado static const struct i2c_device_id pca963x_id[] = { 9256a1740cSRicardo Ribalda Delgado { "pca9632", pca9633 }, 9356a1740cSRicardo Ribalda Delgado { "pca9633", pca9633 }, 9456a1740cSRicardo Ribalda Delgado { "pca9634", pca9634 }, 953dfedb9dSPeter Meerwald { "pca9635", pca9635 }, 9656a1740cSRicardo Ribalda Delgado { } 9756a1740cSRicardo Ribalda Delgado }; 9856a1740cSRicardo Ribalda Delgado MODULE_DEVICE_TABLE(i2c, pca963x_id); 9956a1740cSRicardo Ribalda Delgado 10056a1740cSRicardo Ribalda Delgado struct pca963x_led; 10156a1740cSRicardo Ribalda Delgado 10256a1740cSRicardo Ribalda Delgado struct pca963x { 10356a1740cSRicardo Ribalda Delgado struct pca963x_chipdef *chipdef; 10456a1740cSRicardo Ribalda Delgado struct mutex mutex; 10556a1740cSRicardo Ribalda Delgado struct i2c_client *client; 10656a1740cSRicardo Ribalda Delgado struct pca963x_led *leds; 107a8c170b0SMatt Ranostay unsigned long leds_on; 10856a1740cSRicardo Ribalda Delgado }; 10956a1740cSRicardo Ribalda Delgado 11056a1740cSRicardo Ribalda Delgado struct pca963x_led { 11156a1740cSRicardo Ribalda Delgado struct pca963x *chip; 11256a1740cSRicardo Ribalda Delgado struct led_classdev led_cdev; 1133dfedb9dSPeter Meerwald int led_num; /* 0 .. 15 potentially */ 11456a1740cSRicardo Ribalda Delgado char name[32]; 11556a1740cSRicardo Ribalda Delgado u8 gdc; 11656a1740cSRicardo Ribalda Delgado u8 gfrq; 11756a1740cSRicardo Ribalda Delgado }; 11856a1740cSRicardo Ribalda Delgado 1195029a2e3SAndrew Lunn static int pca963x_brightness(struct pca963x_led *pca963x, 1205029a2e3SAndrew Lunn enum led_brightness brightness) 12156a1740cSRicardo Ribalda Delgado { 12256a1740cSRicardo Ribalda Delgado u8 ledout_addr = pca963x->chip->chipdef->ledout_base 12356a1740cSRicardo Ribalda Delgado + (pca963x->led_num / 4); 12456a1740cSRicardo Ribalda Delgado u8 ledout; 12556a1740cSRicardo Ribalda Delgado int shift = 2 * (pca963x->led_num % 4); 12656a1740cSRicardo Ribalda Delgado u8 mask = 0x3 << shift; 1275029a2e3SAndrew Lunn int ret; 12856a1740cSRicardo Ribalda Delgado 12956a1740cSRicardo Ribalda Delgado ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr); 1305029a2e3SAndrew Lunn switch (brightness) { 13156a1740cSRicardo Ribalda Delgado case LED_FULL: 1325029a2e3SAndrew Lunn ret = i2c_smbus_write_byte_data(pca963x->chip->client, 1335029a2e3SAndrew Lunn ledout_addr, 13456a1740cSRicardo Ribalda Delgado (ledout & ~mask) | (PCA963X_LED_ON << shift)); 13556a1740cSRicardo Ribalda Delgado break; 13656a1740cSRicardo Ribalda Delgado case LED_OFF: 1375029a2e3SAndrew Lunn ret = i2c_smbus_write_byte_data(pca963x->chip->client, 1385029a2e3SAndrew Lunn ledout_addr, ledout & ~mask); 13956a1740cSRicardo Ribalda Delgado break; 14056a1740cSRicardo Ribalda Delgado default: 1415029a2e3SAndrew Lunn ret = i2c_smbus_write_byte_data(pca963x->chip->client, 14256a1740cSRicardo Ribalda Delgado PCA963X_PWM_BASE + pca963x->led_num, 1435029a2e3SAndrew Lunn brightness); 1445029a2e3SAndrew Lunn if (ret < 0) 145a8c170b0SMatt Ranostay return ret; 1465029a2e3SAndrew Lunn ret = i2c_smbus_write_byte_data(pca963x->chip->client, 1475029a2e3SAndrew Lunn ledout_addr, 14856a1740cSRicardo Ribalda Delgado (ledout & ~mask) | (PCA963X_LED_PWM << shift)); 14956a1740cSRicardo Ribalda Delgado break; 15056a1740cSRicardo Ribalda Delgado } 151a8c170b0SMatt Ranostay 1525029a2e3SAndrew Lunn return ret; 15356a1740cSRicardo Ribalda Delgado } 15456a1740cSRicardo Ribalda Delgado 1555029a2e3SAndrew Lunn static void pca963x_blink(struct pca963x_led *pca963x) 15656a1740cSRicardo Ribalda Delgado { 15756a1740cSRicardo Ribalda Delgado u8 ledout_addr = pca963x->chip->chipdef->ledout_base + 15856a1740cSRicardo Ribalda Delgado (pca963x->led_num / 4); 15956a1740cSRicardo Ribalda Delgado u8 ledout; 16056a1740cSRicardo Ribalda Delgado u8 mode2 = i2c_smbus_read_byte_data(pca963x->chip->client, 16156a1740cSRicardo Ribalda Delgado PCA963X_MODE2); 16256a1740cSRicardo Ribalda Delgado int shift = 2 * (pca963x->led_num % 4); 16356a1740cSRicardo Ribalda Delgado u8 mask = 0x3 << shift; 16456a1740cSRicardo Ribalda Delgado 16556a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, 16656a1740cSRicardo Ribalda Delgado pca963x->chip->chipdef->grppwm, pca963x->gdc); 16756a1740cSRicardo Ribalda Delgado 16856a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, 16956a1740cSRicardo Ribalda Delgado pca963x->chip->chipdef->grpfreq, pca963x->gfrq); 17056a1740cSRicardo Ribalda Delgado 17156a1740cSRicardo Ribalda Delgado if (!(mode2 & PCA963X_MODE2_DMBLNK)) 17256a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, PCA963X_MODE2, 17356a1740cSRicardo Ribalda Delgado mode2 | PCA963X_MODE2_DMBLNK); 17456a1740cSRicardo Ribalda Delgado 17556a1740cSRicardo Ribalda Delgado mutex_lock(&pca963x->chip->mutex); 17656a1740cSRicardo Ribalda Delgado ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr); 17756a1740cSRicardo Ribalda Delgado if ((ledout & mask) != (PCA963X_LED_GRP_PWM << shift)) 17856a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr, 17956a1740cSRicardo Ribalda Delgado (ledout & ~mask) | (PCA963X_LED_GRP_PWM << shift)); 18056a1740cSRicardo Ribalda Delgado mutex_unlock(&pca963x->chip->mutex); 18156a1740cSRicardo Ribalda Delgado } 18256a1740cSRicardo Ribalda Delgado 183a8c170b0SMatt Ranostay static int pca963x_power_state(struct pca963x_led *pca963x) 184a8c170b0SMatt Ranostay { 185a8c170b0SMatt Ranostay unsigned long *leds_on = &pca963x->chip->leds_on; 186a8c170b0SMatt Ranostay unsigned long cached_leds = pca963x->chip->leds_on; 187a8c170b0SMatt Ranostay 188a8c170b0SMatt Ranostay if (pca963x->led_cdev.brightness) 189a8c170b0SMatt Ranostay set_bit(pca963x->led_num, leds_on); 190a8c170b0SMatt Ranostay else 191a8c170b0SMatt Ranostay clear_bit(pca963x->led_num, leds_on); 192a8c170b0SMatt Ranostay 193a8c170b0SMatt Ranostay if (!(*leds_on) != !cached_leds) 194a8c170b0SMatt Ranostay return i2c_smbus_write_byte_data(pca963x->chip->client, 195a8c170b0SMatt Ranostay PCA963X_MODE1, *leds_on ? 0 : BIT(4)); 196a8c170b0SMatt Ranostay 197a8c170b0SMatt Ranostay return 0; 198a8c170b0SMatt Ranostay } 199a8c170b0SMatt Ranostay 2005029a2e3SAndrew Lunn static int pca963x_led_set(struct led_classdev *led_cdev, 20156a1740cSRicardo Ribalda Delgado enum led_brightness value) 20256a1740cSRicardo Ribalda Delgado { 20356a1740cSRicardo Ribalda Delgado struct pca963x_led *pca963x; 204a8c170b0SMatt Ranostay int ret; 20556a1740cSRicardo Ribalda Delgado 20656a1740cSRicardo Ribalda Delgado pca963x = container_of(led_cdev, struct pca963x_led, led_cdev); 20756a1740cSRicardo Ribalda Delgado 208a8c170b0SMatt Ranostay mutex_lock(&pca963x->chip->mutex); 209a8c170b0SMatt Ranostay 210a8c170b0SMatt Ranostay ret = pca963x_brightness(pca963x, value); 211a8c170b0SMatt Ranostay if (ret < 0) 212a8c170b0SMatt Ranostay goto unlock; 213a8c170b0SMatt Ranostay ret = pca963x_power_state(pca963x); 214a8c170b0SMatt Ranostay 215a8c170b0SMatt Ranostay unlock: 216a8c170b0SMatt Ranostay mutex_unlock(&pca963x->chip->mutex); 217a8c170b0SMatt Ranostay return ret; 21856a1740cSRicardo Ribalda Delgado } 21956a1740cSRicardo Ribalda Delgado 22035c7d301SMatt Ranostay static unsigned int pca963x_period_scale(struct pca963x_led *pca963x, 22135c7d301SMatt Ranostay unsigned int val) 22235c7d301SMatt Ranostay { 22335c7d301SMatt Ranostay unsigned int scaling = pca963x->chip->chipdef->scaling; 22435c7d301SMatt Ranostay 22535c7d301SMatt Ranostay return scaling ? DIV_ROUND_CLOSEST(val * scaling, 1000) : val; 22635c7d301SMatt Ranostay } 22735c7d301SMatt Ranostay 22856a1740cSRicardo Ribalda Delgado static int pca963x_blink_set(struct led_classdev *led_cdev, 22956a1740cSRicardo Ribalda Delgado unsigned long *delay_on, unsigned long *delay_off) 23056a1740cSRicardo Ribalda Delgado { 23156a1740cSRicardo Ribalda Delgado struct pca963x_led *pca963x; 23256a1740cSRicardo Ribalda Delgado unsigned long time_on, time_off, period; 23356a1740cSRicardo Ribalda Delgado u8 gdc, gfrq; 23456a1740cSRicardo Ribalda Delgado 23556a1740cSRicardo Ribalda Delgado pca963x = container_of(led_cdev, struct pca963x_led, led_cdev); 23656a1740cSRicardo Ribalda Delgado 23756a1740cSRicardo Ribalda Delgado time_on = *delay_on; 23856a1740cSRicardo Ribalda Delgado time_off = *delay_off; 23956a1740cSRicardo Ribalda Delgado 24056a1740cSRicardo Ribalda Delgado /* If both zero, pick reasonable defaults of 500ms each */ 24156a1740cSRicardo Ribalda Delgado if (!time_on && !time_off) { 24256a1740cSRicardo Ribalda Delgado time_on = 500; 24356a1740cSRicardo Ribalda Delgado time_off = 500; 24456a1740cSRicardo Ribalda Delgado } 24556a1740cSRicardo Ribalda Delgado 24635c7d301SMatt Ranostay period = pca963x_period_scale(pca963x, time_on + time_off); 24756a1740cSRicardo Ribalda Delgado 24856a1740cSRicardo Ribalda Delgado /* If period not supported by hardware, default to someting sane. */ 24956a1740cSRicardo Ribalda Delgado if ((period < PCA963X_BLINK_PERIOD_MIN) || 25056a1740cSRicardo Ribalda Delgado (period > PCA963X_BLINK_PERIOD_MAX)) { 25156a1740cSRicardo Ribalda Delgado time_on = 500; 25256a1740cSRicardo Ribalda Delgado time_off = 500; 25335c7d301SMatt Ranostay period = pca963x_period_scale(pca963x, 1000); 25456a1740cSRicardo Ribalda Delgado } 25556a1740cSRicardo Ribalda Delgado 25656a1740cSRicardo Ribalda Delgado /* 25756a1740cSRicardo Ribalda Delgado * From manual: duty cycle = (GDC / 256) -> 25856a1740cSRicardo Ribalda Delgado * (time_on / period) = (GDC / 256) -> 25956a1740cSRicardo Ribalda Delgado * GDC = ((time_on * 256) / period) 26056a1740cSRicardo Ribalda Delgado */ 26135c7d301SMatt Ranostay gdc = (pca963x_period_scale(pca963x, time_on) * 256) / period; 26256a1740cSRicardo Ribalda Delgado 26356a1740cSRicardo Ribalda Delgado /* 26456a1740cSRicardo Ribalda Delgado * From manual: period = ((GFRQ + 1) / 24) in seconds. 26556a1740cSRicardo Ribalda Delgado * So, period (in ms) = (((GFRQ + 1) / 24) * 1000) -> 26656a1740cSRicardo Ribalda Delgado * GFRQ = ((period * 24 / 1000) - 1) 26756a1740cSRicardo Ribalda Delgado */ 26856a1740cSRicardo Ribalda Delgado gfrq = (period * 24 / 1000) - 1; 26956a1740cSRicardo Ribalda Delgado 27056a1740cSRicardo Ribalda Delgado pca963x->gdc = gdc; 27156a1740cSRicardo Ribalda Delgado pca963x->gfrq = gfrq; 27256a1740cSRicardo Ribalda Delgado 2735029a2e3SAndrew Lunn pca963x_blink(pca963x); 27456a1740cSRicardo Ribalda Delgado 27556a1740cSRicardo Ribalda Delgado *delay_on = time_on; 27656a1740cSRicardo Ribalda Delgado *delay_off = time_off; 27756a1740cSRicardo Ribalda Delgado 27856a1740cSRicardo Ribalda Delgado return 0; 27956a1740cSRicardo Ribalda Delgado } 28056a1740cSRicardo Ribalda Delgado 28156a1740cSRicardo Ribalda Delgado static struct pca963x_platform_data * 2820b6034d8SAndy Shevchenko pca963x_get_pdata(struct i2c_client *client, struct pca963x_chipdef *chip) 28356a1740cSRicardo Ribalda Delgado { 28456a1740cSRicardo Ribalda Delgado struct pca963x_platform_data *pdata; 28556a1740cSRicardo Ribalda Delgado struct led_info *pca963x_leds; 2860b6034d8SAndy Shevchenko struct fwnode_handle *child; 28756a1740cSRicardo Ribalda Delgado int count; 28856a1740cSRicardo Ribalda Delgado 2890b6034d8SAndy Shevchenko count = device_get_child_node_count(&client->dev); 29056a1740cSRicardo Ribalda Delgado if (!count || count > chip->n_leds) 29156a1740cSRicardo Ribalda Delgado return ERR_PTR(-ENODEV); 29256a1740cSRicardo Ribalda Delgado 293a86854d0SKees Cook pca963x_leds = devm_kcalloc(&client->dev, 294a86854d0SKees Cook chip->n_leds, sizeof(struct led_info), GFP_KERNEL); 29556a1740cSRicardo Ribalda Delgado if (!pca963x_leds) 29656a1740cSRicardo Ribalda Delgado return ERR_PTR(-ENOMEM); 29756a1740cSRicardo Ribalda Delgado 2980b6034d8SAndy Shevchenko device_for_each_child_node(&client->dev, child) { 299a44b0f5eSGeert Uytterhoeven struct led_info led = {}; 30056a1740cSRicardo Ribalda Delgado u32 reg; 30156a1740cSRicardo Ribalda Delgado int res; 30256a1740cSRicardo Ribalda Delgado 3030b6034d8SAndy Shevchenko res = fwnode_property_read_u32(child, "reg", ®); 3048a6acd64SRicardo Ribalda Delgado if ((res != 0) || (reg >= chip->n_leds)) 3058a6acd64SRicardo Ribalda Delgado continue; 3060b6034d8SAndy Shevchenko 3070b6034d8SAndy Shevchenko res = fwnode_property_read_string(child, "label", &led.name); 3080b6034d8SAndy Shevchenko if ((res != 0) && is_of_node(child)) 3090b6034d8SAndy Shevchenko led.name = to_of_node(child)->name; 3100b6034d8SAndy Shevchenko 3110b6034d8SAndy Shevchenko fwnode_property_read_string(child, "linux,default-trigger", 3120b6034d8SAndy Shevchenko &led.default_trigger); 3130b6034d8SAndy Shevchenko 31456a1740cSRicardo Ribalda Delgado pca963x_leds[reg] = led; 31556a1740cSRicardo Ribalda Delgado } 31656a1740cSRicardo Ribalda Delgado pdata = devm_kzalloc(&client->dev, 31756a1740cSRicardo Ribalda Delgado sizeof(struct pca963x_platform_data), GFP_KERNEL); 31856a1740cSRicardo Ribalda Delgado if (!pdata) 31956a1740cSRicardo Ribalda Delgado return ERR_PTR(-ENOMEM); 32056a1740cSRicardo Ribalda Delgado 32156a1740cSRicardo Ribalda Delgado pdata->leds.leds = pca963x_leds; 3228a6acd64SRicardo Ribalda Delgado pdata->leds.num_leds = chip->n_leds; 32356a1740cSRicardo Ribalda Delgado 32456a1740cSRicardo Ribalda Delgado /* default to open-drain unless totem pole (push-pull) is specified */ 3250b6034d8SAndy Shevchenko if (device_property_read_bool(&client->dev, "nxp,totem-pole")) 32656a1740cSRicardo Ribalda Delgado pdata->outdrv = PCA963X_TOTEM_POLE; 32756a1740cSRicardo Ribalda Delgado else 32856a1740cSRicardo Ribalda Delgado pdata->outdrv = PCA963X_OPEN_DRAIN; 32956a1740cSRicardo Ribalda Delgado 33056a1740cSRicardo Ribalda Delgado /* default to software blinking unless hardware blinking is specified */ 3310b6034d8SAndy Shevchenko if (device_property_read_bool(&client->dev, "nxp,hw-blink")) 33256a1740cSRicardo Ribalda Delgado pdata->blink_type = PCA963X_HW_BLINK; 33356a1740cSRicardo Ribalda Delgado else 33456a1740cSRicardo Ribalda Delgado pdata->blink_type = PCA963X_SW_BLINK; 33556a1740cSRicardo Ribalda Delgado 3360b6034d8SAndy Shevchenko if (device_property_read_u32(&client->dev, "nxp,period-scale", 3370b6034d8SAndy Shevchenko &chip->scaling)) 33835c7d301SMatt Ranostay chip->scaling = 1000; 33935c7d301SMatt Ranostay 340bb29b9ccSAnders Darander /* default to non-inverted output, unless inverted is specified */ 3410b6034d8SAndy Shevchenko if (device_property_read_bool(&client->dev, "nxp,inverted-out")) 342bb29b9ccSAnders Darander pdata->dir = PCA963X_INVERTED; 343bb29b9ccSAnders Darander else 344bb29b9ccSAnders Darander pdata->dir = PCA963X_NORMAL; 345bb29b9ccSAnders Darander 34656a1740cSRicardo Ribalda Delgado return pdata; 34756a1740cSRicardo Ribalda Delgado } 34856a1740cSRicardo Ribalda Delgado 34956a1740cSRicardo Ribalda Delgado static const struct of_device_id of_pca963x_match[] = { 35056a1740cSRicardo Ribalda Delgado { .compatible = "nxp,pca9632", }, 35156a1740cSRicardo Ribalda Delgado { .compatible = "nxp,pca9633", }, 35256a1740cSRicardo Ribalda Delgado { .compatible = "nxp,pca9634", }, 3533dfedb9dSPeter Meerwald { .compatible = "nxp,pca9635", }, 35456a1740cSRicardo Ribalda Delgado {}, 35556a1740cSRicardo Ribalda Delgado }; 3564d59ed85SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, of_pca963x_match); 35756a1740cSRicardo Ribalda Delgado 35856a1740cSRicardo Ribalda Delgado static int pca963x_probe(struct i2c_client *client, 35956a1740cSRicardo Ribalda Delgado const struct i2c_device_id *id) 36056a1740cSRicardo Ribalda Delgado { 36156a1740cSRicardo Ribalda Delgado struct pca963x *pca963x_chip; 36256a1740cSRicardo Ribalda Delgado struct pca963x_led *pca963x; 36356a1740cSRicardo Ribalda Delgado struct pca963x_platform_data *pdata; 36456a1740cSRicardo Ribalda Delgado struct pca963x_chipdef *chip; 36556a1740cSRicardo Ribalda Delgado int i, err; 36656a1740cSRicardo Ribalda Delgado 36756a1740cSRicardo Ribalda Delgado chip = &pca963x_chipdefs[id->driver_data]; 36856a1740cSRicardo Ribalda Delgado pdata = dev_get_platdata(&client->dev); 36956a1740cSRicardo Ribalda Delgado 37056a1740cSRicardo Ribalda Delgado if (!pdata) { 3710b6034d8SAndy Shevchenko pdata = pca963x_get_pdata(client, chip); 37256a1740cSRicardo Ribalda Delgado if (IS_ERR(pdata)) { 37356a1740cSRicardo Ribalda Delgado dev_warn(&client->dev, "could not parse configuration\n"); 37456a1740cSRicardo Ribalda Delgado pdata = NULL; 37556a1740cSRicardo Ribalda Delgado } 37656a1740cSRicardo Ribalda Delgado } 37756a1740cSRicardo Ribalda Delgado 37856a1740cSRicardo Ribalda Delgado if (pdata && (pdata->leds.num_leds < 1 || 37956a1740cSRicardo Ribalda Delgado pdata->leds.num_leds > chip->n_leds)) { 38056a1740cSRicardo Ribalda Delgado dev_err(&client->dev, "board info must claim 1-%d LEDs", 38156a1740cSRicardo Ribalda Delgado chip->n_leds); 38256a1740cSRicardo Ribalda Delgado return -EINVAL; 38356a1740cSRicardo Ribalda Delgado } 38456a1740cSRicardo Ribalda Delgado 38556a1740cSRicardo Ribalda Delgado pca963x_chip = devm_kzalloc(&client->dev, sizeof(*pca963x_chip), 38656a1740cSRicardo Ribalda Delgado GFP_KERNEL); 38756a1740cSRicardo Ribalda Delgado if (!pca963x_chip) 38856a1740cSRicardo Ribalda Delgado return -ENOMEM; 389a86854d0SKees Cook pca963x = devm_kcalloc(&client->dev, chip->n_leds, sizeof(*pca963x), 39056a1740cSRicardo Ribalda Delgado GFP_KERNEL); 39156a1740cSRicardo Ribalda Delgado if (!pca963x) 39256a1740cSRicardo Ribalda Delgado return -ENOMEM; 39356a1740cSRicardo Ribalda Delgado 39456a1740cSRicardo Ribalda Delgado i2c_set_clientdata(client, pca963x_chip); 39556a1740cSRicardo Ribalda Delgado 39656a1740cSRicardo Ribalda Delgado mutex_init(&pca963x_chip->mutex); 39756a1740cSRicardo Ribalda Delgado pca963x_chip->chipdef = chip; 39856a1740cSRicardo Ribalda Delgado pca963x_chip->client = client; 39956a1740cSRicardo Ribalda Delgado pca963x_chip->leds = pca963x; 40056a1740cSRicardo Ribalda Delgado 40156a1740cSRicardo Ribalda Delgado /* Turn off LEDs by default*/ 4023dfedb9dSPeter Meerwald for (i = 0; i < chip->n_leds / 4; i++) 4033dfedb9dSPeter Meerwald i2c_smbus_write_byte_data(client, chip->ledout_base + i, 0x00); 40456a1740cSRicardo Ribalda Delgado 40556a1740cSRicardo Ribalda Delgado for (i = 0; i < chip->n_leds; i++) { 40656a1740cSRicardo Ribalda Delgado pca963x[i].led_num = i; 40756a1740cSRicardo Ribalda Delgado pca963x[i].chip = pca963x_chip; 40856a1740cSRicardo Ribalda Delgado 40956a1740cSRicardo Ribalda Delgado /* Platform data can specify LED names and default triggers */ 41056a1740cSRicardo Ribalda Delgado if (pdata && i < pdata->leds.num_leds) { 41156a1740cSRicardo Ribalda Delgado if (pdata->leds.leds[i].name) 41256a1740cSRicardo Ribalda Delgado snprintf(pca963x[i].name, 41356a1740cSRicardo Ribalda Delgado sizeof(pca963x[i].name), "pca963x:%s", 41456a1740cSRicardo Ribalda Delgado pdata->leds.leds[i].name); 41556a1740cSRicardo Ribalda Delgado if (pdata->leds.leds[i].default_trigger) 41656a1740cSRicardo Ribalda Delgado pca963x[i].led_cdev.default_trigger = 41756a1740cSRicardo Ribalda Delgado pdata->leds.leds[i].default_trigger; 41856a1740cSRicardo Ribalda Delgado } 41956a1740cSRicardo Ribalda Delgado if (!pdata || i >= pdata->leds.num_leds || 42056a1740cSRicardo Ribalda Delgado !pdata->leds.leds[i].name) 42156a1740cSRicardo Ribalda Delgado snprintf(pca963x[i].name, sizeof(pca963x[i].name), 42256a1740cSRicardo Ribalda Delgado "pca963x:%d:%.2x:%d", client->adapter->nr, 42356a1740cSRicardo Ribalda Delgado client->addr, i); 42456a1740cSRicardo Ribalda Delgado 42556a1740cSRicardo Ribalda Delgado pca963x[i].led_cdev.name = pca963x[i].name; 4265029a2e3SAndrew Lunn pca963x[i].led_cdev.brightness_set_blocking = pca963x_led_set; 42756a1740cSRicardo Ribalda Delgado 42856a1740cSRicardo Ribalda Delgado if (pdata && pdata->blink_type == PCA963X_HW_BLINK) 42956a1740cSRicardo Ribalda Delgado pca963x[i].led_cdev.blink_set = pca963x_blink_set; 43056a1740cSRicardo Ribalda Delgado 43156a1740cSRicardo Ribalda Delgado err = led_classdev_register(&client->dev, &pca963x[i].led_cdev); 43256a1740cSRicardo Ribalda Delgado if (err < 0) 43356a1740cSRicardo Ribalda Delgado goto exit; 43456a1740cSRicardo Ribalda Delgado } 43556a1740cSRicardo Ribalda Delgado 436a8c170b0SMatt Ranostay /* Disable LED all-call address, and power down initially */ 437a8c170b0SMatt Ranostay i2c_smbus_write_byte_data(client, PCA963X_MODE1, BIT(4)); 43856a1740cSRicardo Ribalda Delgado 4390c62f42dSPeter Meerwald if (pdata) { 440bb29b9ccSAnders Darander u8 mode2 = i2c_smbus_read_byte_data(pca963x->chip->client, 441bb29b9ccSAnders Darander PCA963X_MODE2); 44256a1740cSRicardo Ribalda Delgado /* Configure output: open-drain or totem pole (push-pull) */ 4430c62f42dSPeter Meerwald if (pdata->outdrv == PCA963X_OPEN_DRAIN) 444bb29b9ccSAnders Darander mode2 |= 0x01; 4450c62f42dSPeter Meerwald else 446bb29b9ccSAnders Darander mode2 |= 0x05; 447bb29b9ccSAnders Darander /* Configure direction: normal or inverted */ 448bb29b9ccSAnders Darander if (pdata->dir == PCA963X_INVERTED) 449bb29b9ccSAnders Darander mode2 |= 0x10; 450bb29b9ccSAnders Darander i2c_smbus_write_byte_data(pca963x->chip->client, PCA963X_MODE2, 451bb29b9ccSAnders Darander mode2); 4520c62f42dSPeter Meerwald } 45356a1740cSRicardo Ribalda Delgado 45456a1740cSRicardo Ribalda Delgado return 0; 45556a1740cSRicardo Ribalda Delgado 45656a1740cSRicardo Ribalda Delgado exit: 4575029a2e3SAndrew Lunn while (i--) 45856a1740cSRicardo Ribalda Delgado led_classdev_unregister(&pca963x[i].led_cdev); 45956a1740cSRicardo Ribalda Delgado 46056a1740cSRicardo Ribalda Delgado return err; 46156a1740cSRicardo Ribalda Delgado } 46256a1740cSRicardo Ribalda Delgado 46356a1740cSRicardo Ribalda Delgado static int pca963x_remove(struct i2c_client *client) 46456a1740cSRicardo Ribalda Delgado { 46556a1740cSRicardo Ribalda Delgado struct pca963x *pca963x = i2c_get_clientdata(client); 46656a1740cSRicardo Ribalda Delgado int i; 46756a1740cSRicardo Ribalda Delgado 4685029a2e3SAndrew Lunn for (i = 0; i < pca963x->chipdef->n_leds; i++) 46956a1740cSRicardo Ribalda Delgado led_classdev_unregister(&pca963x->leds[i].led_cdev); 47056a1740cSRicardo Ribalda Delgado 47156a1740cSRicardo Ribalda Delgado return 0; 47256a1740cSRicardo Ribalda Delgado } 47356a1740cSRicardo Ribalda Delgado 47456a1740cSRicardo Ribalda Delgado static struct i2c_driver pca963x_driver = { 47556a1740cSRicardo Ribalda Delgado .driver = { 47656a1740cSRicardo Ribalda Delgado .name = "leds-pca963x", 4770b6034d8SAndy Shevchenko .of_match_table = of_pca963x_match, 47856a1740cSRicardo Ribalda Delgado }, 47956a1740cSRicardo Ribalda Delgado .probe = pca963x_probe, 48056a1740cSRicardo Ribalda Delgado .remove = pca963x_remove, 48156a1740cSRicardo Ribalda Delgado .id_table = pca963x_id, 48256a1740cSRicardo Ribalda Delgado }; 48356a1740cSRicardo Ribalda Delgado 48456a1740cSRicardo Ribalda Delgado module_i2c_driver(pca963x_driver); 48556a1740cSRicardo Ribalda Delgado 48656a1740cSRicardo Ribalda Delgado MODULE_AUTHOR("Peter Meerwald <p.meerwald@bct-electronic.com>"); 48756a1740cSRicardo Ribalda Delgado MODULE_DESCRIPTION("PCA963X LED driver"); 48856a1740cSRicardo Ribalda Delgado MODULE_LICENSE("GPL v2"); 489