Merge tag 'm68knommu-for-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg...
[linux-2.6-microblaze.git] / drivers / leds / leds-aw200xx.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Awinic AW20036/AW20054/AW20072 LED driver
4  *
5  * Copyright (c) 2023, SberDevices. All Rights Reserved.
6  *
7  * Author: Martin Kurbanov <mmkurbanov@sberdevices.ru>
8  */
9
10 #include <linux/bitfield.h>
11 #include <linux/bits.h>
12 #include <linux/container_of.h>
13 #include <linux/i2c.h>
14 #include <linux/leds.h>
15 #include <linux/mod_devicetable.h>
16 #include <linux/module.h>
17 #include <linux/mutex.h>
18 #include <linux/regmap.h>
19 #include <linux/time.h>
20 #include <linux/units.h>
21
22 #define AW200XX_DIM_MAX                  (BIT(6) - 1)
23 #define AW200XX_FADE_MAX                 (BIT(8) - 1)
24 #define AW200XX_IMAX_DEFAULT_uA          60000
25 #define AW200XX_IMAX_MAX_uA              160000
26 #define AW200XX_IMAX_MIN_uA              3300
27
28 /* Page 0 */
29 #define AW200XX_REG_PAGE0_BASE 0xc000
30
31 /* Select page register */
32 #define AW200XX_REG_PAGE       0xF0
33 #define AW200XX_PAGE_MASK      (GENMASK(7, 6) | GENMASK(2, 0))
34 #define AW200XX_PAGE_SHIFT     0
35 #define AW200XX_NUM_PAGES      6
36 #define AW200XX_PAGE_SIZE      256
37 #define AW200XX_REG(page, reg) \
38         (AW200XX_REG_PAGE0_BASE + (page) * AW200XX_PAGE_SIZE + (reg))
39 #define AW200XX_REG_MAX \
40         AW200XX_REG(AW200XX_NUM_PAGES - 1, AW200XX_PAGE_SIZE - 1)
41 #define AW200XX_PAGE0 0
42 #define AW200XX_PAGE1 1
43 #define AW200XX_PAGE2 2
44 #define AW200XX_PAGE3 3
45 #define AW200XX_PAGE4 4
46 #define AW200XX_PAGE5 5
47
48 /* Chip ID register */
49 #define AW200XX_REG_IDR       AW200XX_REG(AW200XX_PAGE0, 0x00)
50 #define AW200XX_IDR_CHIPID    0x18
51
52 /* Sleep mode register */
53 #define AW200XX_REG_SLPCR     AW200XX_REG(AW200XX_PAGE0, 0x01)
54 #define AW200XX_SLPCR_ACTIVE  0x00
55
56 /* Reset register */
57 #define AW200XX_REG_RSTR      AW200XX_REG(AW200XX_PAGE0, 0x02)
58 #define AW200XX_RSTR_RESET    0x01
59
60 /* Global current configuration register */
61 #define AW200XX_REG_GCCR        AW200XX_REG(AW200XX_PAGE0, 0x03)
62 #define AW200XX_GCCR_IMAX_MASK  GENMASK(7, 4)
63 #define AW200XX_GCCR_IMAX(x)    ((x) << 4)
64 #define AW200XX_GCCR_ALLON      BIT(3)
65
66 /* Fast clear display control register */
67 #define AW200XX_REG_FCD       AW200XX_REG(AW200XX_PAGE0, 0x04)
68 #define AW200XX_FCD_CLEAR     0x01
69
70 /* Display size configuration */
71 #define AW200XX_REG_DSIZE          AW200XX_REG(AW200XX_PAGE0, 0x80)
72 #define AW200XX_DSIZE_COLUMNS_MAX  12
73
74 #define AW200XX_LED2REG(x, columns) \
75         ((x) + (((x) / (columns)) * (AW200XX_DSIZE_COLUMNS_MAX - (columns))))
76
77 /*
78  * DIM current configuration register (page 4).
79  * The even address for current DIM configuration.
80  * The odd address for current FADE configuration
81  */
82 #define AW200XX_REG_DIM(x, columns) \
83         AW200XX_REG(AW200XX_PAGE4, AW200XX_LED2REG(x, columns) * 2)
84 #define AW200XX_REG_DIM2FADE(x) ((x) + 1)
85
86 /*
87  * Duty ratio of display scan (see p.15 of datasheet for formula):
88  *   duty = (592us / 600.5us) * (1 / (display_rows + 1))
89  *
90  * Multiply to 1000 (MILLI) to improve the accuracy of calculations.
91  */
92 #define AW200XX_DUTY_RATIO(rows) \
93         (((592UL * USEC_PER_SEC) / 600500UL) * (MILLI / (rows)) / MILLI)
94
95 struct aw200xx_chipdef {
96         u32 channels;
97         u32 display_size_rows_max;
98         u32 display_size_columns;
99 };
100
101 struct aw200xx_led {
102         struct led_classdev cdev;
103         struct aw200xx *chip;
104         int dim;
105         u32 num;
106 };
107
108 struct aw200xx {
109         const struct aw200xx_chipdef *cdef;
110         struct i2c_client *client;
111         struct regmap *regmap;
112         struct mutex mutex;
113         u32 num_leds;
114         u32 display_rows;
115         struct aw200xx_led leds[] __counted_by(num_leds);
116 };
117
118 static ssize_t dim_show(struct device *dev, struct device_attribute *devattr,
119                         char *buf)
120 {
121         struct led_classdev *cdev = dev_get_drvdata(dev);
122         struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev);
123         int dim = led->dim;
124
125         if (dim < 0)
126                 return sysfs_emit(buf, "auto\n");
127
128         return sysfs_emit(buf, "%d\n", dim);
129 }
130
131 static ssize_t dim_store(struct device *dev, struct device_attribute *devattr,
132                          const char *buf, size_t count)
133 {
134         struct led_classdev *cdev = dev_get_drvdata(dev);
135         struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev);
136         struct aw200xx *chip = led->chip;
137         u32 columns = chip->cdef->display_size_columns;
138         int dim;
139         ssize_t ret;
140
141         if (sysfs_streq(buf, "auto")) {
142                 dim = -1;
143         } else {
144                 ret = kstrtoint(buf, 0, &dim);
145                 if (ret)
146                         return ret;
147
148                 if (dim > AW200XX_DIM_MAX)
149                         return -EINVAL;
150         }
151
152         mutex_lock(&chip->mutex);
153
154         if (dim >= 0) {
155                 ret = regmap_write(chip->regmap,
156                                    AW200XX_REG_DIM(led->num, columns), dim);
157                 if (ret)
158                         goto out_unlock;
159         }
160
161         led->dim = dim;
162         ret = count;
163
164 out_unlock:
165         mutex_unlock(&chip->mutex);
166         return ret;
167 }
168 static DEVICE_ATTR_RW(dim);
169
170 static struct attribute *dim_attrs[] = {
171         &dev_attr_dim.attr,
172         NULL
173 };
174 ATTRIBUTE_GROUPS(dim);
175
176 static int aw200xx_brightness_set(struct led_classdev *cdev,
177                                   enum led_brightness brightness)
178 {
179         struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev);
180         struct aw200xx *chip = led->chip;
181         int dim;
182         u32 reg;
183         int ret;
184
185         mutex_lock(&chip->mutex);
186
187         reg = AW200XX_REG_DIM(led->num, chip->cdef->display_size_columns);
188
189         dim = led->dim;
190         if (dim < 0)
191                 dim = max_t(int,
192                             brightness / (AW200XX_FADE_MAX / AW200XX_DIM_MAX),
193                             1);
194
195         ret = regmap_write(chip->regmap, reg, dim);
196         if (ret)
197                 goto out_unlock;
198
199         ret = regmap_write(chip->regmap,
200                            AW200XX_REG_DIM2FADE(reg), brightness);
201
202 out_unlock:
203         mutex_unlock(&chip->mutex);
204
205         return ret;
206 }
207
208 static u32 aw200xx_imax_from_global(const struct aw200xx *const chip,
209                                     u32 global_imax_uA)
210 {
211         u64 led_imax_uA;
212
213         /*
214          * The output current of each LED (see p.14 of datasheet for formula):
215          *   Iled = Imax * (dim / 63) * ((fade + 1) / 256) * duty
216          *
217          * The value of duty is determined by the following formula:
218          *   duty = (592us / 600.5us) * (1 / (display_rows + 1))
219          *
220          * Calculated for the maximum values of fade and dim.
221          * We divide by 1000 because we earlier multiplied by 1000 to improve
222          * accuracy when calculating the duty.
223          */
224         led_imax_uA = global_imax_uA * AW200XX_DUTY_RATIO(chip->display_rows);
225         do_div(led_imax_uA, MILLI);
226
227         return led_imax_uA;
228 }
229
230 static u32 aw200xx_imax_to_global(const struct aw200xx *const chip,
231                                   u32 led_imax_uA)
232 {
233         u32 duty = AW200XX_DUTY_RATIO(chip->display_rows);
234
235         /* The output current of each LED (see p.14 of datasheet for formula) */
236         return (led_imax_uA * 1000U) / duty;
237 }
238
239 #define AW200XX_IMAX_MULTIPLIER1    10000
240 #define AW200XX_IMAX_MULTIPLIER2    3333
241 #define AW200XX_IMAX_BASE_VAL1      0
242 #define AW200XX_IMAX_BASE_VAL2      8
243
244 /*
245  * The AW200XX has a 4-bit register (GCCR) to configure the global current,
246  * which ranges from 3.3mA to 160mA. The following table indicates the values
247  * of the global current, divided into two parts:
248  *
249  * +-----------+-----------------+-----------+-----------------+
250  * | reg value | global max (mA) | reg value | global max (mA) |
251  * +-----------+-----------------+-----------+-----------------+
252  * | 0         | 10              | 8         | 3.3             |
253  * | 1         | 20              | 9         | 6.7             |
254  * | 2         | 30              | 10        | 10              |
255  * | 3         | 40              | 11        | 13.3            |
256  * | 4         | 60              | 12        | 20              |
257  * | 5         | 80              | 13        | 26.7            |
258  * | 6         | 120             | 14        | 40              |
259  * | 7         | 160             | 15        | 53.3            |
260  * +-----------+-----------------+-----------+-----------------+
261  *
262  * The left part  with a multiplier of 10, and the right part  with a multiplier
263  * of 3.3.
264  * So we have two formulas to calculate the global current:
265  *   for the left part of the table:
266  *     imax = coefficient * 10
267  *
268  *   for the right part of the table:
269  *     imax = coefficient * 3.3
270  *
271  * The coefficient table consists of the following values:
272  *   1, 2, 3, 4, 6, 8, 12, 16.
273  */
274 static int aw200xx_set_imax(const struct aw200xx *const chip,
275                             u32 led_imax_uA)
276 {
277         u32 g_imax_uA = aw200xx_imax_to_global(chip, led_imax_uA);
278         u32 coeff_table[] = {1, 2, 3, 4, 6, 8, 12, 16};
279         u32 gccr_imax = UINT_MAX;
280         u32 cur_imax = 0;
281         int i;
282
283         for (i = 0; i < ARRAY_SIZE(coeff_table); i++) {
284                 u32 imax;
285
286                 /* select closest ones */
287                 imax = coeff_table[i] * AW200XX_IMAX_MULTIPLIER1;
288                 if (g_imax_uA >= imax && imax > cur_imax) {
289                         cur_imax = imax;
290                         gccr_imax = i + AW200XX_IMAX_BASE_VAL1;
291                 }
292
293                 imax = coeff_table[i] * AW200XX_IMAX_MULTIPLIER2;
294                 imax = DIV_ROUND_CLOSEST(imax, 100) * 100;
295                 if (g_imax_uA >= imax && imax > cur_imax) {
296                         cur_imax = imax;
297                         gccr_imax = i + AW200XX_IMAX_BASE_VAL2;
298                 }
299         }
300
301         if (gccr_imax == UINT_MAX)
302                 return -EINVAL;
303
304         return regmap_update_bits(chip->regmap, AW200XX_REG_GCCR,
305                                   AW200XX_GCCR_IMAX_MASK,
306                                   AW200XX_GCCR_IMAX(gccr_imax));
307 }
308
309 static int aw200xx_chip_reset(const struct aw200xx *const chip)
310 {
311         int ret;
312
313         ret = regmap_write(chip->regmap, AW200XX_REG_RSTR, AW200XX_RSTR_RESET);
314         if (ret)
315                 return ret;
316
317         regcache_mark_dirty(chip->regmap);
318         return regmap_write(chip->regmap, AW200XX_REG_FCD, AW200XX_FCD_CLEAR);
319 }
320
321 static int aw200xx_chip_init(const struct aw200xx *const chip)
322 {
323         int ret;
324
325         ret = regmap_write(chip->regmap, AW200XX_REG_DSIZE,
326                            chip->display_rows - 1);
327         if (ret)
328                 return ret;
329
330         ret = regmap_write(chip->regmap, AW200XX_REG_SLPCR,
331                            AW200XX_SLPCR_ACTIVE);
332         if (ret)
333                 return ret;
334
335         return regmap_update_bits(chip->regmap, AW200XX_REG_GCCR,
336                                   AW200XX_GCCR_ALLON, AW200XX_GCCR_ALLON);
337 }
338
339 static int aw200xx_chip_check(const struct aw200xx *const chip)
340 {
341         struct device *dev = &chip->client->dev;
342         u32 chipid;
343         int ret;
344
345         ret = regmap_read(chip->regmap, AW200XX_REG_IDR, &chipid);
346         if (ret)
347                 return dev_err_probe(dev, ret, "Failed to read chip ID\n");
348
349         if (chipid != AW200XX_IDR_CHIPID)
350                 return dev_err_probe(dev, -ENODEV,
351                                      "Chip reported wrong ID: %x\n", chipid);
352
353         return 0;
354 }
355
356 static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip)
357 {
358         struct fwnode_handle *child;
359         u32 current_min, current_max, min_uA;
360         int ret;
361         int i;
362
363         ret = device_property_read_u32(dev, "awinic,display-rows",
364                                        &chip->display_rows);
365         if (ret)
366                 return dev_err_probe(dev, ret,
367                                      "Failed to read 'display-rows' property\n");
368
369         if (!chip->display_rows ||
370             chip->display_rows > chip->cdef->display_size_rows_max) {
371                 return dev_err_probe(dev, -EINVAL,
372                                      "Invalid leds display size %u\n",
373                                      chip->display_rows);
374         }
375
376         current_max = aw200xx_imax_from_global(chip, AW200XX_IMAX_MAX_uA);
377         current_min = aw200xx_imax_from_global(chip, AW200XX_IMAX_MIN_uA);
378         min_uA = UINT_MAX;
379         i = 0;
380
381         device_for_each_child_node(dev, child) {
382                 struct led_init_data init_data = {};
383                 struct aw200xx_led *led;
384                 u32 source, imax;
385
386                 ret = fwnode_property_read_u32(child, "reg", &source);
387                 if (ret) {
388                         dev_err(dev, "Missing reg property\n");
389                         chip->num_leds--;
390                         continue;
391                 }
392
393                 if (source >= chip->cdef->channels) {
394                         dev_err(dev, "LED reg %u out of range (max %u)\n",
395                                 source, chip->cdef->channels);
396                         chip->num_leds--;
397                         continue;
398                 }
399
400                 ret = fwnode_property_read_u32(child, "led-max-microamp",
401                                                &imax);
402                 if (ret) {
403                         dev_info(&chip->client->dev,
404                                  "DT property led-max-microamp is missing\n");
405                 } else if (imax < current_min || imax > current_max) {
406                         dev_err(dev, "Invalid value %u for led-max-microamp\n",
407                                 imax);
408                         chip->num_leds--;
409                         continue;
410                 } else {
411                         min_uA = min(min_uA, imax);
412                 }
413
414                 led = &chip->leds[i];
415                 led->dim = -1;
416                 led->num = source;
417                 led->chip = chip;
418                 led->cdev.brightness_set_blocking = aw200xx_brightness_set;
419                 led->cdev.groups = dim_groups;
420                 init_data.fwnode = child;
421
422                 ret = devm_led_classdev_register_ext(dev, &led->cdev,
423                                                      &init_data);
424                 if (ret) {
425                         fwnode_handle_put(child);
426                         break;
427                 }
428
429                 i++;
430         }
431
432         if (!chip->num_leds)
433                 return -EINVAL;
434
435         if (min_uA == UINT_MAX) {
436                 min_uA = aw200xx_imax_from_global(chip,
437                                                   AW200XX_IMAX_DEFAULT_uA);
438         }
439
440         return aw200xx_set_imax(chip, min_uA);
441 }
442
443 static const struct regmap_range_cfg aw200xx_ranges[] = {
444         {
445                 .name = "aw200xx",
446                 .range_min = 0,
447                 .range_max = AW200XX_REG_MAX,
448                 .selector_reg = AW200XX_REG_PAGE,
449                 .selector_mask = AW200XX_PAGE_MASK,
450                 .selector_shift = AW200XX_PAGE_SHIFT,
451                 .window_start = 0,
452                 .window_len = AW200XX_PAGE_SIZE,
453         },
454 };
455
456 static const struct regmap_range aw200xx_writeonly_ranges[] = {
457         regmap_reg_range(AW200XX_REG(AW200XX_PAGE1, 0x00), AW200XX_REG_MAX),
458 };
459
460 static const struct regmap_access_table aw200xx_readable_table = {
461         .no_ranges = aw200xx_writeonly_ranges,
462         .n_no_ranges = ARRAY_SIZE(aw200xx_writeonly_ranges),
463 };
464
465 static const struct regmap_range aw200xx_readonly_ranges[] = {
466         regmap_reg_range(AW200XX_REG_IDR, AW200XX_REG_IDR),
467 };
468
469 static const struct regmap_access_table aw200xx_writeable_table = {
470         .no_ranges = aw200xx_readonly_ranges,
471         .n_no_ranges = ARRAY_SIZE(aw200xx_readonly_ranges),
472 };
473
474 static const struct regmap_config aw200xx_regmap_config = {
475         .reg_bits = 8,
476         .val_bits = 8,
477         .max_register = AW200XX_REG_MAX,
478         .ranges = aw200xx_ranges,
479         .num_ranges = ARRAY_SIZE(aw200xx_ranges),
480         .rd_table = &aw200xx_readable_table,
481         .wr_table = &aw200xx_writeable_table,
482         .cache_type = REGCACHE_MAPLE,
483 };
484
485 static int aw200xx_probe(struct i2c_client *client)
486 {
487         const struct aw200xx_chipdef *cdef;
488         struct aw200xx *chip;
489         int count;
490         int ret;
491
492         cdef = device_get_match_data(&client->dev);
493         if (!cdef)
494                 return -ENODEV;
495
496         count = device_get_child_node_count(&client->dev);
497         if (!count || count > cdef->channels)
498                 return dev_err_probe(&client->dev, -EINVAL,
499                                      "Incorrect number of leds (%d)", count);
500
501         chip = devm_kzalloc(&client->dev, struct_size(chip, leds, count),
502                             GFP_KERNEL);
503         if (!chip)
504                 return -ENOMEM;
505
506         chip->cdef = cdef;
507         chip->num_leds = count;
508         chip->client = client;
509         i2c_set_clientdata(client, chip);
510
511         chip->regmap = devm_regmap_init_i2c(client, &aw200xx_regmap_config);
512         if (IS_ERR(chip->regmap))
513                 return PTR_ERR(chip->regmap);
514
515         ret = aw200xx_chip_check(chip);
516         if (ret)
517                 return ret;
518
519         mutex_init(&chip->mutex);
520
521         /* Need a lock now since after call aw200xx_probe_fw, sysfs nodes created */
522         mutex_lock(&chip->mutex);
523
524         ret = aw200xx_chip_reset(chip);
525         if (ret)
526                 goto out_unlock;
527
528         ret = aw200xx_probe_fw(&client->dev, chip);
529         if (ret)
530                 goto out_unlock;
531
532         ret = aw200xx_chip_init(chip);
533
534 out_unlock:
535         mutex_unlock(&chip->mutex);
536         return ret;
537 }
538
539 static void aw200xx_remove(struct i2c_client *client)
540 {
541         struct aw200xx *chip = i2c_get_clientdata(client);
542
543         aw200xx_chip_reset(chip);
544         mutex_destroy(&chip->mutex);
545 }
546
547 static const struct aw200xx_chipdef aw20036_cdef = {
548         .channels = 36,
549         .display_size_rows_max = 3,
550         .display_size_columns = 12,
551 };
552
553 static const struct aw200xx_chipdef aw20054_cdef = {
554         .channels = 54,
555         .display_size_rows_max = 6,
556         .display_size_columns = 9,
557 };
558
559 static const struct aw200xx_chipdef aw20072_cdef = {
560         .channels = 72,
561         .display_size_rows_max = 6,
562         .display_size_columns = 12,
563 };
564
565 static const struct i2c_device_id aw200xx_id[] = {
566         { "aw20036" },
567         { "aw20054" },
568         { "aw20072" },
569         {}
570 };
571 MODULE_DEVICE_TABLE(i2c, aw200xx_id);
572
573 static const struct of_device_id aw200xx_match_table[] = {
574         { .compatible = "awinic,aw20036", .data = &aw20036_cdef, },
575         { .compatible = "awinic,aw20054", .data = &aw20054_cdef, },
576         { .compatible = "awinic,aw20072", .data = &aw20072_cdef, },
577         {}
578 };
579 MODULE_DEVICE_TABLE(of, aw200xx_match_table);
580
581 static struct i2c_driver aw200xx_driver = {
582         .driver = {
583                 .name = "aw200xx",
584                 .of_match_table = aw200xx_match_table,
585         },
586         .probe = aw200xx_probe,
587         .remove = aw200xx_remove,
588         .id_table = aw200xx_id,
589 };
590 module_i2c_driver(aw200xx_driver);
591
592 MODULE_AUTHOR("Martin Kurbanov <mmkurbanov@sberdevices.ru>");
593 MODULE_DESCRIPTION("AW200XX LED driver");
594 MODULE_LICENSE("GPL");