1 // SPDX-License-Identifier: GPL-2.0
3 * Awinic AW20036/AW20054/AW20072/AW20108 LED driver
5 * Copyright (c) 2023, SberDevices. All Rights Reserved.
7 * Author: Martin Kurbanov <mmkurbanov@sberdevices.ru>
10 #include <linux/bitfield.h>
11 #include <linux/bits.h>
12 #include <linux/container_of.h>
13 #include <linux/gpio/consumer.h>
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>
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
30 #define AW200XX_REG_PAGE0_BASE 0xc000
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
49 /* Chip ID register */
50 #define AW200XX_REG_IDR AW200XX_REG(AW200XX_PAGE0, 0x00)
51 #define AW200XX_IDR_CHIPID 0x18
53 /* Sleep mode register */
54 #define AW200XX_REG_SLPCR AW200XX_REG(AW200XX_PAGE0, 0x01)
55 #define AW200XX_SLPCR_ACTIVE 0x00
58 #define AW200XX_REG_RSTR AW200XX_REG(AW200XX_PAGE0, 0x02)
59 #define AW200XX_RSTR_RESET 0x01
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)
67 /* Fast clear display control register */
68 #define AW200XX_REG_FCD AW200XX_REG(AW200XX_PAGE0, 0x04)
69 #define AW200XX_FCD_CLEAR 0x01
71 /* Display size configuration */
72 #define AW200XX_REG_DSIZE AW200XX_REG(AW200XX_PAGE0, 0x80)
73 #define AW200XX_DSIZE_COLUMNS_MAX 12
75 #define AW200XX_LED2REG(x, columns) \
76 ((x) + (((x) / (columns)) * (AW200XX_DSIZE_COLUMNS_MAX - (columns))))
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))
83 * DIM current configuration register (page 4).
84 * The even address for current DIM configuration.
85 * The odd address for current FADE configuration
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 #define AW200XX_REG_FADE2DIM(fade) \
91 DIV_ROUND_UP((fade) * AW200XX_DIM_MAX, AW200XX_FADE_MAX)
94 * Duty ratio of display scan (see p.15 of datasheet for formula):
95 * duty = (592us / 600.5us) * (1 / (display_rows + 1))
97 * Multiply to 1000 (MILLI) to improve the accuracy of calculations.
99 #define AW200XX_DUTY_RATIO(rows) \
100 (((592UL * USEC_PER_SEC) / 600500UL) * (MILLI / (rows)) / MILLI)
102 struct aw200xx_chipdef
{
104 u32 display_size_rows_max
;
105 u32 display_size_columns
;
109 struct led_classdev cdev
;
110 struct aw200xx
*chip
;
116 const struct aw200xx_chipdef
*cdef
;
117 struct i2c_client
*client
;
118 struct regmap
*regmap
;
122 struct gpio_desc
*hwen
;
123 struct aw200xx_led leds
[] __counted_by(num_leds
);
126 static ssize_t
dim_show(struct device
*dev
, struct device_attribute
*devattr
,
129 struct led_classdev
*cdev
= dev_get_drvdata(dev
);
130 struct aw200xx_led
*led
= container_of(cdev
, struct aw200xx_led
, cdev
);
134 return sysfs_emit(buf
, "auto\n");
136 return sysfs_emit(buf
, "%d\n", dim
);
139 static ssize_t
dim_store(struct device
*dev
, struct device_attribute
*devattr
,
140 const char *buf
, size_t count
)
142 struct led_classdev
*cdev
= dev_get_drvdata(dev
);
143 struct aw200xx_led
*led
= container_of(cdev
, struct aw200xx_led
, cdev
);
144 struct aw200xx
*chip
= led
->chip
;
145 u32 columns
= chip
->cdef
->display_size_columns
;
149 if (sysfs_streq(buf
, "auto")) {
152 ret
= kstrtoint(buf
, 0, &dim
);
156 if (dim
> AW200XX_DIM_MAX
)
160 mutex_lock(&chip
->mutex
);
163 ret
= regmap_write(chip
->regmap
,
164 AW200XX_REG_DIM_PAGE1(led
->num
, columns
),
174 mutex_unlock(&chip
->mutex
);
177 static DEVICE_ATTR_RW(dim
);
179 static struct attribute
*dim_attrs
[] = {
183 ATTRIBUTE_GROUPS(dim
);
185 static int aw200xx_brightness_set(struct led_classdev
*cdev
,
186 enum led_brightness brightness
)
188 struct aw200xx_led
*led
= container_of(cdev
, struct aw200xx_led
, cdev
);
189 struct aw200xx
*chip
= led
->chip
;
194 mutex_lock(&chip
->mutex
);
196 reg
= AW200XX_REG_DIM(led
->num
, chip
->cdef
->display_size_columns
);
200 dim
= AW200XX_REG_FADE2DIM(brightness
);
202 ret
= regmap_write(chip
->regmap
, reg
, dim
);
206 ret
= regmap_write(chip
->regmap
,
207 AW200XX_REG_DIM2FADE(reg
), brightness
);
210 mutex_unlock(&chip
->mutex
);
215 static u32
aw200xx_imax_from_global(const struct aw200xx
*const chip
,
221 * The output current of each LED (see p.14 of datasheet for formula):
222 * Iled = Imax * (dim / 63) * ((fade + 1) / 256) * duty
224 * The value of duty is determined by the following formula:
225 * duty = (592us / 600.5us) * (1 / (display_rows + 1))
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.
231 led_imax_uA
= global_imax_uA
* AW200XX_DUTY_RATIO(chip
->display_rows
);
232 do_div(led_imax_uA
, MILLI
);
237 static u32
aw200xx_imax_to_global(const struct aw200xx
*const chip
,
240 u32 duty
= AW200XX_DUTY_RATIO(chip
->display_rows
);
242 /* The output current of each LED (see p.14 of datasheet for formula) */
243 return (led_imax_uA
* 1000U) / duty
;
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
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:
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 * +-----------+-----------------+-----------+-----------------+
269 * The left part with a multiplier of 10, and the right part with a multiplier
271 * So we have two formulas to calculate the global current:
272 * for the left part of the table:
273 * imax = coefficient * 10
275 * for the right part of the table:
276 * imax = coefficient * 3.3
278 * The coefficient table consists of the following values:
279 * 1, 2, 3, 4, 6, 8, 12, 16.
281 static int aw200xx_set_imax(const struct aw200xx
*const chip
,
284 u32 g_imax_uA
= aw200xx_imax_to_global(chip
, led_imax_uA
);
285 static const u32 coeff_table
[] = {1, 2, 3, 4, 6, 8, 12, 16};
286 u32 gccr_imax
= UINT_MAX
;
290 for (i
= 0; i
< ARRAY_SIZE(coeff_table
); i
++) {
293 /* select closest ones */
294 imax
= coeff_table
[i
] * AW200XX_IMAX_MULTIPLIER1
;
295 if (g_imax_uA
>= imax
&& imax
> cur_imax
) {
297 gccr_imax
= i
+ AW200XX_IMAX_BASE_VAL1
;
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
) {
304 gccr_imax
= i
+ AW200XX_IMAX_BASE_VAL2
;
308 if (gccr_imax
== UINT_MAX
)
311 return regmap_update_bits(chip
->regmap
, AW200XX_REG_GCCR
,
312 AW200XX_GCCR_IMAX_MASK
,
313 AW200XX_GCCR_IMAX(gccr_imax
));
316 static int aw200xx_chip_reset(const struct aw200xx
*const chip
)
320 ret
= regmap_write(chip
->regmap
, AW200XX_REG_RSTR
, AW200XX_RSTR_RESET
);
324 /* According to the datasheet software reset takes at least 1ms */
327 regcache_mark_dirty(chip
->regmap
);
328 return regmap_write(chip
->regmap
, AW200XX_REG_FCD
, AW200XX_FCD_CLEAR
);
331 static int aw200xx_chip_init(const struct aw200xx
*const chip
)
335 ret
= regmap_write(chip
->regmap
, AW200XX_REG_DSIZE
,
336 chip
->display_rows
- 1);
340 ret
= regmap_write(chip
->regmap
, AW200XX_REG_SLPCR
,
341 AW200XX_SLPCR_ACTIVE
);
345 return regmap_update_bits(chip
->regmap
, AW200XX_REG_GCCR
,
346 AW200XX_GCCR_ALLON
, AW200XX_GCCR_ALLON
);
349 static int aw200xx_chip_check(const struct aw200xx
*const chip
)
351 struct device
*dev
= &chip
->client
->dev
;
355 ret
= regmap_read(chip
->regmap
, AW200XX_REG_IDR
, &chipid
);
357 return dev_err_probe(dev
, ret
, "Failed to read chip ID\n");
359 if (chipid
!= AW200XX_IDR_CHIPID
)
360 return dev_err_probe(dev
, -ENODEV
,
361 "Chip reported wrong ID: %x\n", chipid
);
366 static void aw200xx_enable(const struct aw200xx
*const chip
)
368 gpiod_set_value_cansleep(chip
->hwen
, 1);
371 * After HWEN pin set high the chip begins to load the OTP information,
372 * which takes 200us to complete. About 200us wait time is needed for
373 * internal oscillator startup and display SRAM initialization. After
374 * display SRAM initialization, the registers in page1 to page5 can be
375 * configured via i2c interface.
380 static void aw200xx_disable(const struct aw200xx
*const chip
)
382 return gpiod_set_value_cansleep(chip
->hwen
, 0);
385 static int aw200xx_probe_get_display_rows(struct device
*dev
,
386 struct aw200xx
*chip
)
388 struct fwnode_handle
*child
;
391 device_for_each_child_node(dev
, child
) {
395 ret
= fwnode_property_read_u32(child
, "reg", &source
);
396 if (ret
|| source
>= chip
->cdef
->channels
)
399 max_source
= max(max_source
, source
);
405 chip
->display_rows
= max_source
/ chip
->cdef
->display_size_columns
+ 1;
410 static int aw200xx_probe_fw(struct device
*dev
, struct aw200xx
*chip
)
412 struct fwnode_handle
*child
;
413 u32 current_min
, current_max
, min_uA
;
417 ret
= aw200xx_probe_get_display_rows(dev
, chip
);
419 return dev_err_probe(dev
, ret
,
420 "No valid led definitions found\n");
422 current_max
= aw200xx_imax_from_global(chip
, AW200XX_IMAX_MAX_uA
);
423 current_min
= aw200xx_imax_from_global(chip
, AW200XX_IMAX_MIN_uA
);
427 device_for_each_child_node(dev
, child
) {
428 struct led_init_data init_data
= {};
429 struct aw200xx_led
*led
;
432 ret
= fwnode_property_read_u32(child
, "reg", &source
);
434 dev_err(dev
, "Missing reg property\n");
439 if (source
>= chip
->cdef
->channels
) {
440 dev_err(dev
, "LED reg %u out of range (max %u)\n",
441 source
, chip
->cdef
->channels
);
446 ret
= fwnode_property_read_u32(child
, "led-max-microamp",
449 dev_info(&chip
->client
->dev
,
450 "DT property led-max-microamp is missing\n");
451 } else if (imax
< current_min
|| imax
> current_max
) {
452 dev_err(dev
, "Invalid value %u for led-max-microamp\n",
457 min_uA
= min(min_uA
, imax
);
460 led
= &chip
->leds
[i
];
464 led
->cdev
.brightness_set_blocking
= aw200xx_brightness_set
;
465 led
->cdev
.max_brightness
= AW200XX_FADE_MAX
;
466 led
->cdev
.groups
= dim_groups
;
467 init_data
.fwnode
= child
;
469 ret
= devm_led_classdev_register_ext(dev
, &led
->cdev
,
472 fwnode_handle_put(child
);
482 if (min_uA
== UINT_MAX
) {
483 min_uA
= aw200xx_imax_from_global(chip
,
484 AW200XX_IMAX_DEFAULT_uA
);
487 return aw200xx_set_imax(chip
, min_uA
);
490 static const struct regmap_range_cfg aw200xx_ranges
[] = {
494 .range_max
= AW200XX_REG_MAX
,
495 .selector_reg
= AW200XX_REG_PAGE
,
496 .selector_mask
= AW200XX_PAGE_MASK
,
497 .selector_shift
= AW200XX_PAGE_SHIFT
,
499 .window_len
= AW200XX_PAGE_SIZE
,
503 static const struct regmap_range aw200xx_writeonly_ranges
[] = {
504 regmap_reg_range(AW200XX_REG(AW200XX_PAGE1
, 0x00), AW200XX_REG_MAX
),
507 static const struct regmap_access_table aw200xx_readable_table
= {
508 .no_ranges
= aw200xx_writeonly_ranges
,
509 .n_no_ranges
= ARRAY_SIZE(aw200xx_writeonly_ranges
),
512 static const struct regmap_range aw200xx_readonly_ranges
[] = {
513 regmap_reg_range(AW200XX_REG_IDR
, AW200XX_REG_IDR
),
516 static const struct regmap_access_table aw200xx_writeable_table
= {
517 .no_ranges
= aw200xx_readonly_ranges
,
518 .n_no_ranges
= ARRAY_SIZE(aw200xx_readonly_ranges
),
521 static const struct regmap_config aw200xx_regmap_config
= {
524 .max_register
= AW200XX_REG_MAX
,
525 .ranges
= aw200xx_ranges
,
526 .num_ranges
= ARRAY_SIZE(aw200xx_ranges
),
527 .rd_table
= &aw200xx_readable_table
,
528 .wr_table
= &aw200xx_writeable_table
,
529 .cache_type
= REGCACHE_MAPLE
,
530 .disable_locking
= true,
533 static void aw200xx_chip_reset_action(void *data
)
535 aw200xx_chip_reset(data
);
538 static void aw200xx_disable_action(void *data
)
540 aw200xx_disable(data
);
543 static int aw200xx_probe(struct i2c_client
*client
)
545 const struct aw200xx_chipdef
*cdef
;
546 struct aw200xx
*chip
;
550 cdef
= device_get_match_data(&client
->dev
);
554 count
= device_get_child_node_count(&client
->dev
);
555 if (!count
|| count
> cdef
->channels
)
556 return dev_err_probe(&client
->dev
, -EINVAL
,
557 "Incorrect number of leds (%d)", count
);
559 chip
= devm_kzalloc(&client
->dev
, struct_size(chip
, leds
, count
),
565 chip
->num_leds
= count
;
566 chip
->client
= client
;
567 i2c_set_clientdata(client
, chip
);
569 chip
->regmap
= devm_regmap_init_i2c(client
, &aw200xx_regmap_config
);
570 if (IS_ERR(chip
->regmap
))
571 return PTR_ERR(chip
->regmap
);
573 chip
->hwen
= devm_gpiod_get_optional(&client
->dev
, "enable",
575 if (IS_ERR(chip
->hwen
))
576 return dev_err_probe(&client
->dev
, PTR_ERR(chip
->hwen
),
577 "Cannot get enable GPIO");
579 aw200xx_enable(chip
);
581 ret
= devm_add_action(&client
->dev
, aw200xx_disable_action
, chip
);
585 ret
= aw200xx_chip_check(chip
);
589 ret
= devm_mutex_init(&client
->dev
, &chip
->mutex
);
593 /* Need a lock now since after call aw200xx_probe_fw, sysfs nodes created */
594 mutex_lock(&chip
->mutex
);
596 ret
= aw200xx_chip_reset(chip
);
600 ret
= devm_add_action(&client
->dev
, aw200xx_chip_reset_action
, chip
);
604 ret
= aw200xx_probe_fw(&client
->dev
, chip
);
608 ret
= aw200xx_chip_init(chip
);
612 aw200xx_disable(chip
);
614 mutex_unlock(&chip
->mutex
);
618 static const struct aw200xx_chipdef aw20036_cdef
= {
620 .display_size_rows_max
= 3,
621 .display_size_columns
= 12,
624 static const struct aw200xx_chipdef aw20054_cdef
= {
626 .display_size_rows_max
= 6,
627 .display_size_columns
= 9,
630 static const struct aw200xx_chipdef aw20072_cdef
= {
632 .display_size_rows_max
= 6,
633 .display_size_columns
= 12,
636 static const struct aw200xx_chipdef aw20108_cdef
= {
638 .display_size_rows_max
= 9,
639 .display_size_columns
= 12,
642 static const struct i2c_device_id aw200xx_id
[] = {
649 MODULE_DEVICE_TABLE(i2c
, aw200xx_id
);
651 static const struct of_device_id aw200xx_match_table
[] = {
652 { .compatible
= "awinic,aw20036", .data
= &aw20036_cdef
, },
653 { .compatible
= "awinic,aw20054", .data
= &aw20054_cdef
, },
654 { .compatible
= "awinic,aw20072", .data
= &aw20072_cdef
, },
655 { .compatible
= "awinic,aw20108", .data
= &aw20108_cdef
, },
658 MODULE_DEVICE_TABLE(of
, aw200xx_match_table
);
660 static struct i2c_driver aw200xx_driver
= {
663 .of_match_table
= aw200xx_match_table
,
665 .probe
= aw200xx_probe
,
666 .id_table
= aw200xx_id
,
668 module_i2c_driver(aw200xx_driver
);
670 MODULE_AUTHOR("Martin Kurbanov <mmkurbanov@sberdevices.ru>");
671 MODULE_DESCRIPTION("AW200XX LED driver");
672 MODULE_LICENSE("GPL");