1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2014 Belkin Inc.
4 * Copyright 2015 Andrew Lunn <andrew@lunn.ch>
8 #include <linux/leds.h>
9 #include <linux/module.h>
11 #include <linux/of_device.h>
12 #include <linux/regmap.h>
13 #include <linux/slab.h>
15 #define TLC591XX_MAX_LEDS 16
16 #define TLC591XX_MAX_BRIGHTNESS 256
18 #define TLC591XX_REG_MODE1 0x00
19 #define MODE1_RESPON_ADDR_MASK 0xF0
20 #define MODE1_NORMAL_MODE (0 << 4)
21 #define MODE1_SPEED_MODE (1 << 4)
23 #define TLC591XX_REG_MODE2 0x01
24 #define MODE2_DIM (0 << 5)
25 #define MODE2_BLINK (1 << 5)
26 #define MODE2_OCH_STOP (0 << 3)
27 #define MODE2_OCH_ACK (1 << 3)
29 #define TLC591XX_REG_PWM(x) (0x02 + (x))
31 #define TLC591XX_REG_GRPPWM 0x12
32 #define TLC591XX_REG_GRPFREQ 0x13
34 /* LED Driver Output State, determine the source that drives LED outputs */
35 #define LEDOUT_OFF 0x0 /* Output LOW */
36 #define LEDOUT_ON 0x1 /* Output HI-Z */
37 #define LEDOUT_DIM 0x2 /* Dimming */
38 #define LEDOUT_BLINK 0x3 /* Blinking */
39 #define LEDOUT_MASK 0x3
41 #define ldev_to_led(c) container_of(c, struct tlc591xx_led, ldev)
46 struct led_classdev ldev
;
47 struct tlc591xx_priv
*priv
;
50 struct tlc591xx_priv
{
51 struct tlc591xx_led leds
[TLC591XX_MAX_LEDS
];
52 struct regmap
*regmap
;
53 unsigned int reg_ledout_offset
;
57 unsigned int max_leds
;
58 unsigned int reg_ledout_offset
;
61 static const struct tlc591xx tlc59116
= {
63 .reg_ledout_offset
= 0x14,
66 static const struct tlc591xx tlc59108
= {
68 .reg_ledout_offset
= 0x0c,
72 tlc591xx_set_mode(struct regmap
*regmap
, u8 mode
)
77 err
= regmap_write(regmap
, TLC591XX_REG_MODE1
, MODE1_NORMAL_MODE
);
81 val
= MODE2_OCH_STOP
| mode
;
83 return regmap_write(regmap
, TLC591XX_REG_MODE2
, val
);
87 tlc591xx_set_ledout(struct tlc591xx_priv
*priv
, struct tlc591xx_led
*led
,
90 unsigned int i
= (led
->led_no
% 4) * 2;
91 unsigned int mask
= LEDOUT_MASK
<< i
;
92 unsigned int addr
= priv
->reg_ledout_offset
+ (led
->led_no
>> 2);
96 return regmap_update_bits(priv
->regmap
, addr
, mask
, val
);
100 tlc591xx_set_pwm(struct tlc591xx_priv
*priv
, struct tlc591xx_led
*led
,
103 u8 pwm
= TLC591XX_REG_PWM(led
->led_no
);
105 return regmap_write(priv
->regmap
, pwm
, brightness
);
109 tlc591xx_brightness_set(struct led_classdev
*led_cdev
,
110 enum led_brightness brightness
)
112 struct tlc591xx_led
*led
= ldev_to_led(led_cdev
);
113 struct tlc591xx_priv
*priv
= led
->priv
;
116 switch ((int)brightness
) {
118 err
= tlc591xx_set_ledout(priv
, led
, LEDOUT_OFF
);
120 case TLC591XX_MAX_BRIGHTNESS
:
121 err
= tlc591xx_set_ledout(priv
, led
, LEDOUT_ON
);
124 err
= tlc591xx_set_ledout(priv
, led
, LEDOUT_DIM
);
126 err
= tlc591xx_set_pwm(priv
, led
, brightness
);
132 static const struct regmap_config tlc591xx_regmap
= {
135 .max_register
= 0x1e,
138 static const struct of_device_id of_tlc591xx_leds_match
[] = {
139 { .compatible
= "ti,tlc59116",
141 { .compatible
= "ti,tlc59108",
145 MODULE_DEVICE_TABLE(of
, of_tlc591xx_leds_match
);
148 tlc591xx_probe(struct i2c_client
*client
,
149 const struct i2c_device_id
*id
)
151 struct device_node
*np
= client
->dev
.of_node
, *child
;
152 struct device
*dev
= &client
->dev
;
153 const struct of_device_id
*match
;
154 const struct tlc591xx
*tlc591xx
;
155 struct tlc591xx_priv
*priv
;
158 match
= of_match_device(of_tlc591xx_leds_match
, dev
);
162 tlc591xx
= match
->data
;
166 count
= of_get_child_count(np
);
167 if (!count
|| count
> tlc591xx
->max_leds
)
170 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
174 priv
->regmap
= devm_regmap_init_i2c(client
, &tlc591xx_regmap
);
175 if (IS_ERR(priv
->regmap
)) {
176 err
= PTR_ERR(priv
->regmap
);
177 dev_err(dev
, "Failed to allocate register map: %d\n", err
);
180 priv
->reg_ledout_offset
= tlc591xx
->reg_ledout_offset
;
182 i2c_set_clientdata(client
, priv
);
184 err
= tlc591xx_set_mode(priv
->regmap
, MODE2_DIM
);
188 for_each_child_of_node(np
, child
) {
189 struct tlc591xx_led
*led
;
190 struct led_init_data init_data
= {};
192 init_data
.fwnode
= of_fwnode_handle(child
);
194 err
= of_property_read_u32(child
, "reg", ®
);
199 if (reg
< 0 || reg
>= tlc591xx
->max_leds
||
200 priv
->leds
[reg
].active
) {
204 led
= &priv
->leds
[reg
];
207 led
->ldev
.default_trigger
=
208 of_get_property(child
, "linux,default-trigger", NULL
);
212 led
->ldev
.brightness_set_blocking
= tlc591xx_brightness_set
;
213 led
->ldev
.max_brightness
= TLC591XX_MAX_BRIGHTNESS
;
214 err
= devm_led_classdev_register_ext(dev
, &led
->ldev
,
217 dev_err(dev
, "couldn't register LED %s\n",
225 static const struct i2c_device_id tlc591xx_id
[] = {
230 MODULE_DEVICE_TABLE(i2c
, tlc591xx_id
);
232 static struct i2c_driver tlc591xx_driver
= {
235 .of_match_table
= of_match_ptr(of_tlc591xx_leds_match
),
237 .probe
= tlc591xx_probe
,
238 .id_table
= tlc591xx_id
,
241 module_i2c_driver(tlc591xx_driver
);
243 MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
244 MODULE_LICENSE("GPL");
245 MODULE_DESCRIPTION("TLC591XX LED driver");