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 #include <uapi/linux/uleds.h> 12 13 /* 14 * CR0014114 SPI protocol descrtiption: 15 * +----+-----------------------------------+----+ 16 * | CMD| BRIGHTNESS |CRC | 17 * +----+-----------------------------------+----+ 18 * | | LED0| LED1| LED2| LED3| LED4| LED5| | 19 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 20 * | |R|G|B|R|G|B|R|G|B|R|G|B|R|G|B|R|G|B| | 21 * | 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1 | 22 * | |1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1| | 23 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 24 * | | 18 | | 25 * +----+-----------------------------------+----+ 26 * | 20 | 27 * +---------------------------------------------+ 28 * 29 * PS: Boards can be connected to the chain: 30 * SPI -> board0 -> board1 -> board2 .. 31 */ 32 33 /* CR0014114 SPI commands */ 34 #define CR_SET_BRIGHTNESS 0x80 35 #define CR_INIT_REENUMERATE 0x81 36 #define CR_NEXT_REENUMERATE 0x82 37 38 /* CR0014114 default settings */ 39 #define CR_MAX_BRIGHTNESS GENMASK(6, 0) 40 #define CR_FW_DELAY_MSEC 10 41 #define CR_RECOUNT_DELAY (HZ * 3600) 42 43 struct cr0014114_led { 44 char name[LED_MAX_NAME_SIZE]; 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 of %s to %d\n", 171 led->name, brightness); 172 173 mutex_lock(&led->priv->lock); 174 led->brightness = (u8)brightness; 175 ret = cr0014114_sync(led->priv); 176 mutex_unlock(&led->priv->lock); 177 178 return ret; 179 } 180 181 static int cr0014114_probe_dt(struct cr0014114 *priv) 182 { 183 size_t i = 0; 184 struct cr0014114_led *led; 185 struct fwnode_handle *child; 186 struct device_node *np; 187 int ret; 188 const char *str; 189 190 device_for_each_child_node(priv->dev, child) { 191 np = to_of_node(child); 192 led = &priv->leds[i]; 193 194 ret = fwnode_property_read_string(child, "label", &str); 195 if (ret) 196 snprintf(led->name, sizeof(led->name), 197 "cr0014114::"); 198 else 199 snprintf(led->name, sizeof(led->name), 200 "cr0014114:%s", str); 201 202 fwnode_property_read_string(child, "linux,default-trigger", 203 &led->ldev.default_trigger); 204 205 led->priv = priv; 206 led->ldev.name = led->name; 207 led->ldev.max_brightness = CR_MAX_BRIGHTNESS; 208 led->ldev.brightness_set_blocking = cr0014114_set_sync; 209 210 ret = devm_of_led_classdev_register(priv->dev, np, 211 &led->ldev); 212 if (ret) { 213 dev_err(priv->dev, 214 "failed to register LED device %s, err %d", 215 led->name, ret); 216 fwnode_handle_put(child); 217 return ret; 218 } 219 220 led->ldev.dev->of_node = np; 221 222 i++; 223 } 224 225 return 0; 226 } 227 228 static int cr0014114_probe(struct spi_device *spi) 229 { 230 struct cr0014114 *priv; 231 size_t count; 232 int ret; 233 234 count = device_get_child_node_count(&spi->dev); 235 if (!count) { 236 dev_err(&spi->dev, "LEDs are not defined in device tree!"); 237 return -ENODEV; 238 } 239 240 priv = devm_kzalloc(&spi->dev, struct_size(priv, leds, count), 241 GFP_KERNEL); 242 if (!priv) 243 return -ENOMEM; 244 245 priv->buf = devm_kzalloc(&spi->dev, count + 2, GFP_KERNEL); 246 if (!priv->buf) 247 return -ENOMEM; 248 249 mutex_init(&priv->lock); 250 INIT_DELAYED_WORK(&priv->work, cr0014114_recount_work); 251 priv->count = count; 252 priv->dev = &spi->dev; 253 priv->spi = spi; 254 priv->delay = jiffies - 255 msecs_to_jiffies(CR_FW_DELAY_MSEC); 256 257 priv->do_recount = true; 258 ret = cr0014114_sync(priv); 259 if (ret) { 260 dev_err(priv->dev, "first recount failed %d\n", ret); 261 return ret; 262 } 263 264 priv->do_recount = true; 265 ret = cr0014114_sync(priv); 266 if (ret) { 267 dev_err(priv->dev, "second recount failed %d\n", ret); 268 return ret; 269 } 270 271 ret = cr0014114_probe_dt(priv); 272 if (ret) 273 return ret; 274 275 /* setup recount work to workaround buggy firmware */ 276 schedule_delayed_work(&priv->work, CR_RECOUNT_DELAY); 277 278 spi_set_drvdata(spi, priv); 279 280 return 0; 281 } 282 283 static int cr0014114_remove(struct spi_device *spi) 284 { 285 struct cr0014114 *priv = spi_get_drvdata(spi); 286 287 cancel_delayed_work_sync(&priv->work); 288 mutex_destroy(&priv->lock); 289 290 return 0; 291 } 292 293 static const struct of_device_id cr0014114_dt_ids[] = { 294 { .compatible = "crane,cr0014114", }, 295 {}, 296 }; 297 298 MODULE_DEVICE_TABLE(of, cr0014114_dt_ids); 299 300 static struct spi_driver cr0014114_driver = { 301 .probe = cr0014114_probe, 302 .remove = cr0014114_remove, 303 .driver = { 304 .name = KBUILD_MODNAME, 305 .of_match_table = cr0014114_dt_ids, 306 }, 307 }; 308 309 module_spi_driver(cr0014114_driver); 310 311 MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>"); 312 MODULE_DESCRIPTION("cr0014114 LED driver"); 313 MODULE_LICENSE("GPL v2"); 314 MODULE_ALIAS("spi:cr0014114"); 315