1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2018 Crane Merchandising Systems. All rights reserved.
3 // Copyright (C) 2018 Oleh Kravchenko <oleg@kaa.org.ua>
5 #include <linux/delay.h>
6 #include <linux/leds.h>
7 #include <linux/module.h>
8 #include <linux/of_device.h>
9 #include <linux/spi/spi.h>
10 #include <linux/workqueue.h>
13 * CR0014114 SPI protocol descrtiption:
14 * +----+-----------------------------------+----+
15 * | CMD| BRIGHTNESS |CRC |
16 * +----+-----------------------------------+----+
17 * | | LED0| LED1| LED2| LED3| LED4| LED5| |
18 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
19 * | |R|G|B|R|G|B|R|G|B|R|G|B|R|G|B|R|G|B| |
20 * | 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1 |
21 * | |1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1| |
22 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
24 * +----+-----------------------------------+----+
26 * +---------------------------------------------+
28 * PS: Boards can be connected to the chain:
29 * SPI -> board0 -> board1 -> board2 ..
32 /* CR0014114 SPI commands */
33 #define CR_SET_BRIGHTNESS 0x80
34 #define CR_INIT_REENUMERATE 0x81
35 #define CR_NEXT_REENUMERATE 0x82
37 /* CR0014114 default settings */
38 #define CR_MAX_BRIGHTNESS GENMASK(6, 0)
39 #define CR_FW_DELAY_MSEC 10
40 #define CR_RECOUNT_DELAY (HZ * 3600)
42 #define CR_DEV_NAME "cr0014114"
44 struct cr0014114_led
{
45 struct cr0014114
*priv
;
46 struct led_classdev ldev
;
53 struct delayed_work work
;
56 struct spi_device
*spi
;
59 struct cr0014114_led leds
[];
62 static void cr0014114_calc_crc(u8
*buf
, const size_t len
)
67 for (i
= 1, crc
= 1; i
< len
- 1; i
++)
71 /* special case when CRC matches the SPI commands */
72 if (crc
== CR_SET_BRIGHTNESS
||
73 crc
== CR_INIT_REENUMERATE
||
74 crc
== CR_NEXT_REENUMERATE
)
80 static int cr0014114_recount(struct cr0014114
*priv
)
86 dev_dbg(priv
->dev
, "LEDs recount is started\n");
88 cmd
= CR_INIT_REENUMERATE
;
89 ret
= spi_write(priv
->spi
, &cmd
, sizeof(cmd
));
93 cmd
= CR_NEXT_REENUMERATE
;
94 for (i
= 0; i
< priv
->count
; i
++) {
95 msleep(CR_FW_DELAY_MSEC
);
97 ret
= spi_write(priv
->spi
, &cmd
, sizeof(cmd
));
103 dev_dbg(priv
->dev
, "LEDs recount is finished\n");
106 dev_err(priv
->dev
, "with error %d", ret
);
111 static int cr0014114_sync(struct cr0014114
*priv
)
115 unsigned long udelay
, now
= jiffies
;
117 /* to avoid SPI mistiming with firmware we should wait some time */
118 if (time_after(priv
->delay
, now
)) {
119 udelay
= jiffies_to_usecs(priv
->delay
- now
);
120 usleep_range(udelay
, udelay
+ 1);
123 if (unlikely(priv
->do_recount
)) {
124 ret
= cr0014114_recount(priv
);
128 priv
->do_recount
= false;
129 msleep(CR_FW_DELAY_MSEC
);
132 priv
->buf
[0] = CR_SET_BRIGHTNESS
;
133 for (i
= 0; i
< priv
->count
; i
++)
134 priv
->buf
[i
+ 1] = priv
->leds
[i
].brightness
;
135 cr0014114_calc_crc(priv
->buf
, priv
->count
+ 2);
136 ret
= spi_write(priv
->spi
, priv
->buf
, priv
->count
+ 2);
139 priv
->delay
= jiffies
+ msecs_to_jiffies(CR_FW_DELAY_MSEC
);
144 static void cr0014114_recount_work(struct work_struct
*work
)
147 struct cr0014114
*priv
= container_of(work
,
151 mutex_lock(&priv
->lock
);
152 priv
->do_recount
= true;
153 ret
= cr0014114_sync(priv
);
154 mutex_unlock(&priv
->lock
);
157 dev_warn(priv
->dev
, "sync of LEDs failed %d\n", ret
);
159 schedule_delayed_work(&priv
->work
, CR_RECOUNT_DELAY
);
162 static int cr0014114_set_sync(struct led_classdev
*ldev
,
163 enum led_brightness brightness
)
166 struct cr0014114_led
*led
= container_of(ldev
,
167 struct cr0014114_led
,
170 dev_dbg(led
->priv
->dev
, "Set brightness to %d\n", brightness
);
172 mutex_lock(&led
->priv
->lock
);
173 led
->brightness
= (u8
)brightness
;
174 ret
= cr0014114_sync(led
->priv
);
175 mutex_unlock(&led
->priv
->lock
);
180 static int cr0014114_probe_dt(struct cr0014114
*priv
)
183 struct cr0014114_led
*led
;
184 struct fwnode_handle
*child
;
185 struct led_init_data init_data
= {};
188 device_for_each_child_node(priv
->dev
, child
) {
189 led
= &priv
->leds
[i
];
192 led
->ldev
.max_brightness
= CR_MAX_BRIGHTNESS
;
193 led
->ldev
.brightness_set_blocking
= cr0014114_set_sync
;
195 init_data
.fwnode
= child
;
196 init_data
.devicename
= CR_DEV_NAME
;
197 init_data
.default_label
= ":";
199 ret
= devm_led_classdev_register_ext(priv
->dev
, &led
->ldev
,
203 "failed to register LED device, err %d", ret
);
204 fwnode_handle_put(child
);
214 static int cr0014114_probe(struct spi_device
*spi
)
216 struct cr0014114
*priv
;
220 count
= device_get_child_node_count(&spi
->dev
);
222 dev_err(&spi
->dev
, "LEDs are not defined in device tree!");
226 priv
= devm_kzalloc(&spi
->dev
, struct_size(priv
, leds
, count
),
231 priv
->buf
= devm_kzalloc(&spi
->dev
, count
+ 2, GFP_KERNEL
);
235 mutex_init(&priv
->lock
);
236 INIT_DELAYED_WORK(&priv
->work
, cr0014114_recount_work
);
238 priv
->dev
= &spi
->dev
;
240 priv
->delay
= jiffies
-
241 msecs_to_jiffies(CR_FW_DELAY_MSEC
);
243 priv
->do_recount
= true;
244 ret
= cr0014114_sync(priv
);
246 dev_err(priv
->dev
, "first recount failed %d\n", ret
);
250 priv
->do_recount
= true;
251 ret
= cr0014114_sync(priv
);
253 dev_err(priv
->dev
, "second recount failed %d\n", ret
);
257 ret
= cr0014114_probe_dt(priv
);
261 /* setup recount work to workaround buggy firmware */
262 schedule_delayed_work(&priv
->work
, CR_RECOUNT_DELAY
);
264 spi_set_drvdata(spi
, priv
);
269 static int cr0014114_remove(struct spi_device
*spi
)
271 struct cr0014114
*priv
= spi_get_drvdata(spi
);
273 cancel_delayed_work_sync(&priv
->work
);
274 mutex_destroy(&priv
->lock
);
279 static const struct of_device_id cr0014114_dt_ids
[] = {
280 { .compatible
= "crane,cr0014114", },
284 MODULE_DEVICE_TABLE(of
, cr0014114_dt_ids
);
286 static struct spi_driver cr0014114_driver
= {
287 .probe
= cr0014114_probe
,
288 .remove
= cr0014114_remove
,
290 .name
= KBUILD_MODNAME
,
291 .of_match_table
= cr0014114_dt_ids
,
295 module_spi_driver(cr0014114_driver
);
297 MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>");
298 MODULE_DESCRIPTION("cr0014114 LED driver");
299 MODULE_LICENSE("GPL v2");
300 MODULE_ALIAS("spi:cr0014114");