1 /* 2 * TI LP8860 4-Channel LED Driver 3 * 4 * Copyright (C) 2014 Texas Instruments 5 * 6 * Author: Dan Murphy <dmurphy@ti.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 * 12 */ 13 14 #include <linux/i2c.h> 15 #include <linux/init.h> 16 #include <linux/leds.h> 17 #include <linux/regmap.h> 18 #include <linux/regulator/consumer.h> 19 #include <linux/module.h> 20 #include <linux/mutex.h> 21 #include <linux/of.h> 22 #include <linux/of_gpio.h> 23 #include <linux/gpio/consumer.h> 24 #include <linux/slab.h> 25 26 #define LP8860_DISP_CL1_BRT_MSB 0x00 27 #define LP8860_DISP_CL1_BRT_LSB 0x01 28 #define LP8860_DISP_CL1_CURR_MSB 0x02 29 #define LP8860_DISP_CL1_CURR_LSB 0x03 30 #define LP8860_CL2_BRT_MSB 0x04 31 #define LP8860_CL2_BRT_LSB 0x05 32 #define LP8860_CL2_CURRENT 0x06 33 #define LP8860_CL3_BRT_MSB 0x07 34 #define LP8860_CL3_BRT_LSB 0x08 35 #define LP8860_CL3_CURRENT 0x09 36 #define LP8860_CL4_BRT_MSB 0x0a 37 #define LP8860_CL4_BRT_LSB 0x0b 38 #define LP8860_CL4_CURRENT 0x0c 39 #define LP8860_CONFIG 0x0d 40 #define LP8860_STATUS 0x0e 41 #define LP8860_FAULT 0x0f 42 #define LP8860_LED_FAULT 0x10 43 #define LP8860_FAULT_CLEAR 0x11 44 #define LP8860_ID 0x12 45 #define LP8860_TEMP_MSB 0x13 46 #define LP8860_TEMP_LSB 0x14 47 #define LP8860_DISP_LED_CURR_MSB 0x15 48 #define LP8860_DISP_LED_CURR_LSB 0x16 49 #define LP8860_DISP_LED_PWM_MSB 0x17 50 #define LP8860_DISP_LED_PWM_LSB 0x18 51 #define LP8860_EEPROM_CNTRL 0x19 52 #define LP8860_EEPROM_UNLOCK 0x1a 53 54 #define LP8860_EEPROM_REG_0 0x60 55 #define LP8860_EEPROM_REG_1 0x61 56 #define LP8860_EEPROM_REG_2 0x62 57 #define LP8860_EEPROM_REG_3 0x63 58 #define LP8860_EEPROM_REG_4 0x64 59 #define LP8860_EEPROM_REG_5 0x65 60 #define LP8860_EEPROM_REG_6 0x66 61 #define LP8860_EEPROM_REG_7 0x67 62 #define LP8860_EEPROM_REG_8 0x68 63 #define LP8860_EEPROM_REG_9 0x69 64 #define LP8860_EEPROM_REG_10 0x6a 65 #define LP8860_EEPROM_REG_11 0x6b 66 #define LP8860_EEPROM_REG_12 0x6c 67 #define LP8860_EEPROM_REG_13 0x6d 68 #define LP8860_EEPROM_REG_14 0x6e 69 #define LP8860_EEPROM_REG_15 0x6f 70 #define LP8860_EEPROM_REG_16 0x70 71 #define LP8860_EEPROM_REG_17 0x71 72 #define LP8860_EEPROM_REG_18 0x72 73 #define LP8860_EEPROM_REG_19 0x73 74 #define LP8860_EEPROM_REG_20 0x74 75 #define LP8860_EEPROM_REG_21 0x75 76 #define LP8860_EEPROM_REG_22 0x76 77 #define LP8860_EEPROM_REG_23 0x77 78 #define LP8860_EEPROM_REG_24 0x78 79 80 #define LP8860_LOCK_EEPROM 0x00 81 #define LP8860_UNLOCK_EEPROM 0x01 82 #define LP8860_PROGRAM_EEPROM 0x02 83 #define LP8860_EEPROM_CODE_1 0x08 84 #define LP8860_EEPROM_CODE_2 0xba 85 #define LP8860_EEPROM_CODE_3 0xef 86 87 #define LP8860_CLEAR_FAULTS 0x01 88 89 #define LP8860_DISP_LED_NAME "display_cluster" 90 91 /** 92 * struct lp8860_led - 93 * @lock - Lock for reading/writing the device 94 * @work - Work item used to off load the brightness register writes 95 * @client - Pointer to the I2C client 96 * @led_dev - led class device pointer 97 * @regmap - Devices register map 98 * @eeprom_regmap - EEPROM register map 99 * @enable_gpio - VDDIO/EN gpio to enable communication interface 100 * @regulator - LED supply regulator pointer 101 * @brightness - Current brightness value requested 102 * @label - LED label 103 **/ 104 struct lp8860_led { 105 struct mutex lock; 106 struct work_struct work; 107 struct i2c_client *client; 108 struct led_classdev led_dev; 109 struct regmap *regmap; 110 struct regmap *eeprom_regmap; 111 struct gpio_desc *enable_gpio; 112 struct regulator *regulator; 113 enum led_brightness brightness; 114 const char *label; 115 }; 116 117 struct lp8860_eeprom_reg { 118 uint8_t reg; 119 uint8_t value; 120 }; 121 122 static struct lp8860_eeprom_reg lp8860_eeprom_disp_regs[] = { 123 { LP8860_EEPROM_REG_0, 0xed }, 124 { LP8860_EEPROM_REG_1, 0xdf }, 125 { LP8860_EEPROM_REG_2, 0xdc }, 126 { LP8860_EEPROM_REG_3, 0xf0 }, 127 { LP8860_EEPROM_REG_4, 0xdf }, 128 { LP8860_EEPROM_REG_5, 0xe5 }, 129 { LP8860_EEPROM_REG_6, 0xf2 }, 130 { LP8860_EEPROM_REG_7, 0x77 }, 131 { LP8860_EEPROM_REG_8, 0x77 }, 132 { LP8860_EEPROM_REG_9, 0x71 }, 133 { LP8860_EEPROM_REG_10, 0x3f }, 134 { LP8860_EEPROM_REG_11, 0xb7 }, 135 { LP8860_EEPROM_REG_12, 0x17 }, 136 { LP8860_EEPROM_REG_13, 0xef }, 137 { LP8860_EEPROM_REG_14, 0xb0 }, 138 { LP8860_EEPROM_REG_15, 0x87 }, 139 { LP8860_EEPROM_REG_16, 0xce }, 140 { LP8860_EEPROM_REG_17, 0x72 }, 141 { LP8860_EEPROM_REG_18, 0xe5 }, 142 { LP8860_EEPROM_REG_19, 0xdf }, 143 { LP8860_EEPROM_REG_20, 0x35 }, 144 { LP8860_EEPROM_REG_21, 0x06 }, 145 { LP8860_EEPROM_REG_22, 0xdc }, 146 { LP8860_EEPROM_REG_23, 0x88 }, 147 { LP8860_EEPROM_REG_24, 0x3E }, 148 }; 149 150 static int lp8860_unlock_eeprom(struct lp8860_led *led, int lock) 151 { 152 int ret; 153 154 mutex_lock(&led->lock); 155 156 if (lock == LP8860_UNLOCK_EEPROM) { 157 ret = regmap_write(led->regmap, 158 LP8860_EEPROM_UNLOCK, 159 LP8860_EEPROM_CODE_1); 160 if (ret) { 161 dev_err(&led->client->dev, "EEPROM Unlock failed\n"); 162 goto out; 163 } 164 165 ret = regmap_write(led->regmap, 166 LP8860_EEPROM_UNLOCK, 167 LP8860_EEPROM_CODE_2); 168 if (ret) { 169 dev_err(&led->client->dev, "EEPROM Unlock failed\n"); 170 goto out; 171 } 172 ret = regmap_write(led->regmap, 173 LP8860_EEPROM_UNLOCK, 174 LP8860_EEPROM_CODE_3); 175 if (ret) { 176 dev_err(&led->client->dev, "EEPROM Unlock failed\n"); 177 goto out; 178 } 179 } else { 180 ret = regmap_write(led->regmap, 181 LP8860_EEPROM_UNLOCK, 182 LP8860_LOCK_EEPROM); 183 } 184 185 out: 186 mutex_unlock(&led->lock); 187 return ret; 188 } 189 190 static int lp8860_fault_check(struct lp8860_led *led) 191 { 192 int ret, fault; 193 unsigned int read_buf; 194 195 ret = regmap_read(led->regmap, LP8860_LED_FAULT, &read_buf); 196 if (ret) 197 goto out; 198 199 fault = read_buf; 200 201 ret = regmap_read(led->regmap, LP8860_FAULT, &read_buf); 202 if (ret) 203 goto out; 204 205 fault |= read_buf; 206 207 /* Attempt to clear any faults */ 208 if (fault) 209 ret = regmap_write(led->regmap, LP8860_FAULT_CLEAR, 210 LP8860_CLEAR_FAULTS); 211 out: 212 return ret; 213 } 214 215 static void lp8860_led_brightness_work(struct work_struct *work) 216 { 217 struct lp8860_led *led = container_of(work, struct lp8860_led, work); 218 int ret; 219 int disp_brightness = led->brightness * 255; 220 221 mutex_lock(&led->lock); 222 223 ret = lp8860_fault_check(led); 224 if (ret) { 225 dev_err(&led->client->dev, "Cannot read/clear faults\n"); 226 goto out; 227 } 228 229 ret = regmap_write(led->regmap, LP8860_DISP_CL1_BRT_MSB, 230 (disp_brightness & 0xff00) >> 8); 231 if (ret) { 232 dev_err(&led->client->dev, "Cannot write CL1 MSB\n"); 233 goto out; 234 } 235 236 ret = regmap_write(led->regmap, LP8860_DISP_CL1_BRT_LSB, 237 disp_brightness & 0xff); 238 if (ret) { 239 dev_err(&led->client->dev, "Cannot write CL1 LSB\n"); 240 goto out; 241 } 242 out: 243 mutex_unlock(&led->lock); 244 } 245 246 static void lp8860_brightness_set(struct led_classdev *led_cdev, 247 enum led_brightness brt_val) 248 { 249 struct lp8860_led *led = 250 container_of(led_cdev, struct lp8860_led, led_dev); 251 252 led->brightness = brt_val; 253 schedule_work(&led->work); 254 } 255 256 static int lp8860_init(struct lp8860_led *led) 257 { 258 unsigned int read_buf; 259 int ret, i, reg_count; 260 261 if (led->enable_gpio) 262 gpiod_direction_output(led->enable_gpio, 1); 263 264 ret = lp8860_fault_check(led); 265 if (ret) 266 goto out; 267 268 ret = regmap_read(led->regmap, LP8860_STATUS, &read_buf); 269 if (ret) 270 goto out; 271 272 ret = lp8860_unlock_eeprom(led, LP8860_UNLOCK_EEPROM); 273 if (ret) { 274 dev_err(&led->client->dev, "Failed unlocking EEPROM\n"); 275 goto out; 276 } 277 278 reg_count = ARRAY_SIZE(lp8860_eeprom_disp_regs) / sizeof(lp8860_eeprom_disp_regs[0]); 279 for (i = 0; i < reg_count; i++) { 280 ret = regmap_write(led->eeprom_regmap, 281 lp8860_eeprom_disp_regs[i].reg, 282 lp8860_eeprom_disp_regs[i].value); 283 if (ret) { 284 dev_err(&led->client->dev, "Failed writing EEPROM\n"); 285 goto out; 286 } 287 } 288 289 ret = lp8860_unlock_eeprom(led, LP8860_LOCK_EEPROM); 290 if (ret) 291 goto out; 292 293 ret = regmap_write(led->regmap, 294 LP8860_EEPROM_CNTRL, 295 LP8860_PROGRAM_EEPROM); 296 if (ret) 297 dev_err(&led->client->dev, "Failed programming EEPROM\n"); 298 out: 299 if (ret) 300 if (led->enable_gpio) 301 gpiod_direction_output(led->enable_gpio, 0); 302 return ret; 303 } 304 305 static const struct reg_default lp8860_reg_defs[] = { 306 { LP8860_DISP_CL1_BRT_MSB, 0x00}, 307 { LP8860_DISP_CL1_BRT_LSB, 0x00}, 308 { LP8860_DISP_CL1_CURR_MSB, 0x00}, 309 { LP8860_DISP_CL1_CURR_LSB, 0x00}, 310 { LP8860_CL2_BRT_MSB, 0x00}, 311 { LP8860_CL2_BRT_LSB, 0x00}, 312 { LP8860_CL2_CURRENT, 0x00}, 313 { LP8860_CL3_BRT_MSB, 0x00}, 314 { LP8860_CL3_BRT_LSB, 0x00}, 315 { LP8860_CL3_CURRENT, 0x00}, 316 { LP8860_CL4_BRT_MSB, 0x00}, 317 { LP8860_CL4_BRT_LSB, 0x00}, 318 { LP8860_CL4_CURRENT, 0x00}, 319 { LP8860_CONFIG, 0x00}, 320 { LP8860_FAULT_CLEAR, 0x00}, 321 { LP8860_EEPROM_CNTRL, 0x80}, 322 { LP8860_EEPROM_UNLOCK, 0x00}, 323 }; 324 325 static const struct regmap_config lp8860_regmap_config = { 326 .reg_bits = 8, 327 .val_bits = 8, 328 329 .max_register = LP8860_EEPROM_UNLOCK, 330 .reg_defaults = lp8860_reg_defs, 331 .num_reg_defaults = ARRAY_SIZE(lp8860_reg_defs), 332 .cache_type = REGCACHE_NONE, 333 }; 334 335 static const struct reg_default lp8860_eeprom_defs[] = { 336 { LP8860_EEPROM_REG_0, 0x00 }, 337 { LP8860_EEPROM_REG_1, 0x00 }, 338 { LP8860_EEPROM_REG_2, 0x00 }, 339 { LP8860_EEPROM_REG_3, 0x00 }, 340 { LP8860_EEPROM_REG_4, 0x00 }, 341 { LP8860_EEPROM_REG_5, 0x00 }, 342 { LP8860_EEPROM_REG_6, 0x00 }, 343 { LP8860_EEPROM_REG_7, 0x00 }, 344 { LP8860_EEPROM_REG_8, 0x00 }, 345 { LP8860_EEPROM_REG_9, 0x00 }, 346 { LP8860_EEPROM_REG_10, 0x00 }, 347 { LP8860_EEPROM_REG_11, 0x00 }, 348 { LP8860_EEPROM_REG_12, 0x00 }, 349 { LP8860_EEPROM_REG_13, 0x00 }, 350 { LP8860_EEPROM_REG_14, 0x00 }, 351 { LP8860_EEPROM_REG_15, 0x00 }, 352 { LP8860_EEPROM_REG_16, 0x00 }, 353 { LP8860_EEPROM_REG_17, 0x00 }, 354 { LP8860_EEPROM_REG_18, 0x00 }, 355 { LP8860_EEPROM_REG_19, 0x00 }, 356 { LP8860_EEPROM_REG_20, 0x00 }, 357 { LP8860_EEPROM_REG_21, 0x00 }, 358 { LP8860_EEPROM_REG_22, 0x00 }, 359 { LP8860_EEPROM_REG_23, 0x00 }, 360 { LP8860_EEPROM_REG_24, 0x00 }, 361 }; 362 363 static const struct regmap_config lp8860_eeprom_regmap_config = { 364 .reg_bits = 8, 365 .val_bits = 8, 366 367 .max_register = LP8860_EEPROM_REG_24, 368 .reg_defaults = lp8860_eeprom_defs, 369 .num_reg_defaults = ARRAY_SIZE(lp8860_eeprom_defs), 370 .cache_type = REGCACHE_NONE, 371 }; 372 373 static int lp8860_probe(struct i2c_client *client, 374 const struct i2c_device_id *id) 375 { 376 int ret; 377 struct lp8860_led *led; 378 struct device_node *np = client->dev.of_node; 379 380 led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); 381 if (!led) 382 return -ENOMEM; 383 384 led->label = LP8860_DISP_LED_NAME; 385 386 if (client->dev.of_node) { 387 ret = of_property_read_string(np, "label", &led->label); 388 if (ret) { 389 dev_err(&client->dev, "Missing label in dt\n"); 390 return -EINVAL; 391 } 392 } 393 394 led->enable_gpio = devm_gpiod_get_optional(&client->dev, 395 "enable", GPIOD_OUT_LOW); 396 if (IS_ERR(led->enable_gpio)) { 397 ret = PTR_ERR(led->enable_gpio); 398 dev_err(&client->dev, "Failed to get enable gpio: %d\n", ret); 399 return ret; 400 } 401 402 led->regulator = devm_regulator_get(&client->dev, "vled"); 403 if (IS_ERR(led->regulator)) 404 led->regulator = NULL; 405 406 led->client = client; 407 led->led_dev.name = led->label; 408 led->led_dev.max_brightness = LED_FULL; 409 led->led_dev.brightness_set = lp8860_brightness_set; 410 411 mutex_init(&led->lock); 412 INIT_WORK(&led->work, lp8860_led_brightness_work); 413 414 i2c_set_clientdata(client, led); 415 416 led->regmap = devm_regmap_init_i2c(client, &lp8860_regmap_config); 417 if (IS_ERR(led->regmap)) { 418 ret = PTR_ERR(led->regmap); 419 dev_err(&client->dev, "Failed to allocate register map: %d\n", 420 ret); 421 return ret; 422 } 423 424 led->eeprom_regmap = devm_regmap_init_i2c(client, &lp8860_eeprom_regmap_config); 425 if (IS_ERR(led->eeprom_regmap)) { 426 ret = PTR_ERR(led->eeprom_regmap); 427 dev_err(&client->dev, "Failed to allocate register map: %d\n", 428 ret); 429 return ret; 430 } 431 432 ret = lp8860_init(led); 433 if (ret) 434 return ret; 435 436 ret = led_classdev_register(&client->dev, &led->led_dev); 437 if (ret) { 438 dev_err(&client->dev, "led register err: %d\n", ret); 439 return ret; 440 } 441 442 return 0; 443 } 444 445 static int lp8860_remove(struct i2c_client *client) 446 { 447 struct lp8860_led *led = i2c_get_clientdata(client); 448 int ret; 449 450 led_classdev_unregister(&led->led_dev); 451 cancel_work_sync(&led->work); 452 453 if (led->enable_gpio) 454 gpiod_direction_output(led->enable_gpio, 0); 455 456 if (led->regulator) { 457 ret = regulator_disable(led->regulator); 458 if (ret) 459 dev_err(&led->client->dev, 460 "Failed to disable regulator\n"); 461 } 462 463 return 0; 464 } 465 466 static const struct i2c_device_id lp8860_id[] = { 467 { "lp8860", 0 }, 468 { } 469 }; 470 MODULE_DEVICE_TABLE(i2c, lp8860_id); 471 472 #ifdef CONFIG_OF 473 static const struct of_device_id of_lp8860_leds_match[] = { 474 { .compatible = "ti,lp8860", }, 475 {}, 476 }; 477 MODULE_DEVICE_TABLE(of, of_lp8860_leds_match); 478 #endif 479 480 static struct i2c_driver lp8860_driver = { 481 .driver = { 482 .name = "lp8860", 483 .of_match_table = of_match_ptr(of_lp8860_leds_match), 484 }, 485 .probe = lp8860_probe, 486 .remove = lp8860_remove, 487 .id_table = lp8860_id, 488 }; 489 module_i2c_driver(lp8860_driver); 490 491 MODULE_DESCRIPTION("Texas Instruments LP8860 LED driver"); 492 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>"); 493 MODULE_LICENSE("GPL"); 494