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/
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 -
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
87 struct led_classdev_flash fled_cdev
;
88 struct i2c_client
*client
;
89 struct regmap
*regmap
;
92 unsigned int flash_timeout
;
93 unsigned int last_flag
;
95 u32 torch_current_max
;
96 u32 flash_current_max
;
97 u32 max_flash_timeout
;
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 },
109 static bool lm3601x_volatile_reg(struct device
*dev
, unsigned int reg
)
112 case LM3601X_FLAGS_REG
:
119 static const struct regmap_config lm3601x_regmap
= {
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
,
130 static struct lm3601x_led
*fled_cdev_to_led(struct led_classdev_flash
*fled_cdev
)
132 return container_of(fled_cdev
, struct lm3601x_led
, fled_cdev
);
135 static int lm3601x_read_faults(struct lm3601x_led
*led
)
140 ret
= regmap_read(led
->regmap
, LM3601X_FLAGS_REG
, &flags_val
);
146 if (flags_val
& LM36010_OVP_FAULT
)
147 led
->last_flag
|= LED_FAULT_OVER_VOLTAGE
;
149 if (flags_val
& (LM3601X_THERM_SHUTDOWN
| LM3601X_THERM_CURR
))
150 led
->last_flag
|= LED_FAULT_OVER_TEMPERATURE
;
152 if (flags_val
& LM3601X_SHORT_FAULT
)
153 led
->last_flag
|= LED_FAULT_SHORT_CIRCUIT
;
155 if (flags_val
& LM36010_CURR_LIMIT
)
156 led
->last_flag
|= LED_FAULT_OVER_CURRENT
;
158 if (flags_val
& LM3601X_UVLO_FAULT
)
159 led
->last_flag
|= LED_FAULT_UNDER_VOLTAGE
;
161 if (flags_val
& LM3601X_IVFM_TRIP
)
162 led
->last_flag
|= LED_FAULT_INPUT_VOLTAGE
;
164 if (flags_val
& LM3601X_THERM_SHUTDOWN
)
165 led
->last_flag
|= LED_FAULT_LED_OVER_TEMPERATURE
;
167 return led
->last_flag
;
170 static int lm3601x_brightness_set(struct led_classdev
*cdev
,
171 enum led_brightness brightness
)
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
;
177 mutex_lock(&led
->lock
);
179 ret
= lm3601x_read_faults(led
);
183 if (led
->led_mode
== LM3601X_LED_TORCH
)
184 led_mode_val
= LM3601X_MODE_TORCH
;
186 led_mode_val
= LM3601X_MODE_IR_DRV
;
188 if (brightness
== LED_OFF
) {
189 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
190 led_mode_val
, LED_OFF
);
194 ret
= regmap_write(led
->regmap
, LM3601X_LED_TORCH_REG
, brightness
);
198 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
199 LM3601X_MODE_TORCH
| LM3601X_MODE_IR_DRV
,
202 mutex_unlock(&led
->lock
);
206 static int lm3601x_strobe_set(struct led_classdev_flash
*fled_cdev
,
209 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
214 mutex_lock(&led
->lock
);
216 ret
= regmap_read(led
->regmap
, LM3601X_CFG_REG
, ¤t_timeout
);
220 if (led
->flash_timeout
>= LM3601X_TIMEOUT_XOVER_US
)
221 timeout_reg_val
= led
->flash_timeout
/ LM3601X_UPPER_STEP_US
+ 0x07;
223 timeout_reg_val
= led
->flash_timeout
/ LM3601X_LOWER_STEP_US
- 0x01;
225 if (led
->flash_timeout
!= current_timeout
)
226 ret
= regmap_update_bits(led
->regmap
, LM3601X_CFG_REG
,
227 LM3601X_TIMEOUT_MASK
, timeout_reg_val
);
230 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
231 LM3601X_MODE_TORCH
| LM3601X_MODE_IR_DRV
,
232 LM3601X_MODE_STROBE
);
234 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
235 LM3601X_MODE_STROBE
, LED_OFF
);
237 ret
= lm3601x_read_faults(led
);
239 mutex_unlock(&led
->lock
);
243 static int lm3601x_flash_brightness_set(struct led_classdev_flash
*fled_cdev
,
246 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
250 mutex_lock(&led
->lock
);
251 ret
= lm3601x_read_faults(led
);
255 if (brightness
== LED_OFF
) {
256 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
257 LM3601X_MODE_STROBE
, LED_OFF
);
261 brightness_val
= brightness
/ LM3601X_STROBE_REG_DIV
;
263 ret
= regmap_write(led
->regmap
, LM3601X_LED_FLASH_REG
, brightness_val
);
265 mutex_unlock(&led
->lock
);
269 static int lm3601x_flash_timeout_set(struct led_classdev_flash
*fled_cdev
,
272 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
274 mutex_lock(&led
->lock
);
276 led
->flash_timeout
= timeout
;
278 mutex_unlock(&led
->lock
);
283 static int lm3601x_strobe_get(struct led_classdev_flash
*fled_cdev
, bool *state
)
285 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
289 mutex_lock(&led
->lock
);
291 ret
= regmap_read(led
->regmap
, LM3601X_ENABLE_REG
, &strobe_state
);
295 *state
= strobe_state
& LM3601X_MODE_STROBE
;
298 mutex_unlock(&led
->lock
);
302 static int lm3601x_flash_fault_get(struct led_classdev_flash
*fled_cdev
,
305 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
307 lm3601x_read_faults(led
);
309 *fault
= led
->last_flag
;
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
,
322 static int lm3601x_register_leds(struct lm3601x_led
*led
,
323 struct fwnode_handle
*fwnode
)
325 struct led_classdev
*led_cdev
;
326 struct led_flash_setting
*setting
;
327 struct led_init_data init_data
= {};
329 led
->fled_cdev
.ops
= &flash_ops
;
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
;
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
;
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
;
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 ret
= fwnode_property_read_u32(child
, "flash-max-microamp",
391 &led
->flash_current_max
);
393 dev_warn(&led
->client
->dev
,
394 "flash-max-microamp DT property missing\n");
398 ret
= fwnode_property_read_u32(child
, "flash-max-timeout-us",
399 &led
->max_flash_timeout
);
401 dev_warn(&led
->client
->dev
,
402 "flash-max-timeout-us DT property missing\n");
409 fwnode_handle_put(child
);
413 static int lm3601x_probe(struct i2c_client
*client
)
415 struct lm3601x_led
*led
;
416 struct fwnode_handle
*fwnode
;
419 led
= devm_kzalloc(&client
->dev
, sizeof(*led
), GFP_KERNEL
);
423 led
->client
= client
;
424 i2c_set_clientdata(client
, led
);
426 ret
= lm3601x_parse_node(led
, &fwnode
);
430 led
->regmap
= devm_regmap_init_i2c(client
, &lm3601x_regmap
);
431 if (IS_ERR(led
->regmap
)) {
432 ret
= PTR_ERR(led
->regmap
);
433 dev_err(&client
->dev
,
434 "Failed to allocate register map: %d\n", ret
);
438 mutex_init(&led
->lock
);
440 return lm3601x_register_leds(led
, fwnode
);
443 static int lm3601x_remove(struct i2c_client
*client
)
445 struct lm3601x_led
*led
= i2c_get_clientdata(client
);
447 mutex_destroy(&led
->lock
);
449 return regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
451 LM3601X_MODE_STANDBY
);
454 static const struct i2c_device_id lm3601x_id
[] = {
455 { "LM36010", CHIP_LM36010
},
456 { "LM36011", CHIP_LM36011
},
459 MODULE_DEVICE_TABLE(i2c
, lm3601x_id
);
461 static const struct of_device_id of_lm3601x_leds_match
[] = {
462 { .compatible
= "ti,lm36010", },
463 { .compatible
= "ti,lm36011", },
466 MODULE_DEVICE_TABLE(of
, of_lm3601x_leds_match
);
468 static struct i2c_driver lm3601x_i2c_driver
= {
471 .of_match_table
= of_lm3601x_leds_match
,
473 .probe_new
= lm3601x_probe
,
474 .remove
= lm3601x_remove
,
475 .id_table
= lm3601x_id
,
477 module_i2c_driver(lm3601x_i2c_driver
);
479 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3601X");
480 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
481 MODULE_LICENSE("GPL v2");