xref: /linux/drivers/leds/leds-lp5569.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2024 Christian Marangi <ansuelsmth@gmail.com>
4  */
5 
6 #include <linux/bitfield.h>
7 #include <linux/cleanup.h>
8 #include <linux/delay.h>
9 #include <linux/firmware.h>
10 #include <linux/i2c.h>
11 #include <linux/iopoll.h>
12 #include <linux/leds.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
15 #include <linux/of.h>
16 #include <linux/platform_data/leds-lp55xx.h>
17 #include <linux/slab.h>
18 #include <dt-bindings/leds/leds-lp55xx.h>
19 
20 #include "leds-lp55xx-common.h"
21 
22 #define LP5569_MAX_LEDS			9
23 
24 /* Memory is used like this:
25  * 0x00 engine 1 program (4 pages)
26  * 0x40 engine 2 program (4 pages)
27  * 0x80 engine 3 program (4 pages)
28  * 0xc0 engine 1 muxing info (1 page)
29  * 0xd0 engine 2 muxing info (1 page)
30  * 0xe0 engine 3 muxing info (1 page)
31  */
32 #define LP5569_PAGES_PER_ENGINE		4
33 
34 #define LP5569_REG_ENABLE		0x00
35 #define   LP5569_ENABLE			BIT(6)
36 
37 #define LP5569_REG_EXEC_CTRL		0x01
38 #define   LP5569_MODE_ENG_SHIFT		2
39 
40 #define LP5569_REG_OP_MODE		0x02
41 #define   LP5569_EXEC_ENG_SHIFT		2
42 
43 #define LP5569_REG_ENABLE_LEDS_MSB	0x04
44 #define LP5569_REG_ENABLE_LEDS_LSB	0x05
45 #define LP5569_REG_LED_CTRL_BASE	0x07
46 #define   LP5569_FADER_MAPPING_MASK	GENMASK(7, 5)
47 #define LP5569_REG_LED_PWM_BASE		0x16
48 #define LP5569_REG_LED_CURRENT_BASE	0x22
49 #define LP5569_REG_MISC			0x2F
50 #define   LP5569_AUTO_INC		BIT(6)
51 #define   LP5569_PWR_SAVE		BIT(5)
52 #define   LP5569_CP_MODE_MASK		GENMASK(4, 3)
53 #define   LP5569_PWM_PWR_SAVE		BIT(2)
54 #define   LP5569_INTERNAL_CLK		BIT(0)
55 #define LP5569_REG_MISC2		0x33
56 #define   LP5569_LED_SHORT_TEST		BIT(4)
57 #define   LP5569_LED_OPEN_TEST		BIT(3)
58 #define LP5569_REG_STATUS		0x3C
59 #define   LP5569_MASK_BUSY		BIT(7)
60 #define   LP5569_STARTUP_BUSY		BIT(6)
61 #define   LP5569_ENGINE_BUSY		BIT(5)
62 #define   LP5569_ENGINE1_INT		BIT(2)
63 #define   LP5569_ENGINE2_INT		BIT(1)
64 #define   LP5569_ENGINE3_INT		BIT(0)
65 #define   LP5569_ENG_STATUS_MASK	(LP5569_ENGINE1_INT | LP5569_ENGINE2_INT | \
66 					 LP5569_ENGINE3_INT)
67 #define LP5569_REG_IO_CONTROL		0x3D
68 #define   LP5569_CLK_OUTPUT		BIT(3)
69 #define LP5569_REG_RESET		0x3F
70 #define   LP5569_RESET			0xFF
71 #define LP5569_REG_MASTER_FADER_BASE	0x46
72 #define LP5569_REG_CH1_PROG_START	0x4B
73 #define LP5569_REG_CH2_PROG_START	0x4C
74 #define LP5569_REG_CH3_PROG_START	0x4D
75 #define LP5569_REG_PROG_PAGE_SEL	0x4F
76 #define LP5569_REG_PROG_MEM		0x50
77 #define LP5569_REG_LED_FAULT1		0x81
78 #define   LP5569_LED_FAULT8		BIT(0)
79 #define LP5569_REG_LED_FAULT2		0x82
80 #define   LP5569_LED_FAULT7		BIT(7)
81 #define   LP5569_LED_FAULT6		BIT(6)
82 #define   LP5569_LED_FAULT5		BIT(5)
83 #define   LP5569_LED_FAULT4		BIT(4)
84 #define   LP5569_LED_FAULT3		BIT(3)
85 #define   LP5569_LED_FAULT2		BIT(2)
86 #define   LP5569_LED_FAULT1		BIT(1)
87 #define   LP5569_LED_FAULT0		BIT(0)
88 
89 #define LP5569_ENG1_PROG_ADDR		0x0
90 #define LP5569_ENG2_PROG_ADDR		0x40
91 #define LP5569_ENG3_PROG_ADDR		0x80
92 #define LP5569_ENG1_MUX_ADDR		0xc0
93 #define LP5569_ENG2_MUX_ADDR		0xd0
94 #define LP5569_ENG3_MUX_ADDR		0xe0
95 
96 #define LP5569_STARTUP_SLEEP		500
97 
98 #define LEDn_STATUS_FAULT(n, status)	((status) >> (n) & BIT(0))
99 
100 #define LP5569_DEFAULT_CONFIG \
101 	(LP5569_AUTO_INC | LP5569_PWR_SAVE | LP5569_PWM_PWR_SAVE)
102 
lp5569_run_engine(struct lp55xx_chip * chip,bool start)103 static void lp5569_run_engine(struct lp55xx_chip *chip, bool start)
104 {
105 	if (!start) {
106 		lp55xx_stop_engine(chip);
107 		lp55xx_turn_off_channels(chip);
108 		return;
109 	}
110 
111 	lp55xx_run_engine_common(chip);
112 }
113 
lp5569_init_program_engine(struct lp55xx_chip * chip)114 static int lp5569_init_program_engine(struct lp55xx_chip *chip)
115 {
116 	int i;
117 	int j;
118 	int ret;
119 	u8 status;
120 	/* Precompiled pattern per ENGINE setting LED MUX start and stop addresses */
121 	static const u8 pattern[][LP55xx_BYTES_PER_PAGE] =  {
122 		{ 0x9c, LP5569_ENG1_MUX_ADDR, 0x9c, 0xb0, 0x9d, 0x80, 0xd8, 0x00, 0},
123 		{ 0x9c, LP5569_ENG2_MUX_ADDR, 0x9c, 0xc0, 0x9d, 0x80, 0xd8, 0x00, 0},
124 		{ 0x9c, LP5569_ENG3_MUX_ADDR, 0x9c, 0xd0, 0x9d, 0x80, 0xd8, 0x00, 0},
125 	};
126 
127 	/* Setup each ENGINE program start address */
128 	ret = lp55xx_write(chip, LP5569_REG_CH1_PROG_START, LP5569_ENG1_PROG_ADDR);
129 	if (ret)
130 		return ret;
131 
132 	ret = lp55xx_write(chip, LP5569_REG_CH2_PROG_START, LP5569_ENG2_PROG_ADDR);
133 	if (ret)
134 		return ret;
135 
136 	ret = lp55xx_write(chip, LP5569_REG_CH3_PROG_START, LP5569_ENG3_PROG_ADDR);
137 	if (ret)
138 		return ret;
139 
140 	/* Write precompiled pattern for LED MUX address space for each ENGINE */
141 	for (i = LP55XX_ENGINE_1; i <= LP55XX_ENGINE_3; i++) {
142 		chip->engine_idx = i;
143 		lp55xx_load_engine(chip);
144 
145 		for (j = 0; j < LP55xx_BYTES_PER_PAGE; j++) {
146 			ret = lp55xx_write(chip, LP5569_REG_PROG_MEM + j,
147 					   pattern[i - 1][j]);
148 			if (ret)
149 				goto out;
150 		}
151 	}
152 
153 	lp5569_run_engine(chip, true);
154 
155 	/* Let the programs run for couple of ms and check the engine status */
156 	usleep_range(3000, 6000);
157 	lp55xx_read(chip, LP5569_REG_STATUS, &status);
158 	status = FIELD_GET(LP5569_ENG_STATUS_MASK, status);
159 
160 	if (status != LP5569_ENG_STATUS_MASK) {
161 		dev_err(&chip->cl->dev,
162 			"could not configure LED engine, status = 0x%.2x\n",
163 			status);
164 		ret = -EINVAL;
165 	}
166 
167 out:
168 	lp55xx_stop_all_engine(chip);
169 	return ret;
170 }
171 
lp5569_post_init_device(struct lp55xx_chip * chip)172 static int lp5569_post_init_device(struct lp55xx_chip *chip)
173 {
174 	int ret;
175 	u8 val;
176 
177 	val = LP5569_DEFAULT_CONFIG;
178 	val |= FIELD_PREP(LP5569_CP_MODE_MASK, chip->pdata->charge_pump_mode);
179 	ret = lp55xx_write(chip, LP5569_REG_MISC, val);
180 	if (ret)
181 		return ret;
182 
183 	if (chip->pdata->clock_mode == LP55XX_CLOCK_INT) {
184 		/* Internal clock MUST be configured before CLK output */
185 		ret = lp55xx_update_bits(chip, LP5569_REG_MISC,
186 					 LP5569_INTERNAL_CLK,
187 					 LP5569_INTERNAL_CLK);
188 		if (ret)
189 			return ret;
190 
191 		ret = lp55xx_update_bits(chip, LP5569_REG_IO_CONTROL,
192 					 LP5569_CLK_OUTPUT,
193 					 LP5569_CLK_OUTPUT);
194 		if (ret)
195 			return ret;
196 	}
197 
198 	ret = lp55xx_write(chip, LP5569_REG_ENABLE, LP5569_ENABLE);
199 	if (ret)
200 		return ret;
201 
202 	read_poll_timeout(lp55xx_read, ret, !(val & LP5569_STARTUP_BUSY),
203 			  LP5569_STARTUP_SLEEP, LP5569_STARTUP_SLEEP * 10, false,
204 			  chip, LP5569_REG_STATUS, &val);
205 
206 	return lp5569_init_program_engine(chip);
207 }
208 
lp5569_led_open_test(struct lp55xx_led * led,char * buf)209 static ssize_t lp5569_led_open_test(struct lp55xx_led *led, char *buf)
210 {
211 	struct lp55xx_chip *chip = led->chip;
212 	struct lp55xx_platform_data *pdata = chip->pdata;
213 	bool leds_fault[LP5569_MAX_LEDS];
214 	struct lp55xx_led *led_tmp = led;
215 	int i, ret, pos = 0;
216 	u8 status;
217 
218 	/* Set in STANDBY state */
219 	ret = lp55xx_write(chip, LP5569_REG_ENABLE, 0);
220 	if (ret)
221 		goto exit;
222 
223 	/* Wait 1ms for device to enter STANDBY state */
224 	usleep_range(1000, 2000);
225 
226 	/* Set Charge Pump to 1.5x */
227 	ret = lp55xx_update_bits(chip, LP5569_REG_MISC,
228 				 FIELD_PREP(LP5569_CP_MODE_MASK, LP55XX_CP_BOOST),
229 				 LP5569_CP_MODE_MASK);
230 	if (ret)
231 		goto exit;
232 
233 	/* Enable LED Open Test */
234 	ret = lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_OPEN_TEST,
235 				 LP5569_LED_OPEN_TEST);
236 	if (ret)
237 		goto exit;
238 
239 	/* Put Device in NORMAL state */
240 	ret = lp55xx_write(chip, LP5569_REG_ENABLE, LP5569_ENABLE);
241 	if (ret)
242 		goto exit;
243 
244 	/* Wait 500 us for device to enter NORMAL state */
245 	usleep_range(500, 750);
246 
247 	/* Enable LED and set to 100% brightness */
248 	for (i = 0; i < pdata->num_channels; i++) {
249 		ret = lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led_tmp->chan_nr,
250 				   LED_FULL);
251 		if (ret)
252 			goto exit;
253 
254 		led_tmp++;
255 	}
256 
257 	/* Wait 500 us for device to fill status regs */
258 	usleep_range(500, 750);
259 
260 	/* Parse status led fault 1 regs */
261 	ret = lp55xx_read(chip, LP5569_REG_LED_FAULT1, &status);
262 	if (ret < 0)
263 		goto exit;
264 
265 	for (i = 0; i < 8; i++)
266 		leds_fault[i] = !!((status >> i) & 0x1);
267 
268 	/* Parse status led fault 2 regs */
269 	ret = lp55xx_read(chip, LP5569_REG_LED_FAULT2, &status);
270 	if (ret < 0)
271 		goto exit;
272 
273 	for (i = 0; i < 1; i++)
274 		leds_fault[i + 8] = !!((status >> i) & 0x1);
275 
276 	/* Report LED fault */
277 	led_tmp = led;
278 	for (i = 0; i < pdata->num_channels; i++) {
279 		if (leds_fault[led_tmp->chan_nr])
280 			pos += sysfs_emit_at(buf, pos, "LED %d OPEN FAIL\n",
281 					     led_tmp->chan_nr);
282 
283 		led_tmp++;
284 	}
285 
286 	ret = pos;
287 
288 exit:
289 	/* Disable LED Open Test */
290 	lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_OPEN_TEST, 0);
291 
292 	led_tmp = led;
293 	for (i = 0; i < pdata->num_channels; i++) {
294 		lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led_tmp->chan_nr, 0);
295 
296 		led_tmp++;
297 	}
298 
299 	return ret;
300 }
301 
lp5569_led_short_test(struct lp55xx_led * led,char * buf)302 static ssize_t lp5569_led_short_test(struct lp55xx_led *led, char *buf)
303 {
304 	struct lp55xx_chip *chip = led->chip;
305 	struct lp55xx_platform_data *pdata = chip->pdata;
306 	bool leds_fault[LP5569_MAX_LEDS];
307 	struct lp55xx_led *led_tmp = led;
308 	int i, ret, pos = 0;
309 	u8 status;
310 
311 	/* Set in STANDBY state */
312 	ret = lp55xx_write(chip, LP5569_REG_ENABLE, 0);
313 	if (ret)
314 		goto exit;
315 
316 	/* Wait 1ms for device to enter STANDBY state */
317 	usleep_range(1000, 2000);
318 
319 	/* Set Charge Pump to 1x */
320 	ret = lp55xx_update_bits(chip, LP5569_REG_MISC,
321 				 FIELD_PREP(LP5569_CP_MODE_MASK, LP55XX_CP_BYPASS),
322 				 LP5569_CP_MODE_MASK);
323 	if (ret)
324 		goto exit;
325 
326 	/* Enable LED and set to 100% brightness and current to 100% (25.5mA) */
327 	for (i = 0; i < pdata->num_channels; i++) {
328 		ret = lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led_tmp->chan_nr,
329 				   LED_FULL);
330 		if (ret)
331 			goto exit;
332 
333 		ret = lp55xx_write(chip, LP5569_REG_LED_CURRENT_BASE + led_tmp->chan_nr,
334 				   LED_FULL);
335 		if (ret)
336 			goto exit;
337 
338 		led_tmp++;
339 	}
340 
341 	/* Put Device in NORMAL state */
342 	ret = lp55xx_write(chip, LP5569_REG_ENABLE, LP5569_ENABLE);
343 	if (ret)
344 		goto exit;
345 
346 	/* Wait 500 us for device to enter NORMAL state */
347 	usleep_range(500, 750);
348 
349 	/* Enable LED Shorted Test */
350 	ret = lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_OPEN_TEST,
351 				 LP5569_LED_SHORT_TEST);
352 	if (ret)
353 		goto exit;
354 
355 	/* Wait 500 us for device to fill status regs */
356 	usleep_range(500, 750);
357 
358 	/* Parse status led fault 1 regs */
359 	ret = lp55xx_read(chip, LP5569_REG_LED_FAULT1, &status);
360 	if (ret < 0)
361 		goto exit;
362 
363 	for (i = 0; i < 8; i++)
364 		leds_fault[i] = !!LEDn_STATUS_FAULT(i, status);
365 
366 	/* Parse status led fault 2 regs */
367 	ret = lp55xx_read(chip, LP5569_REG_LED_FAULT2, &status);
368 	if (ret < 0)
369 		goto exit;
370 
371 	for (i = 0; i < 1; i++)
372 		leds_fault[i + 8] = !!LEDn_STATUS_FAULT(i, status);
373 
374 	/* Report LED fault */
375 	led_tmp = led;
376 	for (i = 0; i < pdata->num_channels; i++) {
377 		if (leds_fault[led_tmp->chan_nr])
378 			pos += sysfs_emit_at(buf, pos, "LED %d SHORTED FAIL\n",
379 					     led_tmp->chan_nr);
380 
381 		led_tmp++;
382 	}
383 
384 	ret = pos;
385 
386 exit:
387 	/* Disable LED Shorted Test */
388 	lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_SHORT_TEST, 0);
389 
390 	led_tmp = led;
391 	for (i = 0; i < pdata->num_channels; i++) {
392 		lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led_tmp->chan_nr, 0);
393 
394 		led_tmp++;
395 	}
396 
397 	return ret;
398 }
399 
lp5569_selftest(struct device * dev,struct device_attribute * attr,char * buf)400 static ssize_t lp5569_selftest(struct device *dev,
401 			       struct device_attribute *attr,
402 			       char *buf)
403 {
404 	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
405 	struct lp55xx_chip *chip = led->chip;
406 	int i, pos = 0;
407 
408 	guard(mutex)(&chip->lock);
409 
410 	/* Test LED Open */
411 	pos = lp5569_led_open_test(led, buf);
412 	if (pos < 0)
413 		return sprintf(buf, "FAIL\n");
414 
415 	/* Test LED Shorted */
416 	pos += lp5569_led_short_test(led, buf);
417 	if (pos < 0)
418 		return sprintf(buf, "FAIL\n");
419 
420 	for (i = 0; i < chip->pdata->num_channels; i++) {
421 		/* Restore current */
422 		lp55xx_write(chip, LP5569_REG_LED_CURRENT_BASE + led->chan_nr,
423 			     led->led_current);
424 
425 		/* Restore brightness */
426 		lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led->chan_nr,
427 			     led->brightness);
428 		led++;
429 	}
430 
431 	return pos == 0 ? sysfs_emit(buf, "OK\n") : pos;
432 }
433 
434 LP55XX_DEV_ATTR_ENGINE_MODE(1);
435 LP55XX_DEV_ATTR_ENGINE_MODE(2);
436 LP55XX_DEV_ATTR_ENGINE_MODE(3);
437 LP55XX_DEV_ATTR_ENGINE_LEDS(1);
438 LP55XX_DEV_ATTR_ENGINE_LEDS(2);
439 LP55XX_DEV_ATTR_ENGINE_LEDS(3);
440 LP55XX_DEV_ATTR_ENGINE_LOAD(1);
441 LP55XX_DEV_ATTR_ENGINE_LOAD(2);
442 LP55XX_DEV_ATTR_ENGINE_LOAD(3);
443 static LP55XX_DEV_ATTR_RO(selftest, lp5569_selftest);
444 LP55XX_DEV_ATTR_MASTER_FADER(1);
445 LP55XX_DEV_ATTR_MASTER_FADER(2);
446 LP55XX_DEV_ATTR_MASTER_FADER(3);
447 static LP55XX_DEV_ATTR_RW(master_fader_leds, lp55xx_show_master_fader_leds,
448 			  lp55xx_store_master_fader_leds);
449 
450 static struct attribute *lp5569_attributes[] = {
451 	&dev_attr_engine1_mode.attr,
452 	&dev_attr_engine2_mode.attr,
453 	&dev_attr_engine3_mode.attr,
454 	&dev_attr_engine1_load.attr,
455 	&dev_attr_engine2_load.attr,
456 	&dev_attr_engine3_load.attr,
457 	&dev_attr_engine1_leds.attr,
458 	&dev_attr_engine2_leds.attr,
459 	&dev_attr_engine3_leds.attr,
460 	&dev_attr_selftest.attr,
461 	&dev_attr_master_fader1.attr,
462 	&dev_attr_master_fader2.attr,
463 	&dev_attr_master_fader3.attr,
464 	&dev_attr_master_fader_leds.attr,
465 	NULL,
466 };
467 
468 static const struct attribute_group lp5569_group = {
469 	.attrs = lp5569_attributes,
470 };
471 
472 /* Chip specific configurations */
473 static struct lp55xx_device_config lp5569_cfg = {
474 	.reg_op_mode = {
475 		.addr = LP5569_REG_OP_MODE,
476 		.shift = LP5569_MODE_ENG_SHIFT,
477 	},
478 	.reg_exec = {
479 		.addr = LP5569_REG_EXEC_CTRL,
480 		.shift = LP5569_EXEC_ENG_SHIFT,
481 	},
482 	.reset = {
483 		.addr = LP5569_REG_RESET,
484 		.val  = LP5569_RESET,
485 	},
486 	.enable = {
487 		.addr = LP5569_REG_ENABLE,
488 		.val  = LP5569_ENABLE,
489 	},
490 	.prog_mem_base = {
491 		.addr = LP5569_REG_PROG_MEM,
492 	},
493 	.reg_led_pwm_base = {
494 		.addr = LP5569_REG_LED_PWM_BASE,
495 	},
496 	.reg_led_current_base = {
497 		.addr = LP5569_REG_LED_CURRENT_BASE,
498 	},
499 	.reg_master_fader_base = {
500 		.addr = LP5569_REG_MASTER_FADER_BASE,
501 	},
502 	.reg_led_ctrl_base = {
503 		.addr = LP5569_REG_LED_CTRL_BASE,
504 	},
505 	.pages_per_engine   = LP5569_PAGES_PER_ENGINE,
506 	.max_channel  = LP5569_MAX_LEDS,
507 	.post_init_device   = lp5569_post_init_device,
508 	.brightness_fn      = lp55xx_led_brightness,
509 	.multicolor_brightness_fn = lp55xx_multicolor_brightness,
510 	.set_led_current    = lp55xx_set_led_current,
511 	.firmware_cb        = lp55xx_firmware_loaded_cb,
512 	.run_engine         = lp5569_run_engine,
513 	.dev_attr_group     = &lp5569_group,
514 };
515 
516 static const struct i2c_device_id lp5569_id[] = {
517 	{ "lp5569",  .driver_data = (kernel_ulong_t)&lp5569_cfg, },
518 	{ }
519 };
520 
521 MODULE_DEVICE_TABLE(i2c, lp5569_id);
522 
523 static const struct of_device_id of_lp5569_leds_match[] = {
524 	{ .compatible = "ti,lp5569", .data = &lp5569_cfg, },
525 	{},
526 };
527 
528 MODULE_DEVICE_TABLE(of, of_lp5569_leds_match);
529 
530 static struct i2c_driver lp5569_driver = {
531 	.driver = {
532 		.name	= "lp5569",
533 		.of_match_table = of_lp5569_leds_match,
534 	},
535 	.probe		= lp55xx_probe,
536 	.remove		= lp55xx_remove,
537 	.id_table	= lp5569_id,
538 };
539 
540 module_i2c_driver(lp5569_driver);
541 
542 MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
543 MODULE_DESCRIPTION("LP5569 LED engine");
544 MODULE_LICENSE("GPL");
545