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> 4 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> 11 12 /* 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 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 23 * | | 18 | | 24 * +----+-----------------------------------+----+ 25 * | 20 | 26 * +---------------------------------------------+ 27 * 28 * PS: Boards can be connected to the chain: 29 * SPI -> board0 -> board1 -> board2 .. 30 */ 31 32 /* CR0014114 SPI commands */ 33 #define CR_SET_BRIGHTNESS 0x80 34 #define CR_INIT_REENUMERATE 0x81 35 #define CR_NEXT_REENUMERATE 0x82 36 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) 41 42 #define CR_DEV_NAME "cr0014114" 43 44 struct cr0014114_led { 45 struct cr0014114 *priv; 46 struct led_classdev ldev; 47 u8 brightness; 48 }; 49 50 struct cr0014114 { 51 bool do_recount; 52 size_t count; 53 struct delayed_work work; 54 struct device *dev; 55 struct mutex lock; 56 struct spi_device *spi; 57 u8 *buf; 58 unsigned long delay; 59 struct cr0014114_led leds[]; 60 }; 61 62 static void cr0014114_calc_crc(u8 *buf, const size_t len) 63 { 64 size_t i; 65 u8 crc; 66 67 for (i = 1, crc = 1; i < len - 1; i++) 68 crc += buf[i]; 69 crc |= BIT(7); 70 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) 75 crc = 0xfe; 76 77 buf[len - 1] = crc; 78 } 79 80 static int cr0014114_recount(struct cr0014114 *priv) 81 { 82 int ret; 83 size_t i; 84 u8 cmd; 85 86 dev_dbg(priv->dev, "LEDs recount is started\n"); 87 88 cmd = CR_INIT_REENUMERATE; 89 ret = spi_write(priv->spi, &cmd, sizeof(cmd)); 90 if (ret) 91 goto err; 92 93 cmd = CR_NEXT_REENUMERATE; 94 for (i = 0; i < priv->count; i++) { 95 msleep(CR_FW_DELAY_MSEC); 96 97 ret = spi_write(priv->spi, &cmd, sizeof(cmd)); 98 if (ret) 99 goto err; 100 } 101 102 err: 103 dev_dbg(priv->dev, "LEDs recount is finished\n"); 104 105 if (ret) 106 dev_err(priv->dev, "with error %d", ret); 107 108 return ret; 109 } 110 111 static int cr0014114_sync(struct cr0014114 *priv) 112 { 113 int ret; 114 size_t i; 115 unsigned long udelay, now = jiffies; 116 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); 121 } 122 123 if (unlikely(priv->do_recount)) { 124 ret = cr0014114_recount(priv); 125 if (ret) 126 goto err; 127 128 priv->do_recount = false; 129 msleep(CR_FW_DELAY_MSEC); 130 } 131 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); 137 138 err: 139 priv->delay = jiffies + msecs_to_jiffies(CR_FW_DELAY_MSEC); 140 141 return ret; 142 } 143 144 static void cr0014114_recount_work(struct work_struct *work) 145 { 146 int ret; 147 struct cr0014114 *priv = container_of(work, 148 struct cr0014114, 149 work.work); 150 151 mutex_lock(&priv->lock); 152 priv->do_recount = true; 153 ret = cr0014114_sync(priv); 154 mutex_unlock(&priv->lock); 155 156 if (ret) 157 dev_warn(priv->dev, "sync of LEDs failed %d\n", ret); 158 159 schedule_delayed_work(&priv->work, CR_RECOUNT_DELAY); 160 } 161 162 static int cr0014114_set_sync(struct led_classdev *ldev, 163 enum led_brightness brightness) 164 { 165 int ret; 166 struct cr0014114_led *led = container_of(ldev, 167 struct cr0014114_led, 168 ldev); 169 170 dev_dbg(led->priv->dev, "Set brightness to %d\n", brightness); 171 172 mutex_lock(&led->priv->lock); 173 led->brightness = (u8)brightness; 174 ret = cr0014114_sync(led->priv); 175 mutex_unlock(&led->priv->lock); 176 177 return ret; 178 } 179 180 static int cr0014114_probe_dt(struct cr0014114 *priv) 181 { 182 size_t i = 0; 183 struct cr0014114_led *led; 184 struct fwnode_handle *child; 185 struct led_init_data init_data = {}; 186 int ret; 187 188 device_for_each_child_node(priv->dev, child) { 189 led = &priv->leds[i]; 190 191 fwnode_property_read_string(child, "linux,default-trigger", 192 &led->ldev.default_trigger); 193 194 led->priv = priv; 195 led->ldev.max_brightness = CR_MAX_BRIGHTNESS; 196 led->ldev.brightness_set_blocking = cr0014114_set_sync; 197 198 init_data.fwnode = child; 199 init_data.devicename = CR_DEV_NAME; 200 init_data.default_label = ":"; 201 202 ret = devm_led_classdev_register_ext(priv->dev, &led->ldev, 203 &init_data); 204 if (ret) { 205 dev_err(priv->dev, 206 "failed to register LED device, err %d", ret); 207 fwnode_handle_put(child); 208 return ret; 209 } 210 211 i++; 212 } 213 214 return 0; 215 } 216 217 static int cr0014114_probe(struct spi_device *spi) 218 { 219 struct cr0014114 *priv; 220 size_t count; 221 int ret; 222 223 count = device_get_child_node_count(&spi->dev); 224 if (!count) { 225 dev_err(&spi->dev, "LEDs are not defined in device tree!"); 226 return -ENODEV; 227 } 228 229 priv = devm_kzalloc(&spi->dev, struct_size(priv, leds, count), 230 GFP_KERNEL); 231 if (!priv) 232 return -ENOMEM; 233 234 priv->buf = devm_kzalloc(&spi->dev, count + 2, GFP_KERNEL); 235 if (!priv->buf) 236 return -ENOMEM; 237 238 mutex_init(&priv->lock); 239 INIT_DELAYED_WORK(&priv->work, cr0014114_recount_work); 240 priv->count = count; 241 priv->dev = &spi->dev; 242 priv->spi = spi; 243 priv->delay = jiffies - 244 msecs_to_jiffies(CR_FW_DELAY_MSEC); 245 246 priv->do_recount = true; 247 ret = cr0014114_sync(priv); 248 if (ret) { 249 dev_err(priv->dev, "first recount failed %d\n", ret); 250 return ret; 251 } 252 253 priv->do_recount = true; 254 ret = cr0014114_sync(priv); 255 if (ret) { 256 dev_err(priv->dev, "second recount failed %d\n", ret); 257 return ret; 258 } 259 260 ret = cr0014114_probe_dt(priv); 261 if (ret) 262 return ret; 263 264 /* setup recount work to workaround buggy firmware */ 265 schedule_delayed_work(&priv->work, CR_RECOUNT_DELAY); 266 267 spi_set_drvdata(spi, priv); 268 269 return 0; 270 } 271 272 static int cr0014114_remove(struct spi_device *spi) 273 { 274 struct cr0014114 *priv = spi_get_drvdata(spi); 275 276 cancel_delayed_work_sync(&priv->work); 277 mutex_destroy(&priv->lock); 278 279 return 0; 280 } 281 282 static const struct of_device_id cr0014114_dt_ids[] = { 283 { .compatible = "crane,cr0014114", }, 284 {}, 285 }; 286 287 MODULE_DEVICE_TABLE(of, cr0014114_dt_ids); 288 289 static struct spi_driver cr0014114_driver = { 290 .probe = cr0014114_probe, 291 .remove = cr0014114_remove, 292 .driver = { 293 .name = KBUILD_MODNAME, 294 .of_match_table = cr0014114_dt_ids, 295 }, 296 }; 297 298 module_spi_driver(cr0014114_driver); 299 300 MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>"); 301 MODULE_DESCRIPTION("cr0014114 LED driver"); 302 MODULE_LICENSE("GPL v2"); 303 MODULE_ALIAS("spi:cr0014114"); 304