Lines Matching +full:spi +full:- +full:crc

1 // SPDX-License-Identifier: GPL-2.0
9 #include <linux/spi/spi.h>
13 * CR0014114 SPI protocol descrtiption:
14 * +----+-----------------------------------+----+
15 * | CMD| BRIGHTNESS |CRC |
16 * +----+-----------------------------------+----+
18 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
20 * | 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1 |
22 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
24 * +----+-----------------------------------+----+
26 * +---------------------------------------------+
29 * SPI -> board0 -> board1 -> board2 ..
32 /* CR0014114 SPI commands */
56 struct spi_device *spi; member
65 u8 crc; in cr0014114_calc_crc() local
67 for (i = 1, crc = 1; i < len - 1; i++) in cr0014114_calc_crc()
68 crc += buf[i]; in cr0014114_calc_crc()
69 crc |= BIT(7); in cr0014114_calc_crc()
71 /* special case when CRC matches the SPI commands */ in cr0014114_calc_crc()
72 if (crc == CR_SET_BRIGHTNESS || in cr0014114_calc_crc()
73 crc == CR_INIT_REENUMERATE || in cr0014114_calc_crc()
74 crc == CR_NEXT_REENUMERATE) in cr0014114_calc_crc()
75 crc = 0xfe; in cr0014114_calc_crc()
77 buf[len - 1] = crc; in cr0014114_calc_crc()
86 dev_dbg(priv->dev, "LEDs recount is started\n"); in cr0014114_recount()
89 ret = spi_write(priv->spi, &cmd, sizeof(cmd)); in cr0014114_recount()
94 for (i = 0; i < priv->count; i++) { in cr0014114_recount()
97 ret = spi_write(priv->spi, &cmd, sizeof(cmd)); in cr0014114_recount()
103 dev_dbg(priv->dev, "LEDs recount is finished\n"); in cr0014114_recount()
106 dev_err(priv->dev, "with error %d", ret); in cr0014114_recount()
117 /* to avoid SPI mistiming with firmware we should wait some time */ in cr0014114_sync()
118 if (time_after(priv->delay, now)) { in cr0014114_sync()
119 udelay = jiffies_to_usecs(priv->delay - now); in cr0014114_sync()
123 if (unlikely(priv->do_recount)) { in cr0014114_sync()
128 priv->do_recount = false; in cr0014114_sync()
132 priv->buf[0] = CR_SET_BRIGHTNESS; in cr0014114_sync()
133 for (i = 0; i < priv->count; i++) in cr0014114_sync()
134 priv->buf[i + 1] = priv->leds[i].brightness; in cr0014114_sync()
135 cr0014114_calc_crc(priv->buf, priv->count + 2); in cr0014114_sync()
136 ret = spi_write(priv->spi, priv->buf, priv->count + 2); in cr0014114_sync()
139 priv->delay = jiffies + msecs_to_jiffies(CR_FW_DELAY_MSEC); in cr0014114_sync()
151 mutex_lock(&priv->lock); in cr0014114_recount_work()
152 priv->do_recount = true; in cr0014114_recount_work()
154 mutex_unlock(&priv->lock); in cr0014114_recount_work()
157 dev_warn(priv->dev, "sync of LEDs failed %d\n", ret); in cr0014114_recount_work()
159 schedule_delayed_work(&priv->work, CR_RECOUNT_DELAY); in cr0014114_recount_work()
170 dev_dbg(led->priv->dev, "Set brightness to %d\n", brightness); in cr0014114_set_sync()
172 mutex_lock(&led->priv->lock); in cr0014114_set_sync()
173 led->brightness = (u8)brightness; in cr0014114_set_sync()
174 ret = cr0014114_sync(led->priv); in cr0014114_set_sync()
175 mutex_unlock(&led->priv->lock); in cr0014114_set_sync()
188 device_for_each_child_node(priv->dev, child) { in cr0014114_probe_dt()
189 led = &priv->leds[i]; in cr0014114_probe_dt()
191 led->priv = priv; in cr0014114_probe_dt()
192 led->ldev.max_brightness = CR_MAX_BRIGHTNESS; in cr0014114_probe_dt()
193 led->ldev.brightness_set_blocking = cr0014114_set_sync; in cr0014114_probe_dt()
199 ret = devm_led_classdev_register_ext(priv->dev, &led->ldev, in cr0014114_probe_dt()
202 dev_err(priv->dev, in cr0014114_probe_dt()
214 static int cr0014114_probe(struct spi_device *spi) in cr0014114_probe() argument
220 count = device_get_child_node_count(&spi->dev); in cr0014114_probe()
222 dev_err(&spi->dev, "LEDs are not defined in device tree!"); in cr0014114_probe()
223 return -ENODEV; in cr0014114_probe()
226 priv = devm_kzalloc(&spi->dev, struct_size(priv, leds, count), in cr0014114_probe()
229 return -ENOMEM; in cr0014114_probe()
231 priv->buf = devm_kzalloc(&spi->dev, count + 2, GFP_KERNEL); in cr0014114_probe()
232 if (!priv->buf) in cr0014114_probe()
233 return -ENOMEM; in cr0014114_probe()
235 mutex_init(&priv->lock); in cr0014114_probe()
236 INIT_DELAYED_WORK(&priv->work, cr0014114_recount_work); in cr0014114_probe()
237 priv->count = count; in cr0014114_probe()
238 priv->dev = &spi->dev; in cr0014114_probe()
239 priv->spi = spi; in cr0014114_probe()
240 priv->delay = jiffies - in cr0014114_probe()
243 priv->do_recount = true; in cr0014114_probe()
246 dev_err(priv->dev, "first recount failed %d\n", ret); in cr0014114_probe()
250 priv->do_recount = true; in cr0014114_probe()
253 dev_err(priv->dev, "second recount failed %d\n", ret); in cr0014114_probe()
262 schedule_delayed_work(&priv->work, CR_RECOUNT_DELAY); in cr0014114_probe()
264 spi_set_drvdata(spi, priv); in cr0014114_probe()
269 static void cr0014114_remove(struct spi_device *spi) in cr0014114_remove() argument
271 struct cr0014114 *priv = spi_get_drvdata(spi); in cr0014114_remove()
273 cancel_delayed_work_sync(&priv->work); in cr0014114_remove()
274 mutex_destroy(&priv->lock); in cr0014114_remove()
298 MODULE_ALIAS("spi:cr0014114");