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 - https://www.ti.com/
6 #include <linux/delay.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>
14 #define LM3601X_LED_IR 0x0
15 #define LM3601X_LED_TORCH 0x1
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
25 #define LM3601X_SW_RESET BIT(7)
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)
36 #define LM36010_BOOST_LIMIT_28 BIT(5)
37 #define LM36010_BOOST_FREQ_4MHZ BIT(6)
38 #define LM36010_BOOST_MODE_PASS BIT(7)
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)
50 #define LM3601X_MAX_TORCH_I_UA 376000
51 #define LM3601X_MIN_TORCH_I_UA 2400
52 #define LM3601X_TORCH_REG_DIV 2965
54 #define LM3601X_MAX_STROBE_I_UA 1500000
55 #define LM3601X_MIN_STROBE_I_UA 11000
56 #define LM3601X_STROBE_REG_DIV 11800
58 #define LM3601X_TIMEOUT_MASK 0x1e
59 #define LM3601X_ENABLE_MASK (LM3601X_MODE_IR_DRV | LM3601X_MODE_TORCH)
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
73 * struct lm3601x_led - private lm3601x LED data
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 * @flash_timeout: the timeout for the flash
79 * @last_flag: last known flags register value
80 * @torch_current_max: maximum current for the torch
81 * @flash_current_max: maximum current for the flash
82 * @max_flash_timeout: maximum timeout for the flash
83 * @led_mode: The mode to enable either IR or Torch
86 struct led_classdev_flash fled_cdev
;
87 struct i2c_client
*client
;
88 struct regmap
*regmap
;
91 unsigned int flash_timeout
;
92 unsigned int last_flag
;
94 u32 torch_current_max
;
95 u32 flash_current_max
;
96 u32 max_flash_timeout
;
101 static const struct reg_default lm3601x_regmap_defs
[] = {
102 { LM3601X_ENABLE_REG
, 0x20 },
103 { LM3601X_CFG_REG
, 0x15 },
104 { LM3601X_LED_FLASH_REG
, 0x00 },
105 { LM3601X_LED_TORCH_REG
, 0x00 },
108 static bool lm3601x_volatile_reg(struct device
*dev
, unsigned int reg
)
111 case LM3601X_FLAGS_REG
:
118 static const struct regmap_config lm3601x_regmap
= {
122 .max_register
= LM3601X_DEV_ID_REG
,
123 .reg_defaults
= lm3601x_regmap_defs
,
124 .num_reg_defaults
= ARRAY_SIZE(lm3601x_regmap_defs
),
125 .cache_type
= REGCACHE_MAPLE
,
126 .volatile_reg
= lm3601x_volatile_reg
,
129 static struct lm3601x_led
*fled_cdev_to_led(struct led_classdev_flash
*fled_cdev
)
131 return container_of(fled_cdev
, struct lm3601x_led
, fled_cdev
);
134 static int lm3601x_read_faults(struct lm3601x_led
*led
)
139 ret
= regmap_read(led
->regmap
, LM3601X_FLAGS_REG
, &flags_val
);
145 if (flags_val
& LM36010_OVP_FAULT
)
146 led
->last_flag
|= LED_FAULT_OVER_VOLTAGE
;
148 if (flags_val
& (LM3601X_THERM_SHUTDOWN
| LM3601X_THERM_CURR
))
149 led
->last_flag
|= LED_FAULT_OVER_TEMPERATURE
;
151 if (flags_val
& LM3601X_SHORT_FAULT
)
152 led
->last_flag
|= LED_FAULT_SHORT_CIRCUIT
;
154 if (flags_val
& LM36010_CURR_LIMIT
)
155 led
->last_flag
|= LED_FAULT_OVER_CURRENT
;
157 if (flags_val
& LM3601X_UVLO_FAULT
)
158 led
->last_flag
|= LED_FAULT_UNDER_VOLTAGE
;
160 if (flags_val
& LM3601X_IVFM_TRIP
)
161 led
->last_flag
|= LED_FAULT_INPUT_VOLTAGE
;
163 if (flags_val
& LM3601X_THERM_SHUTDOWN
)
164 led
->last_flag
|= LED_FAULT_LED_OVER_TEMPERATURE
;
166 return led
->last_flag
;
169 static int lm3601x_brightness_set(struct led_classdev
*cdev
,
170 enum led_brightness brightness
)
172 struct led_classdev_flash
*fled_cdev
= lcdev_to_flcdev(cdev
);
173 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
174 int ret
, led_mode_val
;
176 mutex_lock(&led
->lock
);
178 ret
= lm3601x_read_faults(led
);
182 if (led
->led_mode
== LM3601X_LED_TORCH
)
183 led_mode_val
= LM3601X_MODE_TORCH
;
185 led_mode_val
= LM3601X_MODE_IR_DRV
;
187 if (brightness
== LED_OFF
) {
188 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
189 led_mode_val
, LED_OFF
);
193 ret
= regmap_write(led
->regmap
, LM3601X_LED_TORCH_REG
, brightness
- 1);
197 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
198 LM3601X_MODE_TORCH
| LM3601X_MODE_IR_DRV
,
201 mutex_unlock(&led
->lock
);
205 static int lm3601x_strobe_set(struct led_classdev_flash
*fled_cdev
,
208 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
213 mutex_lock(&led
->lock
);
215 ret
= regmap_read(led
->regmap
, LM3601X_CFG_REG
, ¤t_timeout
);
219 if (led
->flash_timeout
>= LM3601X_TIMEOUT_XOVER_US
)
220 timeout_reg_val
= led
->flash_timeout
/ LM3601X_UPPER_STEP_US
+ 0x07;
222 timeout_reg_val
= led
->flash_timeout
/ LM3601X_LOWER_STEP_US
- 0x01;
224 if (led
->flash_timeout
!= current_timeout
)
225 ret
= regmap_update_bits(led
->regmap
, LM3601X_CFG_REG
,
226 LM3601X_TIMEOUT_MASK
, timeout_reg_val
);
229 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
230 LM3601X_MODE_TORCH
| LM3601X_MODE_IR_DRV
,
231 LM3601X_MODE_STROBE
);
233 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
234 LM3601X_MODE_STROBE
, LED_OFF
);
236 ret
= lm3601x_read_faults(led
);
238 mutex_unlock(&led
->lock
);
242 static int lm3601x_flash_brightness_set(struct led_classdev_flash
*fled_cdev
,
245 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
249 mutex_lock(&led
->lock
);
250 ret
= lm3601x_read_faults(led
);
254 if (brightness
== LED_OFF
) {
255 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
256 LM3601X_MODE_STROBE
, LED_OFF
);
260 brightness_val
= brightness
/ LM3601X_STROBE_REG_DIV
;
262 ret
= regmap_write(led
->regmap
, LM3601X_LED_FLASH_REG
, brightness_val
);
264 mutex_unlock(&led
->lock
);
268 static int lm3601x_flash_timeout_set(struct led_classdev_flash
*fled_cdev
,
271 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
273 mutex_lock(&led
->lock
);
275 led
->flash_timeout
= timeout
;
277 mutex_unlock(&led
->lock
);
282 static int lm3601x_strobe_get(struct led_classdev_flash
*fled_cdev
, bool *state
)
284 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
288 mutex_lock(&led
->lock
);
290 ret
= regmap_read(led
->regmap
, LM3601X_ENABLE_REG
, &strobe_state
);
294 *state
= strobe_state
& LM3601X_MODE_STROBE
;
297 mutex_unlock(&led
->lock
);
301 static int lm3601x_flash_fault_get(struct led_classdev_flash
*fled_cdev
,
304 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
306 lm3601x_read_faults(led
);
308 *fault
= led
->last_flag
;
313 static const struct led_flash_ops flash_ops
= {
314 .flash_brightness_set
= lm3601x_flash_brightness_set
,
315 .strobe_set
= lm3601x_strobe_set
,
316 .strobe_get
= lm3601x_strobe_get
,
317 .timeout_set
= lm3601x_flash_timeout_set
,
318 .fault_get
= lm3601x_flash_fault_get
,
321 static int lm3601x_register_leds(struct lm3601x_led
*led
,
322 struct fwnode_handle
*fwnode
)
324 struct led_classdev
*led_cdev
;
325 struct led_flash_setting
*setting
;
326 struct led_init_data init_data
= {};
328 led
->fled_cdev
.ops
= &flash_ops
;
330 setting
= &led
->fled_cdev
.timeout
;
331 setting
->min
= LM3601X_MIN_TIMEOUT_US
;
332 setting
->max
= led
->max_flash_timeout
;
333 setting
->step
= LM3601X_LOWER_STEP_US
;
334 setting
->val
= led
->max_flash_timeout
;
336 setting
= &led
->fled_cdev
.brightness
;
337 setting
->min
= LM3601X_MIN_STROBE_I_UA
;
338 setting
->max
= led
->flash_current_max
;
339 setting
->step
= LM3601X_TORCH_REG_DIV
;
340 setting
->val
= led
->flash_current_max
;
342 led_cdev
= &led
->fled_cdev
.led_cdev
;
343 led_cdev
->brightness_set_blocking
= lm3601x_brightness_set
;
344 led_cdev
->max_brightness
=
345 DIV_ROUND_UP(led
->torch_current_max
- LM3601X_MIN_TORCH_I_UA
+ 1,
346 LM3601X_TORCH_REG_DIV
);
347 led_cdev
->flags
|= LED_DEV_CAP_FLASH
;
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 return devm_led_classdev_flash_register_ext(&led
->client
->dev
,
354 &led
->fled_cdev
, &init_data
);
357 static int lm3601x_parse_node(struct lm3601x_led
*led
,
358 struct fwnode_handle
**fwnode
)
360 struct fwnode_handle
*child
= NULL
;
363 child
= device_get_next_child_node(&led
->client
->dev
, child
);
365 dev_err(&led
->client
->dev
, "No LED Child node\n");
369 ret
= fwnode_property_read_u32(child
, "reg", &led
->led_mode
);
371 dev_err(&led
->client
->dev
, "reg DT property missing\n");
375 if (led
->led_mode
> LM3601X_LED_TORCH
||
376 led
->led_mode
< LM3601X_LED_IR
) {
377 dev_warn(&led
->client
->dev
, "Invalid led mode requested\n");
382 ret
= fwnode_property_read_u32(child
, "led-max-microamp",
383 &led
->torch_current_max
);
385 dev_warn(&led
->client
->dev
,
386 "led-max-microamp DT property missing\n");
390 if (led
->torch_current_max
> LM3601X_MAX_TORCH_I_UA
) {
391 dev_warn(&led
->client
->dev
,
392 "Max torch current set too high (%d vs %d)\n",
393 led
->torch_current_max
,
394 LM3601X_MAX_TORCH_I_UA
);
395 led
->torch_current_max
= LM3601X_MAX_TORCH_I_UA
;
398 ret
= fwnode_property_read_u32(child
, "flash-max-microamp",
399 &led
->flash_current_max
);
401 dev_warn(&led
->client
->dev
,
402 "flash-max-microamp DT property missing\n");
406 ret
= fwnode_property_read_u32(child
, "flash-max-timeout-us",
407 &led
->max_flash_timeout
);
409 dev_warn(&led
->client
->dev
,
410 "flash-max-timeout-us DT property missing\n");
417 fwnode_handle_put(child
);
421 static int lm3601x_probe(struct i2c_client
*client
)
423 struct lm3601x_led
*led
;
424 struct fwnode_handle
*fwnode
;
427 led
= devm_kzalloc(&client
->dev
, sizeof(*led
), GFP_KERNEL
);
431 led
->client
= client
;
432 i2c_set_clientdata(client
, led
);
434 ret
= lm3601x_parse_node(led
, &fwnode
);
438 led
->regmap
= devm_regmap_init_i2c(client
, &lm3601x_regmap
);
439 if (IS_ERR(led
->regmap
)) {
440 ret
= PTR_ERR(led
->regmap
);
441 dev_err(&client
->dev
,
442 "Failed to allocate register map: %d\n", ret
);
446 ret
= regmap_write(led
->regmap
, LM3601X_DEV_ID_REG
, LM3601X_SW_RESET
);
448 dev_warn(&client
->dev
, "Failed to reset the LED controller\n");
450 mutex_init(&led
->lock
);
452 return lm3601x_register_leds(led
, fwnode
);
455 static void lm3601x_remove(struct i2c_client
*client
)
457 struct lm3601x_led
*led
= i2c_get_clientdata(client
);
460 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
461 LM3601X_ENABLE_MASK
, LM3601X_MODE_STANDBY
);
463 dev_warn(&client
->dev
,
464 "Failed to put into standby (%pe)\n", ERR_PTR(ret
));
467 static const struct i2c_device_id lm3601x_id
[] = {
468 { "LM36010", CHIP_LM36010
},
469 { "LM36011", CHIP_LM36011
},
472 MODULE_DEVICE_TABLE(i2c
, lm3601x_id
);
474 static const struct of_device_id of_lm3601x_leds_match
[] = {
475 { .compatible
= "ti,lm36010", },
476 { .compatible
= "ti,lm36011", },
479 MODULE_DEVICE_TABLE(of
, of_lm3601x_leds_match
);
481 static struct i2c_driver lm3601x_i2c_driver
= {
484 .of_match_table
= of_lm3601x_leds_match
,
486 .probe
= lm3601x_probe
,
487 .remove
= lm3601x_remove
,
488 .id_table
= lm3601x_id
,
490 module_i2c_driver(lm3601x_i2c_driver
);
492 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3601X");
493 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
494 MODULE_LICENSE("GPL v2");