xref: /linux/drivers/leds/rgb/leds-lp5860-spi.c (revision 49bda4826843be0ef97a162009a29ea3a63f3935)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2025 Pengutronix
4  *
5  * Author: Steffen Trumtrar <kernel@pengutronix.de>
6  */
7 
8 #include <linux/init.h>
9 #include <linux/module.h>
10 #include <linux/mutex.h>
11 #include <linux/of.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
14 #include <linux/spi/spi.h>
15 
16 #include "leds-lp5860.h"
17 
18 #define LP5860_SPI_WRITE_FLAG BIT(13)
19 
20 /*
21  * The lp5860 uses a rather uncommon SPI data format: The R/W flag is on BIT(5) in the two address
22  * bytes; BIT(4) to BIT(0) are don't care. Therefore it has 10 bits for the address and 6 bits for
23  * padding the address. The address bytes are sent MSB first. Matching the cores registers to regmap
24  * results in write_flag_mask being BIT(13).
25  */
26 static const struct regmap_config lp5860_regmap_config = {
27 	.name = "lp5860",
28 	.reg_bits = 10,
29 	.pad_bits = 6,
30 	.val_bits = 8,
31 	.write_flag_mask = LP5860_SPI_WRITE_FLAG,
32 	.reg_format_endian = REGMAP_ENDIAN_BIG,
33 	.max_register = LP5860_MAX_REG,
34 };
35 
lp5860_probe(struct spi_device * spi)36 static int lp5860_probe(struct spi_device *spi)
37 {
38 	struct device *dev = &spi->dev;
39 	struct lp5860 *lp5860;
40 	unsigned int multi_leds;
41 	int ret;
42 
43 	multi_leds = device_get_child_node_count(dev);
44 	if (!multi_leds) {
45 		dev_err(dev, "LEDs are not defined in Device Tree!");
46 		return -ENODEV;
47 	}
48 
49 	if (multi_leds > LP5860_MAX_LED) {
50 		dev_err(dev, "Too many LEDs specified.\n");
51 		return -EINVAL;
52 	}
53 
54 	lp5860 = devm_kzalloc(dev, struct_size(lp5860, leds, multi_leds),
55 			      GFP_KERNEL);
56 	if (!lp5860)
57 		return -ENOMEM;
58 
59 	lp5860->regmap = devm_regmap_init_spi(spi, &lp5860_regmap_config);
60 	if (IS_ERR(lp5860->regmap))
61 		return dev_err_probe(&spi->dev, PTR_ERR(lp5860->regmap),
62 				     "Failed to initialise Regmap.\n");
63 
64 	lp5860->dev = dev;
65 
66 	ret = devm_mutex_init(dev, &lp5860->lock);
67 	if (ret)
68 		return ret;
69 
70 	spi_set_drvdata(spi, lp5860);
71 
72 	return lp5860_device_init(dev);
73 }
74 
lp5860_remove(struct spi_device * spi)75 static void lp5860_remove(struct spi_device *spi)
76 {
77 	lp5860_device_remove(&spi->dev);
78 }
79 
80 static const struct of_device_id lp5860_of_match[] = {
81 	{ .compatible = "ti,lp5860" },
82 	{}
83 };
84 MODULE_DEVICE_TABLE(of, lp5860_of_match);
85 
86 static struct spi_driver lp5860_driver = {
87 	.driver = {
88 		.name = "lp5860-spi",
89 		.of_match_table = lp5860_of_match,
90 	},
91 	.probe	= lp5860_probe,
92 	.remove = lp5860_remove,
93 };
94 module_spi_driver(lp5860_driver);
95 
96 MODULE_AUTHOR("Steffen Trumtrar <kernel@pengutronix.de>");
97 MODULE_DESCRIPTION("TI LP5860 RGB LED SPI driver");
98 MODULE_LICENSE("GPL");
99