1/* 2* Simple driver for Texas Instruments LM3642 LED Flash driver chip 3* Copyright (C) 2012 Texas Instruments 4* 5* This program is free software; you can redistribute it and/or modify 6* it under the terms of the GNU General Public License version 2 as 7* published by the Free Software Foundation. 8* 9*/ 10#include <linux/module.h> 11#include <linux/delay.h> 12#include <linux/i2c.h> 13#include <linux/leds.h> 14#include <linux/slab.h> 15#include <linux/platform_device.h> 16#include <linux/fs.h> 17#include <linux/regmap.h> 18#include <linux/workqueue.h> 19#include <linux/platform_data/leds-lm3642.h> 20 21#define REG_FILT_TIME (0x0) 22#define REG_IVFM_MODE (0x1) 23#define REG_TORCH_TIME (0x6) 24#define REG_FLASH (0x8) 25#define REG_I_CTRL (0x9) 26#define REG_ENABLE (0xA) 27#define REG_FLAG (0xB) 28#define REG_MAX (0xB) 29 30#define UVLO_EN_SHIFT (7) 31#define IVM_D_TH_SHIFT (2) 32#define TORCH_RAMP_UP_TIME_SHIFT (3) 33#define TORCH_RAMP_DN_TIME_SHIFT (0) 34#define INDUCTOR_I_LIMIT_SHIFT (6) 35#define FLASH_RAMP_TIME_SHIFT (3) 36#define FLASH_TOUT_TIME_SHIFT (0) 37#define TORCH_I_SHIFT (4) 38#define FLASH_I_SHIFT (0) 39#define IVFM_SHIFT (7) 40#define TX_PIN_EN_SHIFT (6) 41#define STROBE_PIN_EN_SHIFT (5) 42#define TORCH_PIN_EN_SHIFT (4) 43#define MODE_BITS_SHIFT (0) 44 45#define UVLO_EN_MASK (0x1) 46#define IVM_D_TH_MASK (0x7) 47#define TORCH_RAMP_UP_TIME_MASK (0x7) 48#define TORCH_RAMP_DN_TIME_MASK (0x7) 49#define INDUCTOR_I_LIMIT_MASK (0x1) 50#define FLASH_RAMP_TIME_MASK (0x7) 51#define FLASH_TOUT_TIME_MASK (0x7) 52#define TORCH_I_MASK (0x7) 53#define FLASH_I_MASK (0xF) 54#define IVFM_MASK (0x1) 55#define TX_PIN_EN_MASK (0x1) 56#define STROBE_PIN_EN_MASK (0x1) 57#define TORCH_PIN_EN_MASK (0x1) 58#define MODE_BITS_MASK (0x73) 59#define EX_PIN_CONTROL_MASK (0x71) 60#define EX_PIN_ENABLE_MASK (0x70) 61 62enum lm3642_mode { 63 MODES_STASNDBY = 0, 64 MODES_INDIC, 65 MODES_TORCH, 66 MODES_FLASH 67}; 68 69struct lm3642_chip_data { 70 struct device *dev; 71 72 struct led_classdev cdev_flash; 73 struct led_classdev cdev_torch; 74 struct led_classdev cdev_indicator; 75 76 struct work_struct work_flash; 77 struct work_struct work_torch; 78 struct work_struct work_indicator; 79 80 u8 br_flash; 81 u8 br_torch; 82 u8 br_indicator; 83 84 enum lm3642_torch_pin_enable torch_pin; 85 enum lm3642_strobe_pin_enable strobe_pin; 86 enum lm3642_tx_pin_enable tx_pin; 87 88 struct lm3642_platform_data *pdata; 89 struct regmap *regmap; 90 struct mutex lock; 91 92 unsigned int last_flag; 93}; 94 95/* chip initialize */ 96static int lm3642_chip_init(struct lm3642_chip_data *chip) 97{ 98 int ret; 99 struct lm3642_platform_data *pdata = chip->pdata; 100 101 /* set enable register */ 102 ret = regmap_update_bits(chip->regmap, REG_ENABLE, EX_PIN_ENABLE_MASK, 103 pdata->tx_pin); 104 if (ret < 0) 105 dev_err(chip->dev, "Failed to update REG_ENABLE Register\n"); 106 return ret; 107} 108 109/* chip control */ 110static int lm3642_control(struct lm3642_chip_data *chip, 111 u8 brightness, enum lm3642_mode opmode) 112{ 113 int ret; 114 115 ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag); 116 if (ret < 0) { 117 dev_err(chip->dev, "Failed to read REG_FLAG Register\n"); 118 goto out; 119 } 120 121 if (chip->last_flag) 122 dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag); 123 124 /* brightness 0 means off-state */ 125 if (!brightness) 126 opmode = MODES_STASNDBY; 127 128 switch (opmode) { 129 case MODES_TORCH: 130 ret = regmap_update_bits(chip->regmap, REG_I_CTRL, 131 TORCH_I_MASK << TORCH_I_SHIFT, 132 (brightness - 1) << TORCH_I_SHIFT); 133 134 if (chip->torch_pin) 135 opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT); 136 break; 137 138 case MODES_FLASH: 139 ret = regmap_update_bits(chip->regmap, REG_I_CTRL, 140 FLASH_I_MASK << FLASH_I_SHIFT, 141 (brightness - 1) << FLASH_I_SHIFT); 142 143 if (chip->strobe_pin) 144 opmode |= (STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT); 145 break; 146 147 case MODES_INDIC: 148 ret = regmap_update_bits(chip->regmap, REG_I_CTRL, 149 TORCH_I_MASK << TORCH_I_SHIFT, 150 (brightness - 1) << TORCH_I_SHIFT); 151 break; 152 153 case MODES_STASNDBY: 154 155 break; 156 157 default: 158 return ret; 159 } 160 if (ret < 0) { 161 dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n"); 162 goto out; 163 } 164 165 if (chip->tx_pin) 166 opmode |= (TX_PIN_EN_MASK << TX_PIN_EN_SHIFT); 167 168 ret = regmap_update_bits(chip->regmap, REG_ENABLE, 169 MODE_BITS_MASK << MODE_BITS_SHIFT, 170 opmode << MODE_BITS_SHIFT); 171out: 172 return ret; 173} 174 175/* torch */ 176 177/* torch pin config for lm3642*/ 178static ssize_t lm3642_torch_pin_store(struct device *dev, 179 struct device_attribute *attr, 180 const char *buf, size_t size) 181{ 182 ssize_t ret; 183 struct led_classdev *led_cdev = dev_get_drvdata(dev); 184 struct lm3642_chip_data *chip = 185 container_of(led_cdev, struct lm3642_chip_data, cdev_indicator); 186 unsigned int state; 187 188 ret = kstrtouint(buf, 10, &state); 189 if (ret) 190 goto out_strtoint; 191 if (state != 0) 192 state = 0x01 << TORCH_PIN_EN_SHIFT; 193 194 chip->torch_pin = state; 195 ret = regmap_update_bits(chip->regmap, REG_ENABLE, 196 TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT, 197 state); 198 if (ret < 0) 199 goto out; 200 201 return size; 202out: 203 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 204 return ret; 205out_strtoint: 206 dev_err(chip->dev, "%s: fail to change str to int\n", __func__); 207 return ret; 208} 209 210static DEVICE_ATTR(torch_pin, S_IWUSR, NULL, lm3642_torch_pin_store); 211 212static void lm3642_deferred_torch_brightness_set(struct work_struct *work) 213{ 214 struct lm3642_chip_data *chip = 215 container_of(work, struct lm3642_chip_data, work_torch); 216 217 mutex_lock(&chip->lock); 218 lm3642_control(chip, chip->br_torch, MODES_TORCH); 219 mutex_unlock(&chip->lock); 220} 221 222static void lm3642_torch_brightness_set(struct led_classdev *cdev, 223 enum led_brightness brightness) 224{ 225 struct lm3642_chip_data *chip = 226 container_of(cdev, struct lm3642_chip_data, cdev_torch); 227 228 chip->br_torch = brightness; 229 schedule_work(&chip->work_torch); 230} 231 232/* flash */ 233 234/* strobe pin config for lm3642*/ 235static ssize_t lm3642_strobe_pin_store(struct device *dev, 236 struct device_attribute *attr, 237 const char *buf, size_t size) 238{ 239 ssize_t ret; 240 struct led_classdev *led_cdev = dev_get_drvdata(dev); 241 struct lm3642_chip_data *chip = 242 container_of(led_cdev, struct lm3642_chip_data, cdev_indicator); 243 unsigned int state; 244 245 ret = kstrtouint(buf, 10, &state); 246 if (ret) 247 goto out_strtoint; 248 if (state != 0) 249 state = 0x01 << STROBE_PIN_EN_SHIFT; 250 251 chip->strobe_pin = state; 252 ret = regmap_update_bits(chip->regmap, REG_ENABLE, 253 STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT, 254 state); 255 if (ret < 0) 256 goto out; 257 258 return size; 259out: 260 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 261 return ret; 262out_strtoint: 263 dev_err(chip->dev, "%s: fail to change str to int\n", __func__); 264 return ret; 265} 266 267static DEVICE_ATTR(strobe_pin, S_IWUSR, NULL, lm3642_strobe_pin_store); 268 269static void lm3642_deferred_strobe_brightness_set(struct work_struct *work) 270{ 271 struct lm3642_chip_data *chip = 272 container_of(work, struct lm3642_chip_data, work_flash); 273 274 mutex_lock(&chip->lock); 275 lm3642_control(chip, chip->br_flash, MODES_FLASH); 276 mutex_unlock(&chip->lock); 277} 278 279static void lm3642_strobe_brightness_set(struct led_classdev *cdev, 280 enum led_brightness brightness) 281{ 282 struct lm3642_chip_data *chip = 283 container_of(cdev, struct lm3642_chip_data, cdev_flash); 284 285 chip->br_flash = brightness; 286 schedule_work(&chip->work_flash); 287} 288 289/* indicator */ 290static void lm3642_deferred_indicator_brightness_set(struct work_struct *work) 291{ 292 struct lm3642_chip_data *chip = 293 container_of(work, struct lm3642_chip_data, work_indicator); 294 295 mutex_lock(&chip->lock); 296 lm3642_control(chip, chip->br_indicator, MODES_INDIC); 297 mutex_unlock(&chip->lock); 298} 299 300static void lm3642_indicator_brightness_set(struct led_classdev *cdev, 301 enum led_brightness brightness) 302{ 303 struct lm3642_chip_data *chip = 304 container_of(cdev, struct lm3642_chip_data, cdev_indicator); 305 306 chip->br_indicator = brightness; 307 schedule_work(&chip->work_indicator); 308} 309 310static const struct regmap_config lm3642_regmap = { 311 .reg_bits = 8, 312 .val_bits = 8, 313 .max_register = REG_MAX, 314}; 315 316static struct attribute *lm3642_flash_attrs[] = { 317 &dev_attr_strobe_pin.attr, 318 NULL 319}; 320ATTRIBUTE_GROUPS(lm3642_flash); 321 322static struct attribute *lm3642_torch_attrs[] = { 323 &dev_attr_torch_pin.attr, 324 NULL 325}; 326ATTRIBUTE_GROUPS(lm3642_torch); 327 328static int lm3642_probe(struct i2c_client *client, 329 const struct i2c_device_id *id) 330{ 331 struct lm3642_platform_data *pdata = dev_get_platdata(&client->dev); 332 struct lm3642_chip_data *chip; 333 334 int err; 335 336 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 337 dev_err(&client->dev, "i2c functionality check fail.\n"); 338 return -EOPNOTSUPP; 339 } 340 341 if (pdata == NULL) { 342 dev_err(&client->dev, "needs Platform Data.\n"); 343 return -ENODATA; 344 } 345 346 chip = devm_kzalloc(&client->dev, 347 sizeof(struct lm3642_chip_data), GFP_KERNEL); 348 if (!chip) 349 return -ENOMEM; 350 351 chip->dev = &client->dev; 352 chip->pdata = pdata; 353 354 chip->tx_pin = pdata->tx_pin; 355 chip->torch_pin = pdata->torch_pin; 356 chip->strobe_pin = pdata->strobe_pin; 357 358 chip->regmap = devm_regmap_init_i2c(client, &lm3642_regmap); 359 if (IS_ERR(chip->regmap)) { 360 err = PTR_ERR(chip->regmap); 361 dev_err(&client->dev, "Failed to allocate register map: %d\n", 362 err); 363 return err; 364 } 365 366 mutex_init(&chip->lock); 367 i2c_set_clientdata(client, chip); 368 369 err = lm3642_chip_init(chip); 370 if (err < 0) 371 goto err_out; 372 373 /* flash */ 374 INIT_WORK(&chip->work_flash, lm3642_deferred_strobe_brightness_set); 375 chip->cdev_flash.name = "flash"; 376 chip->cdev_flash.max_brightness = 16; 377 chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set; 378 chip->cdev_flash.default_trigger = "flash"; 379 chip->cdev_flash.groups = lm3642_flash_groups, 380 err = led_classdev_register((struct device *) 381 &client->dev, &chip->cdev_flash); 382 if (err < 0) { 383 dev_err(chip->dev, "failed to register flash\n"); 384 goto err_out; 385 } 386 387 /* torch */ 388 INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set); 389 chip->cdev_torch.name = "torch"; 390 chip->cdev_torch.max_brightness = 8; 391 chip->cdev_torch.brightness_set = lm3642_torch_brightness_set; 392 chip->cdev_torch.default_trigger = "torch"; 393 chip->cdev_torch.groups = lm3642_torch_groups, 394 err = led_classdev_register((struct device *) 395 &client->dev, &chip->cdev_torch); 396 if (err < 0) { 397 dev_err(chip->dev, "failed to register torch\n"); 398 goto err_create_torch_file; 399 } 400 401 /* indicator */ 402 INIT_WORK(&chip->work_indicator, 403 lm3642_deferred_indicator_brightness_set); 404 chip->cdev_indicator.name = "indicator"; 405 chip->cdev_indicator.max_brightness = 8; 406 chip->cdev_indicator.brightness_set = lm3642_indicator_brightness_set; 407 err = led_classdev_register((struct device *) 408 &client->dev, &chip->cdev_indicator); 409 if (err < 0) { 410 dev_err(chip->dev, "failed to register indicator\n"); 411 goto err_create_indicator_file; 412 } 413 414 dev_info(&client->dev, "LM3642 is initialized\n"); 415 return 0; 416 417err_create_indicator_file: 418 led_classdev_unregister(&chip->cdev_torch); 419err_create_torch_file: 420 led_classdev_unregister(&chip->cdev_flash); 421err_out: 422 return err; 423} 424 425static int lm3642_remove(struct i2c_client *client) 426{ 427 struct lm3642_chip_data *chip = i2c_get_clientdata(client); 428 429 led_classdev_unregister(&chip->cdev_indicator); 430 flush_work(&chip->work_indicator); 431 led_classdev_unregister(&chip->cdev_torch); 432 flush_work(&chip->work_torch); 433 led_classdev_unregister(&chip->cdev_flash); 434 flush_work(&chip->work_flash); 435 regmap_write(chip->regmap, REG_ENABLE, 0); 436 return 0; 437} 438 439static const struct i2c_device_id lm3642_id[] = { 440 {LM3642_NAME, 0}, 441 {} 442}; 443 444MODULE_DEVICE_TABLE(i2c, lm3642_id); 445 446static struct i2c_driver lm3642_i2c_driver = { 447 .driver = { 448 .name = LM3642_NAME, 449 .owner = THIS_MODULE, 450 .pm = NULL, 451 }, 452 .probe = lm3642_probe, 453 .remove = lm3642_remove, 454 .id_table = lm3642_id, 455}; 456 457module_i2c_driver(lm3642_i2c_driver); 458 459MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3642"); 460MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); 461MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); 462MODULE_LICENSE("GPL v2"); 463