]> Git Repo - J-linux.git/blob - drivers/leds/flash/leds-sy7802.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / leds / flash / leds-sy7802.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Silergy SY7802 flash LED driver with an I2C interface
4  *
5  * Copyright 2024 AndrĂ© Apitzsch <[email protected]>
6  */
7
8 #include <linux/gpio/consumer.h>
9 #include <linux/i2c.h>
10 #include <linux/kernel.h>
11 #include <linux/led-class-flash.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/regmap.h>
15 #include <linux/regulator/consumer.h>
16
17 #define SY7802_MAX_LEDS 2
18 #define SY7802_LED_JOINT 2
19
20 #define SY7802_REG_ENABLE               0x10
21 #define SY7802_REG_TORCH_BRIGHTNESS     0xa0
22 #define SY7802_REG_FLASH_BRIGHTNESS     0xb0
23 #define SY7802_REG_FLASH_DURATION       0xc0
24 #define SY7802_REG_FLAGS                0xd0
25 #define SY7802_REG_CONFIG_1             0xe0
26 #define SY7802_REG_CONFIG_2             0xf0
27 #define SY7802_REG_VIN_MONITOR          0x80
28 #define SY7802_REG_LAST_FLASH           0x81
29 #define SY7802_REG_VLED_MONITOR         0x30
30 #define SY7802_REG_ADC_DELAY            0x31
31 #define SY7802_REG_DEV_ID               0xff
32
33 #define SY7802_MODE_OFF         0
34 #define SY7802_MODE_TORCH       2
35 #define SY7802_MODE_FLASH       3
36 #define SY7802_MODE_MASK        GENMASK(1, 0)
37
38 #define SY7802_LEDS_SHIFT       3
39 #define SY7802_LEDS_MASK(_id)   (BIT(_id) << SY7802_LEDS_SHIFT)
40 #define SY7802_LEDS_MASK_ALL    (SY7802_LEDS_MASK(0) | SY7802_LEDS_MASK(1))
41
42 #define SY7802_TORCH_CURRENT_SHIFT      3
43 #define SY7802_TORCH_CURRENT_MASK(_id) \
44         (GENMASK(2, 0) << (SY7802_TORCH_CURRENT_SHIFT * (_id)))
45 #define SY7802_TORCH_CURRENT_MASK_ALL \
46         (SY7802_TORCH_CURRENT_MASK(0) | SY7802_TORCH_CURRENT_MASK(1))
47
48 #define SY7802_FLASH_CURRENT_SHIFT      4
49 #define SY7802_FLASH_CURRENT_MASK(_id) \
50         (GENMASK(3, 0) << (SY7802_FLASH_CURRENT_SHIFT * (_id)))
51 #define SY7802_FLASH_CURRENT_MASK_ALL \
52         (SY7802_FLASH_CURRENT_MASK(0) | SY7802_FLASH_CURRENT_MASK(1))
53
54 #define SY7802_TIMEOUT_DEFAULT_US       512000U
55 #define SY7802_TIMEOUT_MIN_US           32000U
56 #define SY7802_TIMEOUT_MAX_US           1024000U
57 #define SY7802_TIMEOUT_STEPSIZE_US      32000U
58
59 #define SY7802_TORCH_BRIGHTNESS_MAX 8
60
61 #define SY7802_FLASH_BRIGHTNESS_DEFAULT 14
62 #define SY7802_FLASH_BRIGHTNESS_MIN     0
63 #define SY7802_FLASH_BRIGHTNESS_MAX     15
64 #define SY7802_FLASH_BRIGHTNESS_STEP    1
65
66 #define SY7802_FLAG_TIMEOUT                     BIT(0)
67 #define SY7802_FLAG_THERMAL_SHUTDOWN            BIT(1)
68 #define SY7802_FLAG_LED_FAULT                   BIT(2)
69 #define SY7802_FLAG_TX1_INTERRUPT               BIT(3)
70 #define SY7802_FLAG_TX2_INTERRUPT               BIT(4)
71 #define SY7802_FLAG_LED_THERMAL_FAULT           BIT(5)
72 #define SY7802_FLAG_FLASH_INPUT_VOLTAGE_LOW     BIT(6)
73 #define SY7802_FLAG_INPUT_VOLTAGE_LOW           BIT(7)
74
75 #define SY7802_CHIP_ID  0x51
76
77 static const struct reg_default sy7802_regmap_defs[] = {
78         { SY7802_REG_ENABLE, SY7802_LEDS_MASK_ALL },
79         { SY7802_REG_TORCH_BRIGHTNESS, 0x92 },
80         { SY7802_REG_FLASH_BRIGHTNESS, SY7802_FLASH_BRIGHTNESS_DEFAULT |
81                 SY7802_FLASH_BRIGHTNESS_DEFAULT << SY7802_FLASH_CURRENT_SHIFT },
82         { SY7802_REG_FLASH_DURATION, 0x6f },
83         { SY7802_REG_FLAGS, 0x0 },
84         { SY7802_REG_CONFIG_1, 0x68 },
85         { SY7802_REG_CONFIG_2, 0xf0 },
86 };
87
88 struct sy7802_led {
89         struct led_classdev_flash flash;
90         struct sy7802 *chip;
91         u8 led_id;
92 };
93
94 struct sy7802 {
95         struct device *dev;
96         struct regmap *regmap;
97         struct mutex mutex;
98
99         struct gpio_desc *enable_gpio;
100         struct regulator *vin_regulator;
101
102         unsigned int fled_strobe_used;
103         unsigned int fled_torch_used;
104         unsigned int leds_active;
105         int num_leds;
106         struct sy7802_led leds[] __counted_by(num_leds);
107 };
108
109 static int sy7802_torch_brightness_set(struct led_classdev *lcdev, enum led_brightness brightness)
110 {
111         struct sy7802_led *led = container_of(lcdev, struct sy7802_led, flash.led_cdev);
112         struct sy7802 *chip = led->chip;
113         u32 fled_torch_used_tmp;
114         u32 led_enable_mask;
115         u32 enable_mask;
116         u32 torch_mask;
117         u32 val;
118         int ret;
119
120         mutex_lock(&chip->mutex);
121
122         if (chip->fled_strobe_used) {
123                 dev_warn(chip->dev, "Cannot set torch brightness whilst strobe is enabled\n");
124                 ret = -EBUSY;
125                 goto unlock;
126         }
127
128         if (brightness)
129                 fled_torch_used_tmp = chip->fled_torch_used | BIT(led->led_id);
130         else
131                 fled_torch_used_tmp = chip->fled_torch_used & ~BIT(led->led_id);
132
133         led_enable_mask = led->led_id == SY7802_LED_JOINT ?
134                           SY7802_LEDS_MASK_ALL :
135                           SY7802_LEDS_MASK(led->led_id);
136
137         val = brightness ? led_enable_mask : SY7802_MODE_OFF;
138         if (fled_torch_used_tmp)
139                 val |= SY7802_MODE_TORCH;
140
141         /* Disable torch to apply brightness */
142         ret = regmap_update_bits(chip->regmap, SY7802_REG_ENABLE, SY7802_MODE_MASK,
143                                  SY7802_MODE_OFF);
144         if (ret)
145                 goto unlock;
146
147         torch_mask = led->led_id == SY7802_LED_JOINT ?
148                      SY7802_TORCH_CURRENT_MASK_ALL :
149                      SY7802_TORCH_CURRENT_MASK(led->led_id);
150
151         /* Register expects brightness between 0 and MAX_BRIGHTNESS - 1 */
152         if (brightness)
153                 brightness -= 1;
154
155         brightness |= (brightness << SY7802_TORCH_CURRENT_SHIFT);
156
157         ret = regmap_update_bits(chip->regmap, SY7802_REG_TORCH_BRIGHTNESS, torch_mask, brightness);
158         if (ret)
159                 goto unlock;
160
161         enable_mask = SY7802_MODE_MASK | led_enable_mask;
162         ret = regmap_update_bits(chip->regmap, SY7802_REG_ENABLE, enable_mask, val);
163         if (ret)
164                 goto unlock;
165
166         chip->fled_torch_used = fled_torch_used_tmp;
167
168 unlock:
169         mutex_unlock(&chip->mutex);
170         return ret;
171 }
172
173 static int sy7802_flash_brightness_set(struct led_classdev_flash *fl_cdev, u32 brightness)
174 {
175         struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash);
176         struct led_flash_setting *s = &fl_cdev->brightness;
177         u32 val = (brightness - s->min) / s->step;
178         struct sy7802 *chip = led->chip;
179         u32 flash_mask;
180         int ret;
181
182         val |= (val << SY7802_FLASH_CURRENT_SHIFT);
183         flash_mask = led->led_id == SY7802_LED_JOINT ?
184                      SY7802_FLASH_CURRENT_MASK_ALL :
185                      SY7802_FLASH_CURRENT_MASK(led->led_id);
186
187         mutex_lock(&chip->mutex);
188         ret = regmap_update_bits(chip->regmap, SY7802_REG_FLASH_BRIGHTNESS, flash_mask, val);
189         mutex_unlock(&chip->mutex);
190
191         return ret;
192 }
193
194 static int sy7802_strobe_set(struct led_classdev_flash *fl_cdev, bool state)
195 {
196         struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash);
197         struct sy7802 *chip = led->chip;
198         u32 fled_strobe_used_tmp;
199         u32 led_enable_mask;
200         u32 enable_mask;
201         u32 val;
202         int ret;
203
204         mutex_lock(&chip->mutex);
205
206         if (chip->fled_torch_used) {
207                 dev_warn(chip->dev, "Cannot set strobe brightness whilst torch is enabled\n");
208                 ret = -EBUSY;
209                 goto unlock;
210         }
211
212         if (state)
213                 fled_strobe_used_tmp = chip->fled_strobe_used | BIT(led->led_id);
214         else
215                 fled_strobe_used_tmp = chip->fled_strobe_used & ~BIT(led->led_id);
216
217         led_enable_mask = led->led_id == SY7802_LED_JOINT ?
218                           SY7802_LEDS_MASK_ALL :
219                           SY7802_LEDS_MASK(led->led_id);
220
221         val = state ? led_enable_mask : SY7802_MODE_OFF;
222         if (fled_strobe_used_tmp)
223                 val |= SY7802_MODE_FLASH;
224
225         enable_mask = SY7802_MODE_MASK | led_enable_mask;
226         ret = regmap_update_bits(chip->regmap, SY7802_REG_ENABLE, enable_mask, val);
227
228         if (ret)
229                 goto unlock;
230
231         chip->fled_strobe_used = fled_strobe_used_tmp;
232
233 unlock:
234         mutex_unlock(&chip->mutex);
235         return ret;
236 }
237
238 static int sy7802_strobe_get(struct led_classdev_flash *fl_cdev, bool *state)
239 {
240         struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash);
241         struct sy7802 *chip = led->chip;
242
243         mutex_lock(&chip->mutex);
244         *state = !!(chip->fled_strobe_used & BIT(led->led_id));
245         mutex_unlock(&chip->mutex);
246
247         return 0;
248 }
249
250 static int sy7802_timeout_set(struct led_classdev_flash *fl_cdev, u32 timeout)
251 {
252         struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash);
253         struct led_flash_setting *s = &fl_cdev->timeout;
254         u32 val = (timeout - s->min) / s->step;
255         struct sy7802 *chip = led->chip;
256
257         return regmap_write(chip->regmap, SY7802_REG_FLASH_DURATION, val);
258 }
259
260 static int sy7802_fault_get(struct led_classdev_flash *fl_cdev, u32 *fault)
261 {
262         struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash);
263         struct sy7802 *chip = led->chip;
264         u32 val, led_faults = 0;
265         int ret;
266
267         /* NOTE: reading register clears fault status */
268         ret = regmap_read(chip->regmap, SY7802_REG_FLAGS, &val);
269         if (ret)
270                 return ret;
271
272         if (val & (SY7802_FLAG_FLASH_INPUT_VOLTAGE_LOW | SY7802_FLAG_INPUT_VOLTAGE_LOW))
273                 led_faults |= LED_FAULT_INPUT_VOLTAGE;
274
275         if (val & SY7802_FLAG_THERMAL_SHUTDOWN)
276                 led_faults |= LED_FAULT_OVER_TEMPERATURE;
277
278         if (val & SY7802_FLAG_TIMEOUT)
279                 led_faults |= LED_FAULT_TIMEOUT;
280
281         *fault = led_faults;
282         return 0;
283 }
284
285 static const struct led_flash_ops sy7802_flash_ops = {
286         .flash_brightness_set = sy7802_flash_brightness_set,
287         .strobe_set = sy7802_strobe_set,
288         .strobe_get = sy7802_strobe_get,
289         .timeout_set = sy7802_timeout_set,
290         .fault_get = sy7802_fault_get,
291 };
292
293 static void sy7802_init_flash_brightness(struct led_classdev_flash *fl_cdev)
294 {
295         struct led_flash_setting *s;
296
297         /* Init flash brightness setting */
298         s = &fl_cdev->brightness;
299         s->min = SY7802_FLASH_BRIGHTNESS_MIN;
300         s->max = SY7802_FLASH_BRIGHTNESS_MAX;
301         s->step = SY7802_FLASH_BRIGHTNESS_STEP;
302         s->val = SY7802_FLASH_BRIGHTNESS_DEFAULT;
303 }
304
305 static void sy7802_init_flash_timeout(struct led_classdev_flash *fl_cdev)
306 {
307         struct led_flash_setting *s;
308
309         /* Init flash timeout setting */
310         s = &fl_cdev->timeout;
311         s->min = SY7802_TIMEOUT_MIN_US;
312         s->max = SY7802_TIMEOUT_MAX_US;
313         s->step = SY7802_TIMEOUT_STEPSIZE_US;
314         s->val = SY7802_TIMEOUT_DEFAULT_US;
315 }
316
317 static int sy7802_led_register(struct device *dev, struct sy7802_led *led,
318                                struct device_node *np)
319 {
320         struct led_init_data init_data = {};
321         int ret;
322
323         init_data.fwnode = of_fwnode_handle(np);
324
325         ret = devm_led_classdev_flash_register_ext(dev, &led->flash, &init_data);
326         if (ret) {
327                 dev_err(dev, "Couldn't register flash %d\n", led->led_id);
328                 return ret;
329         }
330
331         return 0;
332 }
333
334 static int sy7802_init_flash_properties(struct device *dev, struct sy7802_led *led,
335                                         struct device_node *np)
336 {
337         struct led_classdev_flash *flash = &led->flash;
338         struct led_classdev *lcdev = &flash->led_cdev;
339         u32 sources[SY7802_MAX_LEDS];
340         int i, num, ret;
341
342         num = of_property_count_u32_elems(np, "led-sources");
343         if (num < 1) {
344                 dev_err(dev, "Not specified or wrong number of led-sources\n");
345                 return -EINVAL;
346         }
347
348         ret = of_property_read_u32_array(np, "led-sources", sources, num);
349         if (ret)
350                 return ret;
351
352         for (i = 0; i < num; i++) {
353                 if (sources[i] >= SY7802_MAX_LEDS)
354                         return -EINVAL;
355                 if (led->chip->leds_active & BIT(sources[i]))
356                         return -EINVAL;
357                 led->chip->leds_active |= BIT(sources[i]);
358         }
359
360         /* If both channels are specified in 'led-sources', joint flash output mode is used */
361         led->led_id = num == 2 ? SY7802_LED_JOINT : sources[0];
362
363         lcdev->max_brightness = SY7802_TORCH_BRIGHTNESS_MAX;
364         lcdev->brightness_set_blocking = sy7802_torch_brightness_set;
365         lcdev->flags |= LED_DEV_CAP_FLASH;
366
367         flash->ops = &sy7802_flash_ops;
368
369         sy7802_init_flash_brightness(flash);
370         sy7802_init_flash_timeout(flash);
371
372         return 0;
373 }
374
375 static int sy7802_chip_check(struct sy7802 *chip)
376 {
377         struct device *dev = chip->dev;
378         u32 chipid;
379         int ret;
380
381         ret = regmap_read(chip->regmap, SY7802_REG_DEV_ID, &chipid);
382         if (ret)
383                 return dev_err_probe(dev, ret, "Failed to read chip ID\n");
384
385         if (chipid != SY7802_CHIP_ID)
386                 return dev_err_probe(dev, -ENODEV, "Unsupported chip detected: %x\n", chipid);
387
388         return 0;
389 }
390
391 static void sy7802_enable(struct sy7802 *chip)
392 {
393         gpiod_set_value_cansleep(chip->enable_gpio, 1);
394         usleep_range(200, 300);
395 }
396
397 static void sy7802_disable(struct sy7802 *chip)
398 {
399         gpiod_set_value_cansleep(chip->enable_gpio, 0);
400 }
401
402 static int sy7802_probe_dt(struct sy7802 *chip)
403 {
404         struct device_node *np = dev_of_node(chip->dev);
405         int child_num;
406         int ret;
407
408         regmap_write(chip->regmap, SY7802_REG_ENABLE, SY7802_MODE_OFF);
409         regmap_write(chip->regmap, SY7802_REG_TORCH_BRIGHTNESS, LED_OFF);
410
411         child_num = 0;
412         for_each_available_child_of_node_scoped(np, child) {
413                 struct sy7802_led *led = chip->leds + child_num;
414
415                 led->chip = chip;
416                 led->led_id = child_num;
417
418                 ret = sy7802_init_flash_properties(chip->dev, led, child);
419                 if (ret)
420                         return ret;
421
422                 ret = sy7802_led_register(chip->dev, led, child);
423                 if (ret)
424                         return ret;
425
426                 child_num++;
427         }
428         return 0;
429 }
430
431 static void sy7802_chip_disable_action(void *data)
432 {
433         struct sy7802 *chip = data;
434
435         sy7802_disable(chip);
436 }
437
438 static void sy7802_regulator_disable_action(void *data)
439 {
440         struct sy7802 *chip = data;
441
442         regulator_disable(chip->vin_regulator);
443 }
444
445 static const struct regmap_config sy7802_regmap_config = {
446         .reg_bits = 8,
447         .val_bits = 8,
448         .max_register = 0xff,
449         .cache_type = REGCACHE_MAPLE,
450         .reg_defaults = sy7802_regmap_defs,
451         .num_reg_defaults = ARRAY_SIZE(sy7802_regmap_defs),
452 };
453
454 static int sy7802_probe(struct i2c_client *client)
455 {
456         struct device *dev = &client->dev;
457         struct sy7802 *chip;
458         size_t count;
459         int ret;
460
461         count = device_get_child_node_count(dev);
462         if (!count || count > SY7802_MAX_LEDS)
463                 return dev_err_probe(dev, -EINVAL, "Invalid amount of LED nodes %zu\n", count);
464
465         chip = devm_kzalloc(dev, struct_size(chip, leds, count), GFP_KERNEL);
466         if (!chip)
467                 return -ENOMEM;
468
469         chip->num_leds = count;
470
471         chip->dev = dev;
472         i2c_set_clientdata(client, chip);
473
474         chip->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
475         ret = PTR_ERR_OR_ZERO(chip->enable_gpio);
476         if (ret)
477                 return dev_err_probe(dev, ret, "Failed to request enable gpio\n");
478
479         chip->vin_regulator = devm_regulator_get(dev, "vin");
480         ret = PTR_ERR_OR_ZERO(chip->vin_regulator);
481         if (ret)
482                 return dev_err_probe(dev, ret, "Failed to request regulator\n");
483
484         ret = regulator_enable(chip->vin_regulator);
485         if (ret)
486                 return dev_err_probe(dev, ret, "Failed to enable regulator\n");
487
488         ret = devm_add_action_or_reset(dev, sy7802_regulator_disable_action, chip);
489         if (ret)
490                 return ret;
491
492         ret = devm_mutex_init(dev, &chip->mutex);
493         if (ret)
494                 return ret;
495
496         mutex_lock(&chip->mutex);
497
498         chip->regmap = devm_regmap_init_i2c(client, &sy7802_regmap_config);
499         if (IS_ERR(chip->regmap)) {
500                 ret = PTR_ERR(chip->regmap);
501                 dev_err_probe(dev, ret, "Failed to allocate register map\n");
502                 goto error;
503         }
504
505         ret = sy7802_probe_dt(chip);
506         if (ret < 0)
507                 goto error;
508
509         sy7802_enable(chip);
510
511         ret = devm_add_action_or_reset(dev, sy7802_chip_disable_action, chip);
512         if (ret)
513                 goto error;
514
515         ret = sy7802_chip_check(chip);
516
517 error:
518         mutex_unlock(&chip->mutex);
519         return ret;
520 }
521
522 static const struct of_device_id __maybe_unused sy7802_leds_match[] = {
523         { .compatible = "silergy,sy7802", },
524         {}
525 };
526 MODULE_DEVICE_TABLE(of, sy7802_leds_match);
527
528 static struct i2c_driver sy7802_driver = {
529         .driver = {
530                 .name = "sy7802",
531                 .of_match_table = of_match_ptr(sy7802_leds_match),
532         },
533         .probe = sy7802_probe,
534 };
535 module_i2c_driver(sy7802_driver);
536
537 MODULE_AUTHOR("AndrĂ© Apitzsch <[email protected]>");
538 MODULE_DESCRIPTION("Silergy SY7802 flash LED driver");
539 MODULE_LICENSE("GPL");
This page took 0.056795 seconds and 4 git commands to generate.