]> Git Repo - linux.git/blob - drivers/leds/flash/leds-lm3601x.c
x86/kaslr: Expose and use the end of the physical memory address space
[linux.git] / drivers / leds / flash / leds-lm3601x.c
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/
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 - 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
84  */
85 struct lm3601x_led {
86         struct led_classdev_flash fled_cdev;
87         struct i2c_client *client;
88         struct regmap *regmap;
89         struct mutex lock;
90
91         unsigned int flash_timeout;
92         unsigned int last_flag;
93
94         u32 torch_current_max;
95         u32 flash_current_max;
96         u32 max_flash_timeout;
97
98         u32 led_mode;
99 };
100
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 },
106 };
107
108 static bool lm3601x_volatile_reg(struct device *dev, unsigned int reg)
109 {
110         switch (reg) {
111         case LM3601X_FLAGS_REG:
112                 return true;
113         default:
114                 return false;
115         }
116 }
117
118 static const struct regmap_config lm3601x_regmap = {
119         .reg_bits = 8,
120         .val_bits = 8,
121
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,
127 };
128
129 static struct lm3601x_led *fled_cdev_to_led(struct led_classdev_flash *fled_cdev)
130 {
131         return container_of(fled_cdev, struct lm3601x_led, fled_cdev);
132 }
133
134 static int lm3601x_read_faults(struct lm3601x_led *led)
135 {
136         int flags_val;
137         int ret;
138
139         ret = regmap_read(led->regmap, LM3601X_FLAGS_REG, &flags_val);
140         if (ret < 0)
141                 return -EIO;
142
143         led->last_flag = 0;
144
145         if (flags_val & LM36010_OVP_FAULT)
146                 led->last_flag |= LED_FAULT_OVER_VOLTAGE;
147
148         if (flags_val & (LM3601X_THERM_SHUTDOWN | LM3601X_THERM_CURR))
149                 led->last_flag |= LED_FAULT_OVER_TEMPERATURE;
150
151         if (flags_val & LM3601X_SHORT_FAULT)
152                 led->last_flag |= LED_FAULT_SHORT_CIRCUIT;
153
154         if (flags_val & LM36010_CURR_LIMIT)
155                 led->last_flag |= LED_FAULT_OVER_CURRENT;
156
157         if (flags_val & LM3601X_UVLO_FAULT)
158                 led->last_flag |= LED_FAULT_UNDER_VOLTAGE;
159
160         if (flags_val & LM3601X_IVFM_TRIP)
161                 led->last_flag |= LED_FAULT_INPUT_VOLTAGE;
162
163         if (flags_val & LM3601X_THERM_SHUTDOWN)
164                 led->last_flag |= LED_FAULT_LED_OVER_TEMPERATURE;
165
166         return led->last_flag;
167 }
168
169 static int lm3601x_brightness_set(struct led_classdev *cdev,
170                                         enum led_brightness brightness)
171 {
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;
175
176         mutex_lock(&led->lock);
177
178         ret = lm3601x_read_faults(led);
179         if (ret < 0)
180                 goto out;
181
182         if (led->led_mode == LM3601X_LED_TORCH)
183                 led_mode_val = LM3601X_MODE_TORCH;
184         else
185                 led_mode_val = LM3601X_MODE_IR_DRV;
186
187         if (brightness == LED_OFF) {
188                 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
189                                         led_mode_val, LED_OFF);
190                 goto out;
191         }
192
193         ret = regmap_write(led->regmap, LM3601X_LED_TORCH_REG, brightness);
194         if (ret < 0)
195                 goto out;
196
197         ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
198                                 LM3601X_MODE_TORCH | LM3601X_MODE_IR_DRV,
199                                 led_mode_val);
200 out:
201         mutex_unlock(&led->lock);
202         return ret;
203 }
204
205 static int lm3601x_strobe_set(struct led_classdev_flash *fled_cdev,
206                                 bool state)
207 {
208         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
209         int timeout_reg_val;
210         int current_timeout;
211         int ret;
212
213         mutex_lock(&led->lock);
214
215         ret = regmap_read(led->regmap, LM3601X_CFG_REG, &current_timeout);
216         if (ret < 0)
217                 goto out;
218
219         if (led->flash_timeout >= LM3601X_TIMEOUT_XOVER_US)
220                 timeout_reg_val = led->flash_timeout / LM3601X_UPPER_STEP_US + 0x07;
221         else
222                 timeout_reg_val = led->flash_timeout / LM3601X_LOWER_STEP_US - 0x01;
223
224         if (led->flash_timeout != current_timeout)
225                 ret = regmap_update_bits(led->regmap, LM3601X_CFG_REG,
226                                         LM3601X_TIMEOUT_MASK, timeout_reg_val);
227
228         if (state)
229                 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
230                                         LM3601X_MODE_TORCH | LM3601X_MODE_IR_DRV,
231                                         LM3601X_MODE_STROBE);
232         else
233                 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
234                                         LM3601X_MODE_STROBE, LED_OFF);
235
236         ret = lm3601x_read_faults(led);
237 out:
238         mutex_unlock(&led->lock);
239         return ret;
240 }
241
242 static int lm3601x_flash_brightness_set(struct led_classdev_flash *fled_cdev,
243                                         u32 brightness)
244 {
245         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
246         u8 brightness_val;
247         int ret;
248
249         mutex_lock(&led->lock);
250         ret = lm3601x_read_faults(led);
251         if (ret < 0)
252                 goto out;
253
254         if (brightness == LED_OFF) {
255                 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
256                                         LM3601X_MODE_STROBE, LED_OFF);
257                 goto out;
258         }
259
260         brightness_val = brightness / LM3601X_STROBE_REG_DIV;
261
262         ret = regmap_write(led->regmap, LM3601X_LED_FLASH_REG, brightness_val);
263 out:
264         mutex_unlock(&led->lock);
265         return ret;
266 }
267
268 static int lm3601x_flash_timeout_set(struct led_classdev_flash *fled_cdev,
269                                 u32 timeout)
270 {
271         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
272
273         mutex_lock(&led->lock);
274
275         led->flash_timeout = timeout;
276
277         mutex_unlock(&led->lock);
278
279         return 0;
280 }
281
282 static int lm3601x_strobe_get(struct led_classdev_flash *fled_cdev, bool *state)
283 {
284         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
285         int strobe_state;
286         int ret;
287
288         mutex_lock(&led->lock);
289
290         ret = regmap_read(led->regmap, LM3601X_ENABLE_REG, &strobe_state);
291         if (ret < 0)
292                 goto out;
293
294         *state = strobe_state & LM3601X_MODE_STROBE;
295
296 out:
297         mutex_unlock(&led->lock);
298         return ret;
299 }
300
301 static int lm3601x_flash_fault_get(struct led_classdev_flash *fled_cdev,
302                                 u32 *fault)
303 {
304         struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
305
306         lm3601x_read_faults(led);
307
308         *fault = led->last_flag;
309
310         return 0;
311 }
312
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,
319 };
320
321 static int lm3601x_register_leds(struct lm3601x_led *led,
322                                  struct fwnode_handle *fwnode)
323 {
324         struct led_classdev *led_cdev;
325         struct led_flash_setting *setting;
326         struct led_init_data init_data = {};
327
328         led->fled_cdev.ops = &flash_ops;
329
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;
335
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;
341
342         led_cdev = &led->fled_cdev.led_cdev;
343         led_cdev->brightness_set_blocking = lm3601x_brightness_set;
344         led_cdev->max_brightness = DIV_ROUND_UP(led->torch_current_max,
345                                                 LM3601X_TORCH_REG_DIV);
346         led_cdev->flags |= LED_DEV_CAP_FLASH;
347
348         init_data.fwnode = fwnode;
349         init_data.devicename = led->client->name;
350         init_data.default_label = (led->led_mode == LM3601X_LED_TORCH) ?
351                                         "torch" : "infrared";
352         return devm_led_classdev_flash_register_ext(&led->client->dev,
353                                                 &led->fled_cdev, &init_data);
354 }
355
356 static int lm3601x_parse_node(struct lm3601x_led *led,
357                               struct fwnode_handle **fwnode)
358 {
359         struct fwnode_handle *child = NULL;
360         int ret = -ENODEV;
361
362         child = device_get_next_child_node(&led->client->dev, child);
363         if (!child) {
364                 dev_err(&led->client->dev, "No LED Child node\n");
365                 return ret;
366         }
367
368         ret = fwnode_property_read_u32(child, "reg", &led->led_mode);
369         if (ret) {
370                 dev_err(&led->client->dev, "reg DT property missing\n");
371                 goto out_err;
372         }
373
374         if (led->led_mode > LM3601X_LED_TORCH ||
375             led->led_mode < LM3601X_LED_IR) {
376                 dev_warn(&led->client->dev, "Invalid led mode requested\n");
377                 ret = -EINVAL;
378                 goto out_err;
379         }
380
381         ret = fwnode_property_read_u32(child, "led-max-microamp",
382                                         &led->torch_current_max);
383         if (ret) {
384                 dev_warn(&led->client->dev,
385                         "led-max-microamp DT property missing\n");
386                 goto out_err;
387         }
388
389         ret = fwnode_property_read_u32(child, "flash-max-microamp",
390                                 &led->flash_current_max);
391         if (ret) {
392                 dev_warn(&led->client->dev,
393                          "flash-max-microamp DT property missing\n");
394                 goto out_err;
395         }
396
397         ret = fwnode_property_read_u32(child, "flash-max-timeout-us",
398                                 &led->max_flash_timeout);
399         if (ret) {
400                 dev_warn(&led->client->dev,
401                          "flash-max-timeout-us DT property missing\n");
402                 goto out_err;
403         }
404
405         *fwnode = child;
406
407 out_err:
408         fwnode_handle_put(child);
409         return ret;
410 }
411
412 static int lm3601x_probe(struct i2c_client *client)
413 {
414         struct lm3601x_led *led;
415         struct fwnode_handle *fwnode;
416         int ret;
417
418         led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
419         if (!led)
420                 return -ENOMEM;
421
422         led->client = client;
423         i2c_set_clientdata(client, led);
424
425         ret = lm3601x_parse_node(led, &fwnode);
426         if (ret)
427                 return -ENODEV;
428
429         led->regmap = devm_regmap_init_i2c(client, &lm3601x_regmap);
430         if (IS_ERR(led->regmap)) {
431                 ret = PTR_ERR(led->regmap);
432                 dev_err(&client->dev,
433                         "Failed to allocate register map: %d\n", ret);
434                 return ret;
435         }
436
437         mutex_init(&led->lock);
438
439         return lm3601x_register_leds(led, fwnode);
440 }
441
442 static void lm3601x_remove(struct i2c_client *client)
443 {
444         struct lm3601x_led *led = i2c_get_clientdata(client);
445         int ret;
446
447         ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
448                                  LM3601X_ENABLE_MASK, LM3601X_MODE_STANDBY);
449         if (ret)
450                 dev_warn(&client->dev,
451                          "Failed to put into standby (%pe)\n", ERR_PTR(ret));
452 }
453
454 static const struct i2c_device_id lm3601x_id[] = {
455         { "LM36010", CHIP_LM36010 },
456         { "LM36011", CHIP_LM36011 },
457         { }
458 };
459 MODULE_DEVICE_TABLE(i2c, lm3601x_id);
460
461 static const struct of_device_id of_lm3601x_leds_match[] = {
462         { .compatible = "ti,lm36010", },
463         { .compatible = "ti,lm36011", },
464         { }
465 };
466 MODULE_DEVICE_TABLE(of, of_lm3601x_leds_match);
467
468 static struct i2c_driver lm3601x_i2c_driver = {
469         .driver = {
470                 .name = "lm3601x",
471                 .of_match_table = of_lm3601x_leds_match,
472         },
473         .probe = lm3601x_probe,
474         .remove = lm3601x_remove,
475         .id_table = lm3601x_id,
476 };
477 module_i2c_driver(lm3601x_i2c_driver);
478
479 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3601X");
480 MODULE_AUTHOR("Dan Murphy <[email protected]>");
481 MODULE_LICENSE("GPL v2");
This page took 0.06325 seconds and 4 git commands to generate.