1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Simple driver for Texas Instruments LM355x LED Flash driver chip 4 * Copyright (C) 2012 Texas Instruments 5 */ 6 7 #include <linux/module.h> 8 #include <linux/delay.h> 9 #include <linux/i2c.h> 10 #include <linux/gpio.h> 11 #include <linux/leds.h> 12 #include <linux/slab.h> 13 #include <linux/platform_device.h> 14 #include <linux/fs.h> 15 #include <linux/regmap.h> 16 #include <linux/platform_data/leds-lm355x.h> 17 18 enum lm355x_type { 19 CHIP_LM3554 = 0, 20 CHIP_LM3556, 21 }; 22 23 enum lm355x_regs { 24 REG_FLAG = 0, 25 REG_TORCH_CFG, 26 REG_TORCH_CTRL, 27 REG_STROBE_CFG, 28 REG_FLASH_CTRL, 29 REG_INDI_CFG, 30 REG_INDI_CTRL, 31 REG_OPMODE, 32 REG_MAX, 33 }; 34 35 /* operation mode */ 36 enum lm355x_mode { 37 MODE_SHDN = 0, 38 MODE_INDIC, 39 MODE_TORCH, 40 MODE_FLASH 41 }; 42 43 /* register map info. */ 44 struct lm355x_reg_data { 45 u8 regno; 46 u8 mask; 47 u8 shift; 48 }; 49 50 struct lm355x_chip_data { 51 struct device *dev; 52 enum lm355x_type type; 53 54 struct led_classdev cdev_flash; 55 struct led_classdev cdev_torch; 56 struct led_classdev cdev_indicator; 57 58 struct lm355x_platform_data *pdata; 59 struct regmap *regmap; 60 struct mutex lock; 61 62 unsigned int last_flag; 63 struct lm355x_reg_data *regs; 64 }; 65 66 /* specific indicator function for lm3556 */ 67 enum lm3556_indic_pulse_time { 68 PULSE_TIME_0_MS = 0, 69 PULSE_TIME_32_MS, 70 PULSE_TIME_64_MS, 71 PULSE_TIME_92_MS, 72 PULSE_TIME_128_MS, 73 PULSE_TIME_160_MS, 74 PULSE_TIME_196_MS, 75 PULSE_TIME_224_MS, 76 PULSE_TIME_256_MS, 77 PULSE_TIME_288_MS, 78 PULSE_TIME_320_MS, 79 PULSE_TIME_352_MS, 80 PULSE_TIME_384_MS, 81 PULSE_TIME_416_MS, 82 PULSE_TIME_448_MS, 83 PULSE_TIME_480_MS, 84 }; 85 86 enum lm3556_indic_n_blank { 87 INDIC_N_BLANK_0 = 0, 88 INDIC_N_BLANK_1, 89 INDIC_N_BLANK_2, 90 INDIC_N_BLANK_3, 91 INDIC_N_BLANK_4, 92 INDIC_N_BLANK_5, 93 INDIC_N_BLANK_6, 94 INDIC_N_BLANK_7, 95 INDIC_N_BLANK_8, 96 INDIC_N_BLANK_9, 97 INDIC_N_BLANK_10, 98 INDIC_N_BLANK_11, 99 INDIC_N_BLANK_12, 100 INDIC_N_BLANK_13, 101 INDIC_N_BLANK_14, 102 INDIC_N_BLANK_15, 103 }; 104 105 enum lm3556_indic_period { 106 INDIC_PERIOD_0 = 0, 107 INDIC_PERIOD_1, 108 INDIC_PERIOD_2, 109 INDIC_PERIOD_3, 110 INDIC_PERIOD_4, 111 INDIC_PERIOD_5, 112 INDIC_PERIOD_6, 113 INDIC_PERIOD_7, 114 }; 115 116 #define INDIC_PATTERN_SIZE 4 117 118 struct indicator { 119 u8 blinking; 120 u8 period_cnt; 121 }; 122 123 /* indicator pattern data only for lm3556 */ 124 static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = { 125 [0] = {(INDIC_N_BLANK_1 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_1}, 126 [1] = {(INDIC_N_BLANK_15 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_2}, 127 [2] = {(INDIC_N_BLANK_10 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_4}, 128 [3] = {(INDIC_N_BLANK_5 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_7}, 129 }; 130 131 static struct lm355x_reg_data lm3554_regs[REG_MAX] = { 132 [REG_FLAG] = {0xD0, 0xBF, 0}, 133 [REG_TORCH_CFG] = {0xE0, 0x80, 7}, 134 [REG_TORCH_CTRL] = {0xA0, 0x38, 3}, 135 [REG_STROBE_CFG] = {0xE0, 0x04, 2}, 136 [REG_FLASH_CTRL] = {0xB0, 0x78, 3}, 137 [REG_INDI_CFG] = {0xE0, 0x08, 3}, 138 [REG_INDI_CTRL] = {0xA0, 0xC0, 6}, 139 [REG_OPMODE] = {0xA0, 0x03, 0}, 140 }; 141 142 static struct lm355x_reg_data lm3556_regs[REG_MAX] = { 143 [REG_FLAG] = {0x0B, 0xFF, 0}, 144 [REG_TORCH_CFG] = {0x0A, 0x10, 4}, 145 [REG_TORCH_CTRL] = {0x09, 0x70, 4}, 146 [REG_STROBE_CFG] = {0x0A, 0x20, 5}, 147 [REG_FLASH_CTRL] = {0x09, 0x0F, 0}, 148 [REG_INDI_CFG] = {0xFF, 0xFF, 0}, 149 [REG_INDI_CTRL] = {0x09, 0x70, 4}, 150 [REG_OPMODE] = {0x0A, 0x03, 0}, 151 }; 152 153 static char lm355x_name[][I2C_NAME_SIZE] = { 154 [CHIP_LM3554] = LM3554_NAME, 155 [CHIP_LM3556] = LM3556_NAME, 156 }; 157 158 /* chip initialize */ 159 static int lm355x_chip_init(struct lm355x_chip_data *chip) 160 { 161 int ret; 162 unsigned int reg_val; 163 struct lm355x_platform_data *pdata = chip->pdata; 164 165 /* input and output pins configuration */ 166 switch (chip->type) { 167 case CHIP_LM3554: 168 reg_val = pdata->pin_tx2 | pdata->ntc_pin; 169 ret = regmap_update_bits(chip->regmap, 0xE0, 0x28, reg_val); 170 if (ret < 0) 171 goto out; 172 reg_val = pdata->pass_mode; 173 ret = regmap_update_bits(chip->regmap, 0xA0, 0x04, reg_val); 174 if (ret < 0) 175 goto out; 176 break; 177 178 case CHIP_LM3556: 179 reg_val = pdata->pin_tx2 | pdata->ntc_pin | pdata->pass_mode; 180 ret = regmap_update_bits(chip->regmap, 0x0A, 0xC4, reg_val); 181 if (ret < 0) 182 goto out; 183 break; 184 default: 185 return -ENODATA; 186 } 187 188 return ret; 189 out: 190 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 191 return ret; 192 } 193 194 /* chip control */ 195 static int lm355x_control(struct lm355x_chip_data *chip, 196 u8 brightness, enum lm355x_mode opmode) 197 { 198 int ret; 199 unsigned int reg_val; 200 struct lm355x_platform_data *pdata = chip->pdata; 201 struct lm355x_reg_data *preg = chip->regs; 202 203 ret = regmap_read(chip->regmap, preg[REG_FLAG].regno, &chip->last_flag); 204 if (ret < 0) 205 goto out; 206 if (chip->last_flag & preg[REG_FLAG].mask) 207 dev_info(chip->dev, "%s Last FLAG is 0x%x\n", 208 lm355x_name[chip->type], 209 chip->last_flag & preg[REG_FLAG].mask); 210 /* brightness 0 means shutdown */ 211 if (!brightness) 212 opmode = MODE_SHDN; 213 214 switch (opmode) { 215 case MODE_TORCH: 216 ret = 217 regmap_update_bits(chip->regmap, preg[REG_TORCH_CTRL].regno, 218 preg[REG_TORCH_CTRL].mask, 219 (brightness - 1) 220 << preg[REG_TORCH_CTRL].shift); 221 if (ret < 0) 222 goto out; 223 224 if (pdata->pin_tx1 != LM355x_PIN_TORCH_DISABLE) { 225 ret = 226 regmap_update_bits(chip->regmap, 227 preg[REG_TORCH_CFG].regno, 228 preg[REG_TORCH_CFG].mask, 229 0x01 << 230 preg[REG_TORCH_CFG].shift); 231 if (ret < 0) 232 goto out; 233 opmode = MODE_SHDN; 234 dev_info(chip->dev, 235 "torch brt is set - ext. torch pin mode\n"); 236 } 237 break; 238 239 case MODE_FLASH: 240 241 ret = 242 regmap_update_bits(chip->regmap, preg[REG_FLASH_CTRL].regno, 243 preg[REG_FLASH_CTRL].mask, 244 (brightness - 1) 245 << preg[REG_FLASH_CTRL].shift); 246 if (ret < 0) 247 goto out; 248 249 if (pdata->pin_strobe != LM355x_PIN_STROBE_DISABLE) { 250 if (chip->type == CHIP_LM3554) 251 reg_val = 0x00; 252 else 253 reg_val = 0x01; 254 ret = 255 regmap_update_bits(chip->regmap, 256 preg[REG_STROBE_CFG].regno, 257 preg[REG_STROBE_CFG].mask, 258 reg_val << 259 preg[REG_STROBE_CFG].shift); 260 if (ret < 0) 261 goto out; 262 opmode = MODE_SHDN; 263 dev_info(chip->dev, 264 "flash brt is set - ext. strobe pin mode\n"); 265 } 266 break; 267 268 case MODE_INDIC: 269 ret = 270 regmap_update_bits(chip->regmap, preg[REG_INDI_CTRL].regno, 271 preg[REG_INDI_CTRL].mask, 272 (brightness - 1) 273 << preg[REG_INDI_CTRL].shift); 274 if (ret < 0) 275 goto out; 276 277 if (pdata->pin_tx2 != LM355x_PIN_TX_DISABLE) { 278 ret = 279 regmap_update_bits(chip->regmap, 280 preg[REG_INDI_CFG].regno, 281 preg[REG_INDI_CFG].mask, 282 0x01 << 283 preg[REG_INDI_CFG].shift); 284 if (ret < 0) 285 goto out; 286 opmode = MODE_SHDN; 287 } 288 break; 289 case MODE_SHDN: 290 break; 291 default: 292 return -EINVAL; 293 } 294 /* operation mode control */ 295 ret = regmap_update_bits(chip->regmap, preg[REG_OPMODE].regno, 296 preg[REG_OPMODE].mask, 297 opmode << preg[REG_OPMODE].shift); 298 if (ret < 0) 299 goto out; 300 return ret; 301 out: 302 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 303 return ret; 304 } 305 306 /* torch */ 307 308 static int lm355x_torch_brightness_set(struct led_classdev *cdev, 309 enum led_brightness brightness) 310 { 311 struct lm355x_chip_data *chip = 312 container_of(cdev, struct lm355x_chip_data, cdev_torch); 313 int ret; 314 315 mutex_lock(&chip->lock); 316 ret = lm355x_control(chip, brightness, MODE_TORCH); 317 mutex_unlock(&chip->lock); 318 return ret; 319 } 320 321 /* flash */ 322 323 static int lm355x_strobe_brightness_set(struct led_classdev *cdev, 324 enum led_brightness brightness) 325 { 326 struct lm355x_chip_data *chip = 327 container_of(cdev, struct lm355x_chip_data, cdev_flash); 328 int ret; 329 330 mutex_lock(&chip->lock); 331 ret = lm355x_control(chip, brightness, MODE_FLASH); 332 mutex_unlock(&chip->lock); 333 return ret; 334 } 335 336 /* indicator */ 337 338 static int lm355x_indicator_brightness_set(struct led_classdev *cdev, 339 enum led_brightness brightness) 340 { 341 struct lm355x_chip_data *chip = 342 container_of(cdev, struct lm355x_chip_data, cdev_indicator); 343 int ret; 344 345 mutex_lock(&chip->lock); 346 ret = lm355x_control(chip, brightness, MODE_INDIC); 347 mutex_unlock(&chip->lock); 348 return ret; 349 } 350 351 /* indicator pattern only for lm3556*/ 352 static ssize_t lm3556_indicator_pattern_store(struct device *dev, 353 struct device_attribute *attr, 354 const char *buf, size_t size) 355 { 356 ssize_t ret; 357 struct led_classdev *led_cdev = dev_get_drvdata(dev); 358 struct lm355x_chip_data *chip = 359 container_of(led_cdev, struct lm355x_chip_data, cdev_indicator); 360 unsigned int state; 361 362 ret = kstrtouint(buf, 10, &state); 363 if (ret) 364 goto out; 365 if (state > INDIC_PATTERN_SIZE - 1) 366 state = INDIC_PATTERN_SIZE - 1; 367 368 ret = regmap_write(chip->regmap, 0x04, 369 indicator_pattern[state].blinking); 370 if (ret < 0) 371 goto out; 372 373 ret = regmap_write(chip->regmap, 0x05, 374 indicator_pattern[state].period_cnt); 375 if (ret < 0) 376 goto out; 377 378 return size; 379 out: 380 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 381 return ret; 382 } 383 384 static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store); 385 386 static struct attribute *lm355x_indicator_attrs[] = { 387 &dev_attr_pattern.attr, 388 NULL 389 }; 390 ATTRIBUTE_GROUPS(lm355x_indicator); 391 392 static const struct regmap_config lm355x_regmap = { 393 .reg_bits = 8, 394 .val_bits = 8, 395 .max_register = 0xFF, 396 }; 397 398 /* module initialize */ 399 static int lm355x_probe(struct i2c_client *client, 400 const struct i2c_device_id *id) 401 { 402 struct lm355x_platform_data *pdata = dev_get_platdata(&client->dev); 403 struct lm355x_chip_data *chip; 404 405 int err; 406 407 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 408 dev_err(&client->dev, "i2c functionality check fail.\n"); 409 return -EOPNOTSUPP; 410 } 411 412 if (pdata == NULL) { 413 dev_err(&client->dev, "needs Platform Data.\n"); 414 return -ENODATA; 415 } 416 417 chip = devm_kzalloc(&client->dev, 418 sizeof(struct lm355x_chip_data), GFP_KERNEL); 419 if (!chip) 420 return -ENOMEM; 421 422 chip->dev = &client->dev; 423 chip->type = id->driver_data; 424 switch (id->driver_data) { 425 case CHIP_LM3554: 426 chip->regs = lm3554_regs; 427 break; 428 case CHIP_LM3556: 429 chip->regs = lm3556_regs; 430 break; 431 default: 432 return -ENOSYS; 433 } 434 chip->pdata = pdata; 435 436 chip->regmap = devm_regmap_init_i2c(client, &lm355x_regmap); 437 if (IS_ERR(chip->regmap)) { 438 err = PTR_ERR(chip->regmap); 439 dev_err(&client->dev, 440 "Failed to allocate register map: %d\n", err); 441 return err; 442 } 443 444 mutex_init(&chip->lock); 445 i2c_set_clientdata(client, chip); 446 447 err = lm355x_chip_init(chip); 448 if (err < 0) 449 goto err_out; 450 451 /* flash */ 452 chip->cdev_flash.name = "flash"; 453 chip->cdev_flash.max_brightness = 16; 454 chip->cdev_flash.brightness_set_blocking = lm355x_strobe_brightness_set; 455 chip->cdev_flash.default_trigger = "flash"; 456 err = led_classdev_register((struct device *) 457 &client->dev, &chip->cdev_flash); 458 if (err < 0) 459 goto err_out; 460 /* torch */ 461 chip->cdev_torch.name = "torch"; 462 chip->cdev_torch.max_brightness = 8; 463 chip->cdev_torch.brightness_set_blocking = lm355x_torch_brightness_set; 464 chip->cdev_torch.default_trigger = "torch"; 465 err = led_classdev_register((struct device *) 466 &client->dev, &chip->cdev_torch); 467 if (err < 0) 468 goto err_create_torch_file; 469 /* indicator */ 470 chip->cdev_indicator.name = "indicator"; 471 if (id->driver_data == CHIP_LM3554) 472 chip->cdev_indicator.max_brightness = 4; 473 else 474 chip->cdev_indicator.max_brightness = 8; 475 chip->cdev_indicator.brightness_set_blocking = 476 lm355x_indicator_brightness_set; 477 /* indicator pattern control only for LM3556 */ 478 if (id->driver_data == CHIP_LM3556) 479 chip->cdev_indicator.groups = lm355x_indicator_groups; 480 err = led_classdev_register((struct device *) 481 &client->dev, &chip->cdev_indicator); 482 if (err < 0) 483 goto err_create_indicator_file; 484 485 dev_info(&client->dev, "%s is initialized\n", 486 lm355x_name[id->driver_data]); 487 return 0; 488 489 err_create_indicator_file: 490 led_classdev_unregister(&chip->cdev_torch); 491 err_create_torch_file: 492 led_classdev_unregister(&chip->cdev_flash); 493 err_out: 494 return err; 495 } 496 497 static int lm355x_remove(struct i2c_client *client) 498 { 499 struct lm355x_chip_data *chip = i2c_get_clientdata(client); 500 struct lm355x_reg_data *preg = chip->regs; 501 502 regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0); 503 led_classdev_unregister(&chip->cdev_indicator); 504 led_classdev_unregister(&chip->cdev_torch); 505 led_classdev_unregister(&chip->cdev_flash); 506 dev_info(&client->dev, "%s is removed\n", lm355x_name[chip->type]); 507 508 return 0; 509 } 510 511 static const struct i2c_device_id lm355x_id[] = { 512 {LM3554_NAME, CHIP_LM3554}, 513 {LM3556_NAME, CHIP_LM3556}, 514 {} 515 }; 516 517 MODULE_DEVICE_TABLE(i2c, lm355x_id); 518 519 static struct i2c_driver lm355x_i2c_driver = { 520 .driver = { 521 .name = LM355x_NAME, 522 .pm = NULL, 523 }, 524 .probe = lm355x_probe, 525 .remove = lm355x_remove, 526 .id_table = lm355x_id, 527 }; 528 529 module_i2c_driver(lm355x_i2c_driver); 530 531 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM355x"); 532 MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); 533 MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); 534 MODULE_LICENSE("GPL v2"); 535