xref: /linux/drivers/leds/leds-an30259a.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // Driver for Panasonic AN30259A 3-channel LED driver
4 //
5 // Copyright (c) 2018 Simon Shields <simon@lineageos.org>
6 //
7 // Datasheet:
8 // https://www.alliedelec.com/m/d/a9d2b3ee87c2d1a535a41dd747b1c247.pdf
9 
10 #include <linux/i2c.h>
11 #include <linux/leds.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/of.h>
15 #include <linux/regmap.h>
16 
17 #define AN30259A_MAX_LEDS 3
18 
19 #define AN30259A_REG_SRESET 0x00
20 #define AN30259A_LED_SRESET BIT(0)
21 
22 /* LED power registers */
23 #define AN30259A_REG_LED_ON 0x01
24 #define AN30259A_LED_EN(x) BIT((x) - 1)
25 #define AN30259A_LED_SLOPE(x) BIT(((x) - 1) + 4)
26 
27 #define AN30259A_REG_LEDCC(x) (0x03 + ((x) - 1))
28 
29 /* slope control registers */
30 #define AN30259A_REG_SLOPE(x) (0x06 + ((x) - 1))
31 #define AN30259A_LED_SLOPETIME1(x) (x)
32 #define AN30259A_LED_SLOPETIME2(x) ((x) << 4)
33 
34 #define AN30259A_REG_LEDCNT1(x) (0x09 + (4 * ((x) - 1)))
35 #define AN30259A_LED_DUTYMAX(x) ((x) << 4)
36 #define AN30259A_LED_DUTYMID(x) (x)
37 
38 #define AN30259A_REG_LEDCNT2(x) (0x0A + (4 * ((x) - 1)))
39 #define AN30259A_LED_DELAY(x) ((x) << 4)
40 #define AN30259A_LED_DUTYMIN(x) (x)
41 
42 /* detention time control (length of each slope step) */
43 #define AN30259A_REG_LEDCNT3(x) (0x0B + (4 * ((x) - 1)))
44 #define AN30259A_LED_DT1(x) (x)
45 #define AN30259A_LED_DT2(x) ((x) << 4)
46 
47 #define AN30259A_REG_LEDCNT4(x) (0x0C + (4 * ((x) - 1)))
48 #define AN30259A_LED_DT3(x) (x)
49 #define AN30259A_LED_DT4(x) ((x) << 4)
50 
51 #define AN30259A_REG_MAX 0x14
52 
53 #define AN30259A_BLINK_MAX_TIME 7500 /* ms */
54 #define AN30259A_SLOPE_RESOLUTION 500 /* ms */
55 
56 #define AN30259A_NAME "an30259a"
57 
58 struct an30259a;
59 
60 struct an30259a_led {
61 	struct an30259a *chip;
62 	struct fwnode_handle *fwnode;
63 	struct led_classdev cdev;
64 	u32 num;
65 	enum led_default_state default_state;
66 	bool sloping;
67 };
68 
69 struct an30259a {
70 	struct mutex mutex; /* held when writing to registers */
71 	struct i2c_client *client;
72 	struct an30259a_led leds[AN30259A_MAX_LEDS];
73 	struct regmap *regmap;
74 	int num_leds;
75 };
76 
an30259a_brightness_set(struct led_classdev * cdev,enum led_brightness brightness)77 static int an30259a_brightness_set(struct led_classdev *cdev,
78 				   enum led_brightness brightness)
79 {
80 	struct an30259a_led *led;
81 	int ret;
82 	unsigned int led_on;
83 
84 	led = container_of(cdev, struct an30259a_led, cdev);
85 	mutex_lock(&led->chip->mutex);
86 
87 	ret = regmap_read(led->chip->regmap, AN30259A_REG_LED_ON, &led_on);
88 	if (ret)
89 		goto error;
90 
91 	switch (brightness) {
92 	case LED_OFF:
93 		led_on &= ~AN30259A_LED_EN(led->num);
94 		led_on &= ~AN30259A_LED_SLOPE(led->num);
95 		led->sloping = false;
96 		break;
97 	default:
98 		led_on |= AN30259A_LED_EN(led->num);
99 		if (led->sloping)
100 			led_on |= AN30259A_LED_SLOPE(led->num);
101 		ret = regmap_write(led->chip->regmap,
102 				   AN30259A_REG_LEDCNT1(led->num),
103 				   AN30259A_LED_DUTYMAX(0xf) |
104 				   AN30259A_LED_DUTYMID(0xf));
105 		if (ret)
106 			goto error;
107 		break;
108 	}
109 
110 	ret = regmap_write(led->chip->regmap, AN30259A_REG_LED_ON, led_on);
111 	if (ret)
112 		goto error;
113 
114 	ret = regmap_write(led->chip->regmap, AN30259A_REG_LEDCC(led->num),
115 			   brightness);
116 
117 error:
118 	mutex_unlock(&led->chip->mutex);
119 
120 	return ret;
121 }
122 
an30259a_blink_set(struct led_classdev * cdev,unsigned long * delay_off,unsigned long * delay_on)123 static int an30259a_blink_set(struct led_classdev *cdev,
124 			      unsigned long *delay_off, unsigned long *delay_on)
125 {
126 	struct an30259a_led *led;
127 	int ret, num;
128 	unsigned int led_on;
129 	unsigned long off = *delay_off, on = *delay_on;
130 
131 	led = container_of(cdev, struct an30259a_led, cdev);
132 
133 	mutex_lock(&led->chip->mutex);
134 	num = led->num;
135 
136 	/* slope time can only be a multiple of 500ms. */
137 	if (off % AN30259A_SLOPE_RESOLUTION || on % AN30259A_SLOPE_RESOLUTION) {
138 		ret = -EINVAL;
139 		goto error;
140 	}
141 
142 	/* up to a maximum of 7500ms. */
143 	if (off > AN30259A_BLINK_MAX_TIME || on > AN30259A_BLINK_MAX_TIME) {
144 		ret = -EINVAL;
145 		goto error;
146 	}
147 
148 	/* if no blink specified, default to 1 Hz. */
149 	if (!off && !on) {
150 		*delay_off = off = 500;
151 		*delay_on = on = 500;
152 	}
153 
154 	/* convert into values the HW will understand. */
155 	off /= AN30259A_SLOPE_RESOLUTION;
156 	on /= AN30259A_SLOPE_RESOLUTION;
157 
158 	/* duty min should be zero (=off), delay should be zero. */
159 	ret = regmap_write(led->chip->regmap, AN30259A_REG_LEDCNT2(num),
160 			   AN30259A_LED_DELAY(0) | AN30259A_LED_DUTYMIN(0));
161 	if (ret)
162 		goto error;
163 
164 	/* reset detention time (no "breathing" effect). */
165 	ret = regmap_write(led->chip->regmap, AN30259A_REG_LEDCNT3(num),
166 			   AN30259A_LED_DT1(0) | AN30259A_LED_DT2(0));
167 	if (ret)
168 		goto error;
169 	ret = regmap_write(led->chip->regmap, AN30259A_REG_LEDCNT4(num),
170 			   AN30259A_LED_DT3(0) | AN30259A_LED_DT4(0));
171 	if (ret)
172 		goto error;
173 
174 	/* slope time controls on/off cycle length. */
175 	ret = regmap_write(led->chip->regmap, AN30259A_REG_SLOPE(num),
176 			   AN30259A_LED_SLOPETIME1(off) |
177 			   AN30259A_LED_SLOPETIME2(on));
178 	if (ret)
179 		goto error;
180 
181 	/* Finally, enable slope mode. */
182 	ret = regmap_read(led->chip->regmap, AN30259A_REG_LED_ON, &led_on);
183 	if (ret)
184 		goto error;
185 
186 	led_on |= AN30259A_LED_SLOPE(num) | AN30259A_LED_EN(led->num);
187 
188 	ret = regmap_write(led->chip->regmap, AN30259A_REG_LED_ON, led_on);
189 
190 	if (!ret)
191 		led->sloping = true;
192 error:
193 	mutex_unlock(&led->chip->mutex);
194 
195 	return ret;
196 }
197 
an30259a_dt_init(struct i2c_client * client,struct an30259a * chip)198 static int an30259a_dt_init(struct i2c_client *client,
199 			    struct an30259a *chip)
200 {
201 	struct device_node *np = dev_of_node(&client->dev), *child;
202 	int count, ret;
203 	int i = 0;
204 	struct an30259a_led *led;
205 
206 	count = of_get_available_child_count(np);
207 	if (!count || count > AN30259A_MAX_LEDS)
208 		return -EINVAL;
209 
210 	for_each_available_child_of_node(np, child) {
211 		u32 source;
212 
213 		ret = of_property_read_u32(child, "reg", &source);
214 		if (ret != 0 || !source || source > AN30259A_MAX_LEDS) {
215 			dev_err(&client->dev, "Couldn't read LED address: %d\n",
216 				ret);
217 			count--;
218 			continue;
219 		}
220 
221 		led = &chip->leds[i];
222 
223 		led->num = source;
224 		led->chip = chip;
225 		led->fwnode = of_fwnode_handle(child);
226 		led->default_state = led_init_default_state_get(led->fwnode);
227 
228 		i++;
229 	}
230 
231 	if (!count)
232 		return -EINVAL;
233 
234 	chip->num_leds = i;
235 
236 	return 0;
237 }
238 
239 static const struct regmap_config an30259a_regmap_config = {
240 	.reg_bits = 8,
241 	.val_bits = 8,
242 	.max_register = AN30259A_REG_MAX,
243 };
244 
an30259a_init_default_state(struct an30259a_led * led)245 static void an30259a_init_default_state(struct an30259a_led *led)
246 {
247 	struct an30259a *chip = led->chip;
248 	int led_on, err;
249 
250 	switch (led->default_state) {
251 	case LEDS_DEFSTATE_ON:
252 		led->cdev.brightness = LED_FULL;
253 		break;
254 	case LEDS_DEFSTATE_KEEP:
255 		err = regmap_read(chip->regmap, AN30259A_REG_LED_ON, &led_on);
256 		if (err)
257 			break;
258 
259 		if (!(led_on & AN30259A_LED_EN(led->num))) {
260 			led->cdev.brightness = LED_OFF;
261 			break;
262 		}
263 		regmap_read(chip->regmap, AN30259A_REG_LEDCC(led->num),
264 			    &led->cdev.brightness);
265 		break;
266 	default:
267 		led->cdev.brightness = LED_OFF;
268 	}
269 
270 	an30259a_brightness_set(&led->cdev, led->cdev.brightness);
271 }
272 
an30259a_probe(struct i2c_client * client)273 static int an30259a_probe(struct i2c_client *client)
274 {
275 	struct an30259a *chip;
276 	int i, err;
277 
278 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
279 	if (!chip)
280 		return -ENOMEM;
281 
282 	err = an30259a_dt_init(client, chip);
283 	if (err < 0)
284 		return err;
285 
286 	err = devm_mutex_init(&client->dev, &chip->mutex);
287 	if (err)
288 		return err;
289 
290 	chip->client = client;
291 	i2c_set_clientdata(client, chip);
292 
293 	chip->regmap = devm_regmap_init_i2c(client, &an30259a_regmap_config);
294 
295 	if (IS_ERR(chip->regmap)) {
296 		err = PTR_ERR(chip->regmap);
297 		dev_err(&client->dev, "Failed to allocate register map: %d\n",
298 			err);
299 		goto exit;
300 	}
301 
302 	for (i = 0; i < chip->num_leds; i++) {
303 		struct led_init_data init_data = {};
304 
305 		an30259a_init_default_state(&chip->leds[i]);
306 		chip->leds[i].cdev.brightness_set_blocking =
307 			an30259a_brightness_set;
308 		chip->leds[i].cdev.blink_set = an30259a_blink_set;
309 
310 		init_data.fwnode = chip->leds[i].fwnode;
311 		init_data.devicename = AN30259A_NAME;
312 		init_data.default_label = ":";
313 
314 		err = devm_led_classdev_register_ext(&client->dev,
315 						 &chip->leds[i].cdev,
316 						 &init_data);
317 		if (err < 0)
318 			goto exit;
319 	}
320 	return 0;
321 
322 exit:
323 	return err;
324 }
325 
326 static const struct of_device_id an30259a_match_table[] = {
327 	{ .compatible = "panasonic,an30259a", },
328 	{ /* sentinel */ },
329 };
330 
331 MODULE_DEVICE_TABLE(of, an30259a_match_table);
332 
333 static const struct i2c_device_id an30259a_id[] = {
334 	{ "an30259a" },
335 	{ /* sentinel */ }
336 };
337 MODULE_DEVICE_TABLE(i2c, an30259a_id);
338 
339 static struct i2c_driver an30259a_driver = {
340 	.driver = {
341 		.name = "leds-an30259a",
342 		.of_match_table = an30259a_match_table,
343 	},
344 	.probe = an30259a_probe,
345 	.id_table = an30259a_id,
346 };
347 
348 module_i2c_driver(an30259a_driver);
349 
350 MODULE_AUTHOR("Simon Shields <simon@lineageos.org>");
351 MODULE_DESCRIPTION("AN30259A LED driver");
352 MODULE_LICENSE("GPL v2");
353