root/drivers/leds/leds-lm3601x.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lm3601x_volatile_reg
  2. fled_cdev_to_led
  3. lm3601x_read_faults
  4. lm3601x_brightness_set
  5. lm3601x_strobe_set
  6. lm3601x_flash_brightness_set
  7. lm3601x_flash_timeout_set
  8. lm3601x_strobe_get
  9. lm3601x_flash_fault_get
  10. lm3601x_register_leds
  11. lm3601x_parse_node
  12. lm3601x_probe
  13. lm3601x_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 // Flash and torch driver for Texas Instruments LM3601X LED
   3 // Flash driver chip family
   4 // Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
   5 
   6 #include <linux/delay.h>
   7 #include <linux/i2c.h>
   8 #include <linux/leds.h>
   9 #include <linux/led-class-flash.h>
  10 #include <linux/module.h>
  11 #include <linux/regmap.h>
  12 #include <linux/slab.h>
  13 
  14 #define LM3601X_LED_IR          0x0
  15 #define LM3601X_LED_TORCH       0x1
  16 
  17 /* Registers */
  18 #define LM3601X_ENABLE_REG      0x01
  19 #define LM3601X_CFG_REG         0x02
  20 #define LM3601X_LED_FLASH_REG   0x03
  21 #define LM3601X_LED_TORCH_REG   0x04
  22 #define LM3601X_FLAGS_REG       0x05
  23 #define LM3601X_DEV_ID_REG      0x06
  24 
  25 #define LM3601X_SW_RESET        BIT(7)
  26 
  27 /* Enable Mode bits */
  28 #define LM3601X_MODE_STANDBY    0x00
  29 #define LM3601X_MODE_IR_DRV     BIT(0)
  30 #define LM3601X_MODE_TORCH      BIT(1)
  31 #define LM3601X_MODE_STROBE     (BIT(0) | BIT(1))
  32 #define LM3601X_STRB_EN         BIT(2)
  33 #define LM3601X_STRB_EDGE_TRIG  BIT(3)
  34 #define LM3601X_IVFM_EN         BIT(4)
  35 
  36 #define LM36010_BOOST_LIMIT_28  BIT(5)
  37 #define LM36010_BOOST_FREQ_4MHZ BIT(6)
  38 #define LM36010_BOOST_MODE_PASS BIT(7)
  39 
  40 /* Flag Mask */
  41 #define LM3601X_FLASH_TIME_OUT  BIT(0)
  42 #define LM3601X_UVLO_FAULT      BIT(1)
  43 #define LM3601X_THERM_SHUTDOWN  BIT(2)
  44 #define LM3601X_THERM_CURR      BIT(3)
  45 #define LM36010_CURR_LIMIT      BIT(4)
  46 #define LM3601X_SHORT_FAULT     BIT(5)
  47 #define LM3601X_IVFM_TRIP       BIT(6)
  48 #define LM36010_OVP_FAULT       BIT(7)
  49 
  50 #define LM3601X_MAX_TORCH_I_UA  376000
  51 #define LM3601X_MIN_TORCH_I_UA  2400
  52 #define LM3601X_TORCH_REG_DIV   2965
  53 
  54 #define LM3601X_MAX_STROBE_I_UA 1500000
  55 #define LM3601X_MIN_STROBE_I_UA 11000
  56 #define LM3601X_STROBE_REG_DIV  11800
  57 
  58 #define LM3601X_TIMEOUT_MASK    0x1e
  59 #define LM3601X_ENABLE_MASK     (LM3601X_MODE_IR_DRV | LM3601X_MODE_TORCH)
  60 
  61 #define LM3601X_LOWER_STEP_US   40000
  62 #define LM3601X_UPPER_STEP_US   200000
  63 #define LM3601X_MIN_TIMEOUT_US  40000
  64 #define LM3601X_MAX_TIMEOUT_US  1600000
  65 #define LM3601X_TIMEOUT_XOVER_US 400000
  66 
  67 enum lm3601x_type {
  68         CHIP_LM36010 = 0,
  69         CHIP_LM36011,
  70 };
  71 
  72 /**
  73  * struct lm3601x_led -
  74  * @fled_cdev: flash LED class device pointer
  75  * @client: Pointer to the I2C client
  76  * @regmap: Devices register map
  77  * @lock: Lock for reading/writing the device
  78  * @led_name: LED label for the Torch or IR LED
  79  * @flash_timeout: the timeout for the flash
  80  * @last_flag: last known flags register value
  81  * @torch_current_max: maximum current for the torch
  82  * @flash_current_max: maximum current for the flash
  83  * @max_flash_timeout: maximum timeout for the flash
  84  * @led_mode: The mode to enable either IR or Torch
  85  */
  86 struct lm3601x_led {
  87         struct led_classdev_flash fled_cdev;
  88         struct i2c_client *client;
  89         struct regmap *regmap;
  90         struct mutex lock;
  91 
  92         unsigned int flash_timeout;
  93         unsigned int last_flag;
  94 
  95         u32 torch_current_max;
  96         u32 flash_current_max;
  97         u32 max_flash_timeout;
  98 
  99         u32 led_mode;
 100 };
 101 
 102 static const struct reg_default lm3601x_regmap_defs[] = {
 103         { LM3601X_ENABLE_REG, 0x20 },
 104         { LM3601X_CFG_REG, 0x15 },
 105         { LM3601X_LED_FLASH_REG, 0x00 },
 106         { LM3601X_LED_TORCH_REG, 0x00 },
 107 };
 108 
 109 static bool lm3601x_volatile_reg(struct device *dev, unsigned int reg)
 110 {
 111         switch (reg) {
 112         case LM3601X_FLAGS_REG:
 113                 return true;
 114         default:
 115                 return false;
 116         }
 117 }
 118 
 119 static const struct regmap_config lm3601x_regmap = {
 120         .reg_bits = 8,
 121         .val_bits = 8,
 122 
 123         .max_register = LM3601X_DEV_ID_REG,
 124         .reg_defaults = lm3601x_regmap_defs,
 125         .num_reg_defaults = ARRAY_SIZE(lm3601x_regmap_defs),
 126         .cache_type = REGCACHE_RBTREE,
 127         .volatile_reg = lm3601x_volatile_reg,
 128 };
 129 
 130 static struct lm3601x_led *fled_cdev_to_led(struct led_classdev_flash *fled_cdev)
 131 {
 132         return container_of(fled_cdev, struct lm3601x_led, fled_cdev);
 133 }
 134 
 135 static int lm3601x_read_faults(struct lm3601x_led *led)
 136 {
 137         int flags_val;
 138         int ret;
 139 
 140         ret = regmap_read(led->regmap, LM3601X_FLAGS_REG, &flags_val);
 141         if (ret < 0)
 142                 return -EIO;
 143 
 144         led->last_flag = 0;
 145 
 146         if (flags_val & LM36010_OVP_FAULT)
 147                 led->last_flag |= LED_FAULT_OVER_VOLTAGE;
 148 
 149         if (flags_val & (LM3601X_THERM_SHUTDOWN | LM3601X_THERM_CURR))
 150                 led->last_flag |= LED_FAULT_OVER_TEMPERATURE;
 151 
 152         if (flags_val & LM3601X_SHORT_FAULT)
 153                 led->last_flag |= LED_FAULT_SHORT_CIRCUIT;
 154 
 155         if (flags_val & LM36010_CURR_LIMIT)
 156                 led->last_flag |= LED_FAULT_OVER_CURRENT;
 157 
 158         if (flags_val & LM3601X_UVLO_FAULT)
 159                 led->last_flag |= LED_FAULT_UNDER_VOLTAGE;
 160 
 161         if (flags_val & LM3601X_IVFM_TRIP)
 162                 led->last_flag |= LED_FAULT_INPUT_VOLTAGE;
 163 
 164         if (flags_val & LM3601X_THERM_SHUTDOWN)
 165                 led->last_flag |= LED_FAULT_LED_OVER_TEMPERATURE;
 166 
 167         return led->last_flag;
 168 }
 169 
 170 static int lm3601x_brightness_set(struct led_classdev *cdev,
 171                                         enum led_brightness brightness)
 172 {
 173         struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(cdev);
 174         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
 175         int ret, led_mode_val;
 176 
 177         mutex_lock(&led->lock);
 178 
 179         ret = lm3601x_read_faults(led);
 180         if (ret < 0)
 181                 goto out;
 182 
 183         if (led->led_mode == LM3601X_LED_TORCH)
 184                 led_mode_val = LM3601X_MODE_TORCH;
 185         else
 186                 led_mode_val = LM3601X_MODE_IR_DRV;
 187 
 188         if (brightness == LED_OFF) {
 189                 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
 190                                         led_mode_val, LED_OFF);
 191                 goto out;
 192         }
 193 
 194         ret = regmap_write(led->regmap, LM3601X_LED_TORCH_REG, brightness);
 195         if (ret < 0)
 196                 goto out;
 197 
 198         ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
 199                                 LM3601X_MODE_TORCH | LM3601X_MODE_IR_DRV,
 200                                 led_mode_val);
 201 out:
 202         mutex_unlock(&led->lock);
 203         return ret;
 204 }
 205 
 206 static int lm3601x_strobe_set(struct led_classdev_flash *fled_cdev,
 207                                 bool state)
 208 {
 209         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
 210         int timeout_reg_val;
 211         int current_timeout;
 212         int ret;
 213 
 214         mutex_lock(&led->lock);
 215 
 216         ret = regmap_read(led->regmap, LM3601X_CFG_REG, &current_timeout);
 217         if (ret < 0)
 218                 goto out;
 219 
 220         if (led->flash_timeout >= LM3601X_TIMEOUT_XOVER_US)
 221                 timeout_reg_val = led->flash_timeout / LM3601X_UPPER_STEP_US + 0x07;
 222         else
 223                 timeout_reg_val = led->flash_timeout / LM3601X_LOWER_STEP_US - 0x01;
 224 
 225         if (led->flash_timeout != current_timeout)
 226                 ret = regmap_update_bits(led->regmap, LM3601X_CFG_REG,
 227                                         LM3601X_TIMEOUT_MASK, timeout_reg_val);
 228 
 229         if (state)
 230                 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
 231                                         LM3601X_MODE_TORCH | LM3601X_MODE_IR_DRV,
 232                                         LM3601X_MODE_STROBE);
 233         else
 234                 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
 235                                         LM3601X_MODE_STROBE, LED_OFF);
 236 
 237         ret = lm3601x_read_faults(led);
 238 out:
 239         mutex_unlock(&led->lock);
 240         return ret;
 241 }
 242 
 243 static int lm3601x_flash_brightness_set(struct led_classdev_flash *fled_cdev,
 244                                         u32 brightness)
 245 {
 246         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
 247         u8 brightness_val;
 248         int ret;
 249 
 250         mutex_lock(&led->lock);
 251         ret = lm3601x_read_faults(led);
 252         if (ret < 0)
 253                 goto out;
 254 
 255         if (brightness == LED_OFF) {
 256                 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
 257                                         LM3601X_MODE_STROBE, LED_OFF);
 258                 goto out;
 259         }
 260 
 261         brightness_val = brightness / LM3601X_STROBE_REG_DIV;
 262 
 263         ret = regmap_write(led->regmap, LM3601X_LED_FLASH_REG, brightness_val);
 264 out:
 265         mutex_unlock(&led->lock);
 266         return ret;
 267 }
 268 
 269 static int lm3601x_flash_timeout_set(struct led_classdev_flash *fled_cdev,
 270                                 u32 timeout)
 271 {
 272         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
 273 
 274         mutex_lock(&led->lock);
 275 
 276         led->flash_timeout = timeout;
 277 
 278         mutex_unlock(&led->lock);
 279 
 280         return 0;
 281 }
 282 
 283 static int lm3601x_strobe_get(struct led_classdev_flash *fled_cdev, bool *state)
 284 {
 285         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
 286         int strobe_state;
 287         int ret;
 288 
 289         mutex_lock(&led->lock);
 290 
 291         ret = regmap_read(led->regmap, LM3601X_ENABLE_REG, &strobe_state);
 292         if (ret < 0)
 293                 goto out;
 294 
 295         *state = strobe_state & LM3601X_MODE_STROBE;
 296 
 297 out:
 298         mutex_unlock(&led->lock);
 299         return ret;
 300 }
 301 
 302 static int lm3601x_flash_fault_get(struct led_classdev_flash *fled_cdev,
 303                                 u32 *fault)
 304 {
 305         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
 306 
 307         lm3601x_read_faults(led);
 308 
 309         *fault = led->last_flag;
 310 
 311         return 0;
 312 }
 313 
 314 static const struct led_flash_ops flash_ops = {
 315         .flash_brightness_set   = lm3601x_flash_brightness_set,
 316         .strobe_set             = lm3601x_strobe_set,
 317         .strobe_get             = lm3601x_strobe_get,
 318         .timeout_set            = lm3601x_flash_timeout_set,
 319         .fault_get              = lm3601x_flash_fault_get,
 320 };
 321 
 322 static int lm3601x_register_leds(struct lm3601x_led *led,
 323                                  struct fwnode_handle *fwnode)
 324 {
 325         struct led_classdev *led_cdev;
 326         struct led_flash_setting *setting;
 327         struct led_init_data init_data = {};
 328 
 329         led->fled_cdev.ops = &flash_ops;
 330 
 331         setting = &led->fled_cdev.timeout;
 332         setting->min = LM3601X_MIN_TIMEOUT_US;
 333         setting->max = led->max_flash_timeout;
 334         setting->step = LM3601X_LOWER_STEP_US;
 335         setting->val = led->max_flash_timeout;
 336 
 337         setting = &led->fled_cdev.brightness;
 338         setting->min = LM3601X_MIN_STROBE_I_UA;
 339         setting->max = led->flash_current_max;
 340         setting->step = LM3601X_TORCH_REG_DIV;
 341         setting->val = led->flash_current_max;
 342 
 343         led_cdev = &led->fled_cdev.led_cdev;
 344         led_cdev->brightness_set_blocking = lm3601x_brightness_set;
 345         led_cdev->max_brightness = DIV_ROUND_UP(led->torch_current_max,
 346                                                 LM3601X_TORCH_REG_DIV);
 347         led_cdev->flags |= LED_DEV_CAP_FLASH;
 348 
 349         init_data.fwnode = fwnode;
 350         init_data.devicename = led->client->name;
 351         init_data.default_label = (led->led_mode == LM3601X_LED_TORCH) ?
 352                                         "torch" : "infrared";
 353 
 354         return led_classdev_flash_register_ext(&led->client->dev,
 355                                                 &led->fled_cdev, &init_data);
 356 }
 357 
 358 static int lm3601x_parse_node(struct lm3601x_led *led,
 359                               struct fwnode_handle **fwnode)
 360 {
 361         struct fwnode_handle *child = NULL;
 362         int ret = -ENODEV;
 363 
 364         child = device_get_next_child_node(&led->client->dev, child);
 365         if (!child) {
 366                 dev_err(&led->client->dev, "No LED Child node\n");
 367                 return ret;
 368         }
 369 
 370         ret = fwnode_property_read_u32(child, "reg", &led->led_mode);
 371         if (ret) {
 372                 dev_err(&led->client->dev, "reg DT property missing\n");
 373                 goto out_err;
 374         }
 375 
 376         if (led->led_mode > LM3601X_LED_TORCH ||
 377             led->led_mode < LM3601X_LED_IR) {
 378                 dev_warn(&led->client->dev, "Invalid led mode requested\n");
 379                 ret = -EINVAL;
 380                 goto out_err;
 381         }
 382 
 383         ret = fwnode_property_read_u32(child, "led-max-microamp",
 384                                         &led->torch_current_max);
 385         if (ret) {
 386                 dev_warn(&led->client->dev,
 387                         "led-max-microamp DT property missing\n");
 388                 goto out_err;
 389         }
 390 
 391         ret = fwnode_property_read_u32(child, "flash-max-microamp",
 392                                 &led->flash_current_max);
 393         if (ret) {
 394                 dev_warn(&led->client->dev,
 395                          "flash-max-microamp DT property missing\n");
 396                 goto out_err;
 397         }
 398 
 399         ret = fwnode_property_read_u32(child, "flash-max-timeout-us",
 400                                 &led->max_flash_timeout);
 401         if (ret) {
 402                 dev_warn(&led->client->dev,
 403                          "flash-max-timeout-us DT property missing\n");
 404                 goto out_err;
 405         }
 406 
 407         *fwnode = child;
 408 
 409 out_err:
 410         fwnode_handle_put(child);
 411         return ret;
 412 }
 413 
 414 static int lm3601x_probe(struct i2c_client *client)
 415 {
 416         struct lm3601x_led *led;
 417         struct fwnode_handle *fwnode;
 418         int ret;
 419 
 420         led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
 421         if (!led)
 422                 return -ENOMEM;
 423 
 424         led->client = client;
 425         i2c_set_clientdata(client, led);
 426 
 427         ret = lm3601x_parse_node(led, &fwnode);
 428         if (ret)
 429                 return -ENODEV;
 430 
 431         led->regmap = devm_regmap_init_i2c(client, &lm3601x_regmap);
 432         if (IS_ERR(led->regmap)) {
 433                 ret = PTR_ERR(led->regmap);
 434                 dev_err(&client->dev,
 435                         "Failed to allocate register map: %d\n", ret);
 436                 return ret;
 437         }
 438 
 439         mutex_init(&led->lock);
 440 
 441         return lm3601x_register_leds(led, fwnode);
 442 }
 443 
 444 static int lm3601x_remove(struct i2c_client *client)
 445 {
 446         struct lm3601x_led *led = i2c_get_clientdata(client);
 447 
 448         led_classdev_flash_unregister(&led->fled_cdev);
 449         mutex_destroy(&led->lock);
 450 
 451         return regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
 452                            LM3601X_ENABLE_MASK,
 453                            LM3601X_MODE_STANDBY);
 454 }
 455 
 456 static const struct i2c_device_id lm3601x_id[] = {
 457         { "LM36010", CHIP_LM36010 },
 458         { "LM36011", CHIP_LM36011 },
 459         { }
 460 };
 461 MODULE_DEVICE_TABLE(i2c, lm3601x_id);
 462 
 463 static const struct of_device_id of_lm3601x_leds_match[] = {
 464         { .compatible = "ti,lm36010", },
 465         { .compatible = "ti,lm36011", },
 466         { }
 467 };
 468 MODULE_DEVICE_TABLE(of, of_lm3601x_leds_match);
 469 
 470 static struct i2c_driver lm3601x_i2c_driver = {
 471         .driver = {
 472                 .name = "lm3601x",
 473                 .of_match_table = of_lm3601x_leds_match,
 474         },
 475         .probe_new = lm3601x_probe,
 476         .remove = lm3601x_remove,
 477         .id_table = lm3601x_id,
 478 };
 479 module_i2c_driver(lm3601x_i2c_driver);
 480 
 481 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3601X");
 482 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
 483 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */