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