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