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) 1556a1740cSRicardo Ribalda Delgado * LED driver for the PCA9634 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> 3556a1740cSRicardo Ribalda Delgado #include <linux/workqueue.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, 5556a1740cSRicardo Ribalda Delgado }; 5656a1740cSRicardo Ribalda Delgado 5756a1740cSRicardo Ribalda Delgado struct pca963x_chipdef { 5856a1740cSRicardo Ribalda Delgado u8 grppwm; 5956a1740cSRicardo Ribalda Delgado u8 grpfreq; 6056a1740cSRicardo Ribalda Delgado u8 ledout_base; 6156a1740cSRicardo Ribalda Delgado int n_leds; 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 }, 7756a1740cSRicardo Ribalda Delgado }; 7856a1740cSRicardo Ribalda Delgado 7956a1740cSRicardo Ribalda Delgado /* Total blink period in milliseconds */ 8056a1740cSRicardo Ribalda Delgado #define PCA963X_BLINK_PERIOD_MIN 42 8156a1740cSRicardo Ribalda Delgado #define PCA963X_BLINK_PERIOD_MAX 10667 8256a1740cSRicardo Ribalda Delgado 8356a1740cSRicardo Ribalda Delgado static const struct i2c_device_id pca963x_id[] = { 8456a1740cSRicardo Ribalda Delgado { "pca9632", pca9633 }, 8556a1740cSRicardo Ribalda Delgado { "pca9633", pca9633 }, 8656a1740cSRicardo Ribalda Delgado { "pca9634", pca9634 }, 8756a1740cSRicardo Ribalda Delgado { } 8856a1740cSRicardo Ribalda Delgado }; 8956a1740cSRicardo Ribalda Delgado MODULE_DEVICE_TABLE(i2c, pca963x_id); 9056a1740cSRicardo Ribalda Delgado 9156a1740cSRicardo Ribalda Delgado enum pca963x_cmd { 9256a1740cSRicardo Ribalda Delgado BRIGHTNESS_SET, 9356a1740cSRicardo Ribalda Delgado BLINK_SET, 9456a1740cSRicardo Ribalda Delgado }; 9556a1740cSRicardo Ribalda Delgado 9656a1740cSRicardo Ribalda Delgado struct pca963x_led; 9756a1740cSRicardo Ribalda Delgado 9856a1740cSRicardo Ribalda Delgado struct pca963x { 9956a1740cSRicardo Ribalda Delgado struct pca963x_chipdef *chipdef; 10056a1740cSRicardo Ribalda Delgado struct mutex mutex; 10156a1740cSRicardo Ribalda Delgado struct i2c_client *client; 10256a1740cSRicardo Ribalda Delgado struct pca963x_led *leds; 10356a1740cSRicardo Ribalda Delgado }; 10456a1740cSRicardo Ribalda Delgado 10556a1740cSRicardo Ribalda Delgado struct pca963x_led { 10656a1740cSRicardo Ribalda Delgado struct pca963x *chip; 10756a1740cSRicardo Ribalda Delgado struct work_struct work; 10856a1740cSRicardo Ribalda Delgado enum led_brightness brightness; 10956a1740cSRicardo Ribalda Delgado struct led_classdev led_cdev; 11056a1740cSRicardo Ribalda Delgado int led_num; /* 0 .. 7 potentially */ 11156a1740cSRicardo Ribalda Delgado enum pca963x_cmd cmd; 11256a1740cSRicardo Ribalda Delgado char name[32]; 11356a1740cSRicardo Ribalda Delgado u8 gdc; 11456a1740cSRicardo Ribalda Delgado u8 gfrq; 11556a1740cSRicardo Ribalda Delgado }; 11656a1740cSRicardo Ribalda Delgado 11756a1740cSRicardo Ribalda Delgado static void pca963x_brightness_work(struct pca963x_led *pca963x) 11856a1740cSRicardo Ribalda Delgado { 11956a1740cSRicardo Ribalda Delgado u8 ledout_addr = pca963x->chip->chipdef->ledout_base 12056a1740cSRicardo Ribalda Delgado + (pca963x->led_num / 4); 12156a1740cSRicardo Ribalda Delgado u8 ledout; 12256a1740cSRicardo Ribalda Delgado int shift = 2 * (pca963x->led_num % 4); 12356a1740cSRicardo Ribalda Delgado u8 mask = 0x3 << shift; 12456a1740cSRicardo Ribalda Delgado 12556a1740cSRicardo Ribalda Delgado mutex_lock(&pca963x->chip->mutex); 12656a1740cSRicardo Ribalda Delgado ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr); 12756a1740cSRicardo Ribalda Delgado switch (pca963x->brightness) { 12856a1740cSRicardo Ribalda Delgado case LED_FULL: 12956a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr, 13056a1740cSRicardo Ribalda Delgado (ledout & ~mask) | (PCA963X_LED_ON << shift)); 13156a1740cSRicardo Ribalda Delgado break; 13256a1740cSRicardo Ribalda Delgado case LED_OFF: 13356a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr, 13456a1740cSRicardo Ribalda Delgado ledout & ~mask); 13556a1740cSRicardo Ribalda Delgado break; 13656a1740cSRicardo Ribalda Delgado default: 13756a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, 13856a1740cSRicardo Ribalda Delgado PCA963X_PWM_BASE + pca963x->led_num, 13956a1740cSRicardo Ribalda Delgado pca963x->brightness); 14056a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr, 14156a1740cSRicardo Ribalda Delgado (ledout & ~mask) | (PCA963X_LED_PWM << shift)); 14256a1740cSRicardo Ribalda Delgado break; 14356a1740cSRicardo Ribalda Delgado } 14456a1740cSRicardo Ribalda Delgado mutex_unlock(&pca963x->chip->mutex); 14556a1740cSRicardo Ribalda Delgado } 14656a1740cSRicardo Ribalda Delgado 14756a1740cSRicardo Ribalda Delgado static void pca963x_blink_work(struct pca963x_led *pca963x) 14856a1740cSRicardo Ribalda Delgado { 14956a1740cSRicardo Ribalda Delgado u8 ledout_addr = pca963x->chip->chipdef->ledout_base + 15056a1740cSRicardo Ribalda Delgado (pca963x->led_num / 4); 15156a1740cSRicardo Ribalda Delgado u8 ledout; 15256a1740cSRicardo Ribalda Delgado u8 mode2 = i2c_smbus_read_byte_data(pca963x->chip->client, 15356a1740cSRicardo Ribalda Delgado PCA963X_MODE2); 15456a1740cSRicardo Ribalda Delgado int shift = 2 * (pca963x->led_num % 4); 15556a1740cSRicardo Ribalda Delgado u8 mask = 0x3 << shift; 15656a1740cSRicardo Ribalda Delgado 15756a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, 15856a1740cSRicardo Ribalda Delgado pca963x->chip->chipdef->grppwm, pca963x->gdc); 15956a1740cSRicardo Ribalda Delgado 16056a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, 16156a1740cSRicardo Ribalda Delgado pca963x->chip->chipdef->grpfreq, pca963x->gfrq); 16256a1740cSRicardo Ribalda Delgado 16356a1740cSRicardo Ribalda Delgado if (!(mode2 & PCA963X_MODE2_DMBLNK)) 16456a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, PCA963X_MODE2, 16556a1740cSRicardo Ribalda Delgado mode2 | PCA963X_MODE2_DMBLNK); 16656a1740cSRicardo Ribalda Delgado 16756a1740cSRicardo Ribalda Delgado mutex_lock(&pca963x->chip->mutex); 16856a1740cSRicardo Ribalda Delgado ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr); 16956a1740cSRicardo Ribalda Delgado if ((ledout & mask) != (PCA963X_LED_GRP_PWM << shift)) 17056a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr, 17156a1740cSRicardo Ribalda Delgado (ledout & ~mask) | (PCA963X_LED_GRP_PWM << shift)); 17256a1740cSRicardo Ribalda Delgado mutex_unlock(&pca963x->chip->mutex); 17356a1740cSRicardo Ribalda Delgado } 17456a1740cSRicardo Ribalda Delgado 17556a1740cSRicardo Ribalda Delgado static void pca963x_work(struct work_struct *work) 17656a1740cSRicardo Ribalda Delgado { 17756a1740cSRicardo Ribalda Delgado struct pca963x_led *pca963x = container_of(work, 17856a1740cSRicardo Ribalda Delgado struct pca963x_led, work); 17956a1740cSRicardo Ribalda Delgado 18056a1740cSRicardo Ribalda Delgado switch (pca963x->cmd) { 18156a1740cSRicardo Ribalda Delgado case BRIGHTNESS_SET: 18256a1740cSRicardo Ribalda Delgado pca963x_brightness_work(pca963x); 18356a1740cSRicardo Ribalda Delgado break; 18456a1740cSRicardo Ribalda Delgado case BLINK_SET: 18556a1740cSRicardo Ribalda Delgado pca963x_blink_work(pca963x); 18656a1740cSRicardo Ribalda Delgado break; 18756a1740cSRicardo Ribalda Delgado } 18856a1740cSRicardo Ribalda Delgado } 18956a1740cSRicardo Ribalda Delgado 19056a1740cSRicardo Ribalda Delgado static void pca963x_led_set(struct led_classdev *led_cdev, 19156a1740cSRicardo Ribalda Delgado enum led_brightness value) 19256a1740cSRicardo Ribalda Delgado { 19356a1740cSRicardo Ribalda Delgado struct pca963x_led *pca963x; 19456a1740cSRicardo Ribalda Delgado 19556a1740cSRicardo Ribalda Delgado pca963x = container_of(led_cdev, struct pca963x_led, led_cdev); 19656a1740cSRicardo Ribalda Delgado 19756a1740cSRicardo Ribalda Delgado pca963x->cmd = BRIGHTNESS_SET; 19856a1740cSRicardo Ribalda Delgado pca963x->brightness = value; 19956a1740cSRicardo Ribalda Delgado 20056a1740cSRicardo Ribalda Delgado /* 20156a1740cSRicardo Ribalda Delgado * Must use workqueue for the actual I/O since I2C operations 20256a1740cSRicardo Ribalda Delgado * can sleep. 20356a1740cSRicardo Ribalda Delgado */ 20456a1740cSRicardo Ribalda Delgado schedule_work(&pca963x->work); 20556a1740cSRicardo Ribalda Delgado } 20656a1740cSRicardo Ribalda Delgado 20756a1740cSRicardo Ribalda Delgado static int pca963x_blink_set(struct led_classdev *led_cdev, 20856a1740cSRicardo Ribalda Delgado unsigned long *delay_on, unsigned long *delay_off) 20956a1740cSRicardo Ribalda Delgado { 21056a1740cSRicardo Ribalda Delgado struct pca963x_led *pca963x; 21156a1740cSRicardo Ribalda Delgado unsigned long time_on, time_off, period; 21256a1740cSRicardo Ribalda Delgado u8 gdc, gfrq; 21356a1740cSRicardo Ribalda Delgado 21456a1740cSRicardo Ribalda Delgado pca963x = container_of(led_cdev, struct pca963x_led, led_cdev); 21556a1740cSRicardo Ribalda Delgado 21656a1740cSRicardo Ribalda Delgado time_on = *delay_on; 21756a1740cSRicardo Ribalda Delgado time_off = *delay_off; 21856a1740cSRicardo Ribalda Delgado 21956a1740cSRicardo Ribalda Delgado /* If both zero, pick reasonable defaults of 500ms each */ 22056a1740cSRicardo Ribalda Delgado if (!time_on && !time_off) { 22156a1740cSRicardo Ribalda Delgado time_on = 500; 22256a1740cSRicardo Ribalda Delgado time_off = 500; 22356a1740cSRicardo Ribalda Delgado } 22456a1740cSRicardo Ribalda Delgado 22556a1740cSRicardo Ribalda Delgado period = time_on + time_off; 22656a1740cSRicardo Ribalda Delgado 22756a1740cSRicardo Ribalda Delgado /* If period not supported by hardware, default to someting sane. */ 22856a1740cSRicardo Ribalda Delgado if ((period < PCA963X_BLINK_PERIOD_MIN) || 22956a1740cSRicardo Ribalda Delgado (period > PCA963X_BLINK_PERIOD_MAX)) { 23056a1740cSRicardo Ribalda Delgado time_on = 500; 23156a1740cSRicardo Ribalda Delgado time_off = 500; 23256a1740cSRicardo Ribalda Delgado period = time_on + time_off; 23356a1740cSRicardo Ribalda Delgado } 23456a1740cSRicardo Ribalda Delgado 23556a1740cSRicardo Ribalda Delgado /* 23656a1740cSRicardo Ribalda Delgado * From manual: duty cycle = (GDC / 256) -> 23756a1740cSRicardo Ribalda Delgado * (time_on / period) = (GDC / 256) -> 23856a1740cSRicardo Ribalda Delgado * GDC = ((time_on * 256) / period) 23956a1740cSRicardo Ribalda Delgado */ 24056a1740cSRicardo Ribalda Delgado gdc = (time_on * 256) / period; 24156a1740cSRicardo Ribalda Delgado 24256a1740cSRicardo Ribalda Delgado /* 24356a1740cSRicardo Ribalda Delgado * From manual: period = ((GFRQ + 1) / 24) in seconds. 24456a1740cSRicardo Ribalda Delgado * So, period (in ms) = (((GFRQ + 1) / 24) * 1000) -> 24556a1740cSRicardo Ribalda Delgado * GFRQ = ((period * 24 / 1000) - 1) 24656a1740cSRicardo Ribalda Delgado */ 24756a1740cSRicardo Ribalda Delgado gfrq = (period * 24 / 1000) - 1; 24856a1740cSRicardo Ribalda Delgado 24956a1740cSRicardo Ribalda Delgado pca963x->cmd = BLINK_SET; 25056a1740cSRicardo Ribalda Delgado pca963x->gdc = gdc; 25156a1740cSRicardo Ribalda Delgado pca963x->gfrq = gfrq; 25256a1740cSRicardo Ribalda Delgado 25356a1740cSRicardo Ribalda Delgado /* 25456a1740cSRicardo Ribalda Delgado * Must use workqueue for the actual I/O since I2C operations 25556a1740cSRicardo Ribalda Delgado * can sleep. 25656a1740cSRicardo Ribalda Delgado */ 25756a1740cSRicardo Ribalda Delgado schedule_work(&pca963x->work); 25856a1740cSRicardo Ribalda Delgado 25956a1740cSRicardo Ribalda Delgado *delay_on = time_on; 26056a1740cSRicardo Ribalda Delgado *delay_off = time_off; 26156a1740cSRicardo Ribalda Delgado 26256a1740cSRicardo Ribalda Delgado return 0; 26356a1740cSRicardo Ribalda Delgado } 26456a1740cSRicardo Ribalda Delgado 26556a1740cSRicardo Ribalda Delgado #if IS_ENABLED(CONFIG_OF) 26656a1740cSRicardo Ribalda Delgado static struct pca963x_platform_data * 26756a1740cSRicardo Ribalda Delgado pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip) 26856a1740cSRicardo Ribalda Delgado { 26956a1740cSRicardo Ribalda Delgado struct device_node *np = client->dev.of_node, *child; 27056a1740cSRicardo Ribalda Delgado struct pca963x_platform_data *pdata; 27156a1740cSRicardo Ribalda Delgado struct led_info *pca963x_leds; 27256a1740cSRicardo Ribalda Delgado int count; 27356a1740cSRicardo Ribalda Delgado 27456a1740cSRicardo Ribalda Delgado count = of_get_child_count(np); 27556a1740cSRicardo Ribalda Delgado if (!count || count > chip->n_leds) 27656a1740cSRicardo Ribalda Delgado return ERR_PTR(-ENODEV); 27756a1740cSRicardo Ribalda Delgado 27856a1740cSRicardo Ribalda Delgado pca963x_leds = devm_kzalloc(&client->dev, 27956a1740cSRicardo Ribalda Delgado sizeof(struct led_info) * chip->n_leds, GFP_KERNEL); 28056a1740cSRicardo Ribalda Delgado if (!pca963x_leds) 28156a1740cSRicardo Ribalda Delgado return ERR_PTR(-ENOMEM); 28256a1740cSRicardo Ribalda Delgado 28356a1740cSRicardo Ribalda Delgado for_each_child_of_node(np, child) { 28456a1740cSRicardo Ribalda Delgado struct led_info led; 28556a1740cSRicardo Ribalda Delgado u32 reg; 28656a1740cSRicardo Ribalda Delgado int res; 28756a1740cSRicardo Ribalda Delgado 2888a6acd64SRicardo Ribalda Delgado res = of_property_read_u32(child, "reg", ®); 2898a6acd64SRicardo Ribalda Delgado if ((res != 0) || (reg >= chip->n_leds)) 2908a6acd64SRicardo Ribalda Delgado continue; 29156a1740cSRicardo Ribalda Delgado led.name = 29256a1740cSRicardo Ribalda Delgado of_get_property(child, "label", NULL) ? : child->name; 29356a1740cSRicardo Ribalda Delgado led.default_trigger = 29456a1740cSRicardo Ribalda Delgado of_get_property(child, "linux,default-trigger", NULL); 29556a1740cSRicardo Ribalda Delgado pca963x_leds[reg] = led; 29656a1740cSRicardo Ribalda Delgado } 29756a1740cSRicardo Ribalda Delgado pdata = devm_kzalloc(&client->dev, 29856a1740cSRicardo Ribalda Delgado sizeof(struct pca963x_platform_data), GFP_KERNEL); 29956a1740cSRicardo Ribalda Delgado if (!pdata) 30056a1740cSRicardo Ribalda Delgado return ERR_PTR(-ENOMEM); 30156a1740cSRicardo Ribalda Delgado 30256a1740cSRicardo Ribalda Delgado pdata->leds.leds = pca963x_leds; 3038a6acd64SRicardo Ribalda Delgado pdata->leds.num_leds = chip->n_leds; 30456a1740cSRicardo Ribalda Delgado 30556a1740cSRicardo Ribalda Delgado /* default to open-drain unless totem pole (push-pull) is specified */ 30656a1740cSRicardo Ribalda Delgado if (of_property_read_bool(np, "nxp,totem-pole")) 30756a1740cSRicardo Ribalda Delgado pdata->outdrv = PCA963X_TOTEM_POLE; 30856a1740cSRicardo Ribalda Delgado else 30956a1740cSRicardo Ribalda Delgado pdata->outdrv = PCA963X_OPEN_DRAIN; 31056a1740cSRicardo Ribalda Delgado 31156a1740cSRicardo Ribalda Delgado /* default to software blinking unless hardware blinking is specified */ 31256a1740cSRicardo Ribalda Delgado if (of_property_read_bool(np, "nxp,hw-blink")) 31356a1740cSRicardo Ribalda Delgado pdata->blink_type = PCA963X_HW_BLINK; 31456a1740cSRicardo Ribalda Delgado else 31556a1740cSRicardo Ribalda Delgado pdata->blink_type = PCA963X_SW_BLINK; 31656a1740cSRicardo Ribalda Delgado 31756a1740cSRicardo Ribalda Delgado return pdata; 31856a1740cSRicardo Ribalda Delgado } 31956a1740cSRicardo Ribalda Delgado 32056a1740cSRicardo Ribalda Delgado static const struct of_device_id of_pca963x_match[] = { 32156a1740cSRicardo Ribalda Delgado { .compatible = "nxp,pca9632", }, 32256a1740cSRicardo Ribalda Delgado { .compatible = "nxp,pca9633", }, 32356a1740cSRicardo Ribalda Delgado { .compatible = "nxp,pca9634", }, 32456a1740cSRicardo Ribalda Delgado {}, 32556a1740cSRicardo Ribalda Delgado }; 32656a1740cSRicardo Ribalda Delgado #else 32756a1740cSRicardo Ribalda Delgado static struct pca963x_platform_data * 32856a1740cSRicardo Ribalda Delgado pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip) 32956a1740cSRicardo Ribalda Delgado { 33056a1740cSRicardo Ribalda Delgado return ERR_PTR(-ENODEV); 33156a1740cSRicardo Ribalda Delgado } 33256a1740cSRicardo Ribalda Delgado #endif 33356a1740cSRicardo Ribalda Delgado 33456a1740cSRicardo Ribalda Delgado static int pca963x_probe(struct i2c_client *client, 33556a1740cSRicardo Ribalda Delgado const struct i2c_device_id *id) 33656a1740cSRicardo Ribalda Delgado { 33756a1740cSRicardo Ribalda Delgado struct pca963x *pca963x_chip; 33856a1740cSRicardo Ribalda Delgado struct pca963x_led *pca963x; 33956a1740cSRicardo Ribalda Delgado struct pca963x_platform_data *pdata; 34056a1740cSRicardo Ribalda Delgado struct pca963x_chipdef *chip; 34156a1740cSRicardo Ribalda Delgado int i, err; 34256a1740cSRicardo Ribalda Delgado 34356a1740cSRicardo Ribalda Delgado chip = &pca963x_chipdefs[id->driver_data]; 34456a1740cSRicardo Ribalda Delgado pdata = dev_get_platdata(&client->dev); 34556a1740cSRicardo Ribalda Delgado 34656a1740cSRicardo Ribalda Delgado if (!pdata) { 34756a1740cSRicardo Ribalda Delgado pdata = pca963x_dt_init(client, chip); 34856a1740cSRicardo Ribalda Delgado if (IS_ERR(pdata)) { 34956a1740cSRicardo Ribalda Delgado dev_warn(&client->dev, "could not parse configuration\n"); 35056a1740cSRicardo Ribalda Delgado pdata = NULL; 35156a1740cSRicardo Ribalda Delgado } 35256a1740cSRicardo Ribalda Delgado } 35356a1740cSRicardo Ribalda Delgado 35456a1740cSRicardo Ribalda Delgado if (pdata && (pdata->leds.num_leds < 1 || 35556a1740cSRicardo Ribalda Delgado pdata->leds.num_leds > chip->n_leds)) { 35656a1740cSRicardo Ribalda Delgado dev_err(&client->dev, "board info must claim 1-%d LEDs", 35756a1740cSRicardo Ribalda Delgado chip->n_leds); 35856a1740cSRicardo Ribalda Delgado return -EINVAL; 35956a1740cSRicardo Ribalda Delgado } 36056a1740cSRicardo Ribalda Delgado 36156a1740cSRicardo Ribalda Delgado pca963x_chip = devm_kzalloc(&client->dev, sizeof(*pca963x_chip), 36256a1740cSRicardo Ribalda Delgado GFP_KERNEL); 36356a1740cSRicardo Ribalda Delgado if (!pca963x_chip) 36456a1740cSRicardo Ribalda Delgado return -ENOMEM; 36556a1740cSRicardo Ribalda Delgado pca963x = devm_kzalloc(&client->dev, chip->n_leds * sizeof(*pca963x), 36656a1740cSRicardo Ribalda Delgado GFP_KERNEL); 36756a1740cSRicardo Ribalda Delgado if (!pca963x) 36856a1740cSRicardo Ribalda Delgado return -ENOMEM; 36956a1740cSRicardo Ribalda Delgado 37056a1740cSRicardo Ribalda Delgado i2c_set_clientdata(client, pca963x_chip); 37156a1740cSRicardo Ribalda Delgado 37256a1740cSRicardo Ribalda Delgado mutex_init(&pca963x_chip->mutex); 37356a1740cSRicardo Ribalda Delgado pca963x_chip->chipdef = chip; 37456a1740cSRicardo Ribalda Delgado pca963x_chip->client = client; 37556a1740cSRicardo Ribalda Delgado pca963x_chip->leds = pca963x; 37656a1740cSRicardo Ribalda Delgado 37756a1740cSRicardo Ribalda Delgado /* Turn off LEDs by default*/ 37856a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(client, chip->ledout_base, 0x00); 37956a1740cSRicardo Ribalda Delgado if (chip->n_leds > 4) 38056a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(client, chip->ledout_base + 1, 0x00); 38156a1740cSRicardo Ribalda Delgado 38256a1740cSRicardo Ribalda Delgado for (i = 0; i < chip->n_leds; i++) { 38356a1740cSRicardo Ribalda Delgado pca963x[i].led_num = i; 38456a1740cSRicardo Ribalda Delgado pca963x[i].chip = pca963x_chip; 38556a1740cSRicardo Ribalda Delgado 38656a1740cSRicardo Ribalda Delgado /* Platform data can specify LED names and default triggers */ 38756a1740cSRicardo Ribalda Delgado if (pdata && i < pdata->leds.num_leds) { 38856a1740cSRicardo Ribalda Delgado if (pdata->leds.leds[i].name) 38956a1740cSRicardo Ribalda Delgado snprintf(pca963x[i].name, 39056a1740cSRicardo Ribalda Delgado sizeof(pca963x[i].name), "pca963x:%s", 39156a1740cSRicardo Ribalda Delgado pdata->leds.leds[i].name); 39256a1740cSRicardo Ribalda Delgado if (pdata->leds.leds[i].default_trigger) 39356a1740cSRicardo Ribalda Delgado pca963x[i].led_cdev.default_trigger = 39456a1740cSRicardo Ribalda Delgado pdata->leds.leds[i].default_trigger; 39556a1740cSRicardo Ribalda Delgado } 39656a1740cSRicardo Ribalda Delgado if (!pdata || i >= pdata->leds.num_leds || 39756a1740cSRicardo Ribalda Delgado !pdata->leds.leds[i].name) 39856a1740cSRicardo Ribalda Delgado snprintf(pca963x[i].name, sizeof(pca963x[i].name), 39956a1740cSRicardo Ribalda Delgado "pca963x:%d:%.2x:%d", client->adapter->nr, 40056a1740cSRicardo Ribalda Delgado client->addr, i); 40156a1740cSRicardo Ribalda Delgado 40256a1740cSRicardo Ribalda Delgado pca963x[i].led_cdev.name = pca963x[i].name; 40356a1740cSRicardo Ribalda Delgado pca963x[i].led_cdev.brightness_set = pca963x_led_set; 40456a1740cSRicardo Ribalda Delgado 40556a1740cSRicardo Ribalda Delgado if (pdata && pdata->blink_type == PCA963X_HW_BLINK) 40656a1740cSRicardo Ribalda Delgado pca963x[i].led_cdev.blink_set = pca963x_blink_set; 40756a1740cSRicardo Ribalda Delgado 40856a1740cSRicardo Ribalda Delgado INIT_WORK(&pca963x[i].work, pca963x_work); 40956a1740cSRicardo Ribalda Delgado 41056a1740cSRicardo Ribalda Delgado err = led_classdev_register(&client->dev, &pca963x[i].led_cdev); 41156a1740cSRicardo Ribalda Delgado if (err < 0) 41256a1740cSRicardo Ribalda Delgado goto exit; 41356a1740cSRicardo Ribalda Delgado } 41456a1740cSRicardo Ribalda Delgado 41556a1740cSRicardo Ribalda Delgado /* Disable LED all-call address and set normal mode */ 41656a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(client, PCA963X_MODE1, 0x00); 41756a1740cSRicardo Ribalda Delgado 41856a1740cSRicardo Ribalda Delgado /* Configure output: open-drain or totem pole (push-pull) */ 41956a1740cSRicardo Ribalda Delgado if (pdata && pdata->outdrv == PCA963X_OPEN_DRAIN) 42056a1740cSRicardo Ribalda Delgado i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01); 42156a1740cSRicardo Ribalda Delgado 42256a1740cSRicardo Ribalda Delgado return 0; 42356a1740cSRicardo Ribalda Delgado 42456a1740cSRicardo Ribalda Delgado exit: 42556a1740cSRicardo Ribalda Delgado while (i--) { 42656a1740cSRicardo Ribalda Delgado led_classdev_unregister(&pca963x[i].led_cdev); 42756a1740cSRicardo Ribalda Delgado cancel_work_sync(&pca963x[i].work); 42856a1740cSRicardo Ribalda Delgado } 42956a1740cSRicardo Ribalda Delgado 43056a1740cSRicardo Ribalda Delgado return err; 43156a1740cSRicardo Ribalda Delgado } 43256a1740cSRicardo Ribalda Delgado 43356a1740cSRicardo Ribalda Delgado static int pca963x_remove(struct i2c_client *client) 43456a1740cSRicardo Ribalda Delgado { 43556a1740cSRicardo Ribalda Delgado struct pca963x *pca963x = i2c_get_clientdata(client); 43656a1740cSRicardo Ribalda Delgado int i; 43756a1740cSRicardo Ribalda Delgado 43856a1740cSRicardo Ribalda Delgado for (i = 0; i < pca963x->chipdef->n_leds; i++) { 43956a1740cSRicardo Ribalda Delgado led_classdev_unregister(&pca963x->leds[i].led_cdev); 44056a1740cSRicardo Ribalda Delgado cancel_work_sync(&pca963x->leds[i].work); 44156a1740cSRicardo Ribalda Delgado } 44256a1740cSRicardo Ribalda Delgado 44356a1740cSRicardo Ribalda Delgado return 0; 44456a1740cSRicardo Ribalda Delgado } 44556a1740cSRicardo Ribalda Delgado 44656a1740cSRicardo Ribalda Delgado static struct i2c_driver pca963x_driver = { 44756a1740cSRicardo Ribalda Delgado .driver = { 44856a1740cSRicardo Ribalda Delgado .name = "leds-pca963x", 44956a1740cSRicardo Ribalda Delgado .owner = THIS_MODULE, 45056a1740cSRicardo Ribalda Delgado .of_match_table = of_match_ptr(of_pca963x_match), 45156a1740cSRicardo Ribalda Delgado }, 45256a1740cSRicardo Ribalda Delgado .probe = pca963x_probe, 45356a1740cSRicardo Ribalda Delgado .remove = pca963x_remove, 45456a1740cSRicardo Ribalda Delgado .id_table = pca963x_id, 45556a1740cSRicardo Ribalda Delgado }; 45656a1740cSRicardo Ribalda Delgado 45756a1740cSRicardo Ribalda Delgado module_i2c_driver(pca963x_driver); 45856a1740cSRicardo Ribalda Delgado 45956a1740cSRicardo Ribalda Delgado MODULE_AUTHOR("Peter Meerwald <p.meerwald@bct-electronic.com>"); 46056a1740cSRicardo Ribalda Delgado MODULE_DESCRIPTION("PCA963X LED driver"); 46156a1740cSRicardo Ribalda Delgado MODULE_LICENSE("GPL v2"); 462