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>
13 #include <uapi/linux/uleds.h>
15 #define LM3601X_LED_IR 0x0
16 #define LM3601X_LED_TORCH 0x1
19 #define LM3601X_ENABLE_REG 0x01
20 #define LM3601X_CFG_REG 0x02
21 #define LM3601X_LED_FLASH_REG 0x03
22 #define LM3601X_LED_TORCH_REG 0x04
23 #define LM3601X_FLAGS_REG 0x05
24 #define LM3601X_DEV_ID_REG 0x06
26 #define LM3601X_SW_RESET BIT(7)
28 /* Enable Mode bits */
29 #define LM3601X_MODE_STANDBY 0x00
30 #define LM3601X_MODE_IR_DRV BIT(0)
31 #define LM3601X_MODE_TORCH BIT(1)
32 #define LM3601X_MODE_STROBE (BIT(0) | BIT(1))
33 #define LM3601X_STRB_EN BIT(2)
34 #define LM3601X_STRB_EDGE_TRIG BIT(3)
35 #define LM3601X_IVFM_EN BIT(4)
37 #define LM36010_BOOST_LIMIT_28 BIT(5)
38 #define LM36010_BOOST_FREQ_4MHZ BIT(6)
39 #define LM36010_BOOST_MODE_PASS BIT(7)
42 #define LM3601X_FLASH_TIME_OUT BIT(0)
43 #define LM3601X_UVLO_FAULT BIT(1)
44 #define LM3601X_THERM_SHUTDOWN BIT(2)
45 #define LM3601X_THERM_CURR BIT(3)
46 #define LM36010_CURR_LIMIT BIT(4)
47 #define LM3601X_SHORT_FAULT BIT(5)
48 #define LM3601X_IVFM_TRIP BIT(6)
49 #define LM36010_OVP_FAULT BIT(7)
51 #define LM3601X_MAX_TORCH_I_UA 376000
52 #define LM3601X_MIN_TORCH_I_UA 2400
53 #define LM3601X_TORCH_REG_DIV 2965
55 #define LM3601X_MAX_STROBE_I_UA 1500000
56 #define LM3601X_MIN_STROBE_I_UA 11000
57 #define LM3601X_STROBE_REG_DIV 11800
59 #define LM3601X_TIMEOUT_MASK 0x1e
60 #define LM3601X_ENABLE_MASK (LM3601X_MODE_IR_DRV | LM3601X_MODE_TORCH)
62 #define LM3601X_LOWER_STEP_US 40000
63 #define LM3601X_UPPER_STEP_US 200000
64 #define LM3601X_MIN_TIMEOUT_US 40000
65 #define LM3601X_MAX_TIMEOUT_US 1600000
66 #define LM3601X_TIMEOUT_XOVER_US 400000
74 * struct lm3601x_led -
75 * @fled_cdev: flash LED class device pointer
76 * @client: Pointer to the I2C client
77 * @regmap: Devices register map
78 * @lock: Lock for reading/writing the device
79 * @led_name: LED label for the Torch or IR LED
80 * @flash_timeout: the timeout for the flash
81 * @last_flag: last known flags register value
82 * @torch_current_max: maximum current for the torch
83 * @flash_current_max: maximum current for the flash
84 * @max_flash_timeout: maximum timeout for the flash
85 * @led_mode: The mode to enable either IR or Torch
88 struct led_classdev_flash fled_cdev
;
89 struct i2c_client
*client
;
90 struct regmap
*regmap
;
93 char led_name
[LED_MAX_NAME_SIZE
];
95 unsigned int flash_timeout
;
96 unsigned int last_flag
;
98 u32 torch_current_max
;
99 u32 flash_current_max
;
100 u32 max_flash_timeout
;
105 static const struct reg_default lm3601x_regmap_defs
[] = {
106 { LM3601X_ENABLE_REG
, 0x20 },
107 { LM3601X_CFG_REG
, 0x15 },
108 { LM3601X_LED_FLASH_REG
, 0x00 },
109 { LM3601X_LED_TORCH_REG
, 0x00 },
112 static bool lm3601x_volatile_reg(struct device
*dev
, unsigned int reg
)
115 case LM3601X_FLAGS_REG
:
122 static const struct regmap_config lm3601x_regmap
= {
126 .max_register
= LM3601X_DEV_ID_REG
,
127 .reg_defaults
= lm3601x_regmap_defs
,
128 .num_reg_defaults
= ARRAY_SIZE(lm3601x_regmap_defs
),
129 .cache_type
= REGCACHE_RBTREE
,
130 .volatile_reg
= lm3601x_volatile_reg
,
133 static struct lm3601x_led
*fled_cdev_to_led(struct led_classdev_flash
*fled_cdev
)
135 return container_of(fled_cdev
, struct lm3601x_led
, fled_cdev
);
138 static int lm3601x_read_faults(struct lm3601x_led
*led
)
143 ret
= regmap_read(led
->regmap
, LM3601X_FLAGS_REG
, &flags_val
);
149 if (flags_val
& LM36010_OVP_FAULT
)
150 led
->last_flag
|= LED_FAULT_OVER_VOLTAGE
;
152 if (flags_val
& (LM3601X_THERM_SHUTDOWN
| LM3601X_THERM_CURR
))
153 led
->last_flag
|= LED_FAULT_OVER_TEMPERATURE
;
155 if (flags_val
& LM3601X_SHORT_FAULT
)
156 led
->last_flag
|= LED_FAULT_SHORT_CIRCUIT
;
158 if (flags_val
& LM36010_CURR_LIMIT
)
159 led
->last_flag
|= LED_FAULT_OVER_CURRENT
;
161 if (flags_val
& LM3601X_UVLO_FAULT
)
162 led
->last_flag
|= LED_FAULT_UNDER_VOLTAGE
;
164 if (flags_val
& LM3601X_IVFM_TRIP
)
165 led
->last_flag
|= LED_FAULT_INPUT_VOLTAGE
;
167 if (flags_val
& LM3601X_THERM_SHUTDOWN
)
168 led
->last_flag
|= LED_FAULT_LED_OVER_TEMPERATURE
;
170 return led
->last_flag
;
173 static int lm3601x_brightness_set(struct led_classdev
*cdev
,
174 enum led_brightness brightness
)
176 struct led_classdev_flash
*fled_cdev
= lcdev_to_flcdev(cdev
);
177 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
178 int ret
, led_mode_val
;
180 mutex_lock(&led
->lock
);
182 ret
= lm3601x_read_faults(led
);
186 if (led
->led_mode
== LM3601X_LED_TORCH
)
187 led_mode_val
= LM3601X_MODE_TORCH
;
189 led_mode_val
= LM3601X_MODE_IR_DRV
;
191 if (brightness
== LED_OFF
) {
192 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
193 led_mode_val
, LED_OFF
);
197 ret
= regmap_write(led
->regmap
, LM3601X_LED_TORCH_REG
, brightness
);
201 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
202 LM3601X_MODE_TORCH
| LM3601X_MODE_IR_DRV
,
205 mutex_unlock(&led
->lock
);
209 static int lm3601x_strobe_set(struct led_classdev_flash
*fled_cdev
,
212 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
217 mutex_lock(&led
->lock
);
219 ret
= regmap_read(led
->regmap
, LM3601X_CFG_REG
, ¤t_timeout
);
223 if (led
->flash_timeout
>= LM3601X_TIMEOUT_XOVER_US
)
224 timeout_reg_val
= led
->flash_timeout
/ LM3601X_UPPER_STEP_US
+ 0x07;
226 timeout_reg_val
= led
->flash_timeout
/ LM3601X_LOWER_STEP_US
- 0x01;
228 if (led
->flash_timeout
!= current_timeout
)
229 ret
= regmap_update_bits(led
->regmap
, LM3601X_CFG_REG
,
230 LM3601X_TIMEOUT_MASK
, timeout_reg_val
);
233 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
234 LM3601X_MODE_TORCH
| LM3601X_MODE_IR_DRV
,
235 LM3601X_MODE_STROBE
);
237 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
238 LM3601X_MODE_STROBE
, LED_OFF
);
240 ret
= lm3601x_read_faults(led
);
242 mutex_unlock(&led
->lock
);
246 static int lm3601x_flash_brightness_set(struct led_classdev_flash
*fled_cdev
,
249 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
253 mutex_lock(&led
->lock
);
254 ret
= lm3601x_read_faults(led
);
258 if (brightness
== LED_OFF
) {
259 ret
= regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
260 LM3601X_MODE_STROBE
, LED_OFF
);
264 brightness_val
= brightness
/ LM3601X_STROBE_REG_DIV
;
266 ret
= regmap_write(led
->regmap
, LM3601X_LED_FLASH_REG
, brightness_val
);
268 mutex_unlock(&led
->lock
);
272 static int lm3601x_flash_timeout_set(struct led_classdev_flash
*fled_cdev
,
275 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
277 mutex_lock(&led
->lock
);
279 led
->flash_timeout
= timeout
;
281 mutex_unlock(&led
->lock
);
286 static int lm3601x_strobe_get(struct led_classdev_flash
*fled_cdev
, bool *state
)
288 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
292 mutex_lock(&led
->lock
);
294 ret
= regmap_read(led
->regmap
, LM3601X_ENABLE_REG
, &strobe_state
);
298 *state
= strobe_state
& LM3601X_MODE_STROBE
;
301 mutex_unlock(&led
->lock
);
305 static int lm3601x_flash_fault_get(struct led_classdev_flash
*fled_cdev
,
308 struct lm3601x_led
*led
= fled_cdev_to_led(fled_cdev
);
310 lm3601x_read_faults(led
);
312 *fault
= led
->last_flag
;
317 static const struct led_flash_ops flash_ops
= {
318 .flash_brightness_set
= lm3601x_flash_brightness_set
,
319 .strobe_set
= lm3601x_strobe_set
,
320 .strobe_get
= lm3601x_strobe_get
,
321 .timeout_set
= lm3601x_flash_timeout_set
,
322 .fault_get
= lm3601x_flash_fault_get
,
325 static int lm3601x_register_leds(struct lm3601x_led
*led
)
327 struct led_classdev
*led_cdev
;
328 struct led_flash_setting
*setting
;
330 led
->fled_cdev
.ops
= &flash_ops
;
332 setting
= &led
->fled_cdev
.timeout
;
333 setting
->min
= LM3601X_MIN_TIMEOUT_US
;
334 setting
->max
= led
->max_flash_timeout
;
335 setting
->step
= LM3601X_LOWER_STEP_US
;
336 setting
->val
= led
->max_flash_timeout
;
338 setting
= &led
->fled_cdev
.brightness
;
339 setting
->min
= LM3601X_MIN_STROBE_I_UA
;
340 setting
->max
= led
->flash_current_max
;
341 setting
->step
= LM3601X_TORCH_REG_DIV
;
342 setting
->val
= led
->flash_current_max
;
344 led_cdev
= &led
->fled_cdev
.led_cdev
;
345 led_cdev
->name
= led
->led_name
;
346 led_cdev
->brightness_set_blocking
= lm3601x_brightness_set
;
347 led_cdev
->max_brightness
= DIV_ROUND_UP(led
->torch_current_max
,
348 LM3601X_TORCH_REG_DIV
);
349 led_cdev
->flags
|= LED_DEV_CAP_FLASH
;
351 return led_classdev_flash_register(&led
->client
->dev
, &led
->fled_cdev
);
354 static int lm3601x_parse_node(struct lm3601x_led
*led
)
356 struct fwnode_handle
*child
= NULL
;
360 child
= device_get_next_child_node(&led
->client
->dev
, child
);
362 dev_err(&led
->client
->dev
, "No LED Child node\n");
366 ret
= fwnode_property_read_u32(child
, "reg", &led
->led_mode
);
368 dev_err(&led
->client
->dev
, "reg DT property missing\n");
372 if (led
->led_mode
> LM3601X_LED_TORCH
||
373 led
->led_mode
< LM3601X_LED_IR
) {
374 dev_warn(&led
->client
->dev
, "Invalid led mode requested\n");
379 ret
= fwnode_property_read_string(child
, "label", &name
);
381 if (led
->led_mode
== LM3601X_LED_TORCH
)
387 snprintf(led
->led_name
, sizeof(led
->led_name
),
388 "%s:%s", led
->client
->name
, name
);
390 ret
= fwnode_property_read_u32(child
, "led-max-microamp",
391 &led
->torch_current_max
);
393 dev_warn(&led
->client
->dev
,
394 "led-max-microamp DT property missing\n");
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");
415 fwnode_handle_put(child
);
419 static int lm3601x_probe(struct i2c_client
*client
)
421 struct lm3601x_led
*led
;
424 led
= devm_kzalloc(&client
->dev
, sizeof(*led
), GFP_KERNEL
);
428 led
->client
= client
;
429 i2c_set_clientdata(client
, led
);
431 ret
= lm3601x_parse_node(led
);
435 led
->regmap
= devm_regmap_init_i2c(client
, &lm3601x_regmap
);
436 if (IS_ERR(led
->regmap
)) {
437 ret
= PTR_ERR(led
->regmap
);
438 dev_err(&client
->dev
,
439 "Failed to allocate register map: %d\n", ret
);
443 mutex_init(&led
->lock
);
445 return lm3601x_register_leds(led
);
448 static int lm3601x_remove(struct i2c_client
*client
)
450 struct lm3601x_led
*led
= i2c_get_clientdata(client
);
452 led_classdev_flash_unregister(&led
->fled_cdev
);
453 mutex_destroy(&led
->lock
);
455 return regmap_update_bits(led
->regmap
, LM3601X_ENABLE_REG
,
457 LM3601X_MODE_STANDBY
);
460 static const struct i2c_device_id lm3601x_id
[] = {
461 { "LM36010", CHIP_LM36010
},
462 { "LM36011", CHIP_LM36011
},
465 MODULE_DEVICE_TABLE(i2c
, lm3601x_id
);
467 static const struct of_device_id of_lm3601x_leds_match
[] = {
468 { .compatible
= "ti,lm36010", },
469 { .compatible
= "ti,lm36011", },
472 MODULE_DEVICE_TABLE(of
, of_lm3601x_leds_match
);
474 static struct i2c_driver lm3601x_i2c_driver
= {
477 .of_match_table
= of_lm3601x_leds_match
,
479 .probe_new
= lm3601x_probe
,
480 .remove
= lm3601x_remove
,
481 .id_table
= lm3601x_id
,
483 module_i2c_driver(lm3601x_i2c_driver
);
485 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3601X");
486 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
487 MODULE_LICENSE("GPL v2");