1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * leds-netxbig.c - Driver for the 2Big and 5Big Network series LEDs 4 * 5 * Copyright (C) 2010 LaCie 6 * 7 * Author: Simon Guinot <sguinot@lacie.com> 8 */ 9 10 #include <linux/module.h> 11 #include <linux/irq.h> 12 #include <linux/slab.h> 13 #include <linux/spinlock.h> 14 #include <linux/platform_device.h> 15 #include <linux/gpio.h> 16 #include <linux/of_gpio.h> 17 #include <linux/leds.h> 18 19 struct netxbig_gpio_ext { 20 unsigned int *addr; 21 int num_addr; 22 unsigned int *data; 23 int num_data; 24 unsigned int enable; 25 }; 26 27 enum netxbig_led_mode { 28 NETXBIG_LED_OFF, 29 NETXBIG_LED_ON, 30 NETXBIG_LED_SATA, 31 NETXBIG_LED_TIMER1, 32 NETXBIG_LED_TIMER2, 33 NETXBIG_LED_MODE_NUM, 34 }; 35 36 #define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM 37 38 struct netxbig_led_timer { 39 unsigned long delay_on; 40 unsigned long delay_off; 41 enum netxbig_led_mode mode; 42 }; 43 44 struct netxbig_led { 45 const char *name; 46 const char *default_trigger; 47 int mode_addr; 48 int *mode_val; 49 int bright_addr; 50 int bright_max; 51 }; 52 53 struct netxbig_led_platform_data { 54 struct netxbig_gpio_ext *gpio_ext; 55 struct netxbig_led_timer *timer; 56 int num_timer; 57 struct netxbig_led *leds; 58 int num_leds; 59 }; 60 61 /* 62 * GPIO extension bus. 63 */ 64 65 static DEFINE_SPINLOCK(gpio_ext_lock); 66 67 static void gpio_ext_set_addr(struct netxbig_gpio_ext *gpio_ext, int addr) 68 { 69 int pin; 70 71 for (pin = 0; pin < gpio_ext->num_addr; pin++) 72 gpio_set_value(gpio_ext->addr[pin], (addr >> pin) & 1); 73 } 74 75 static void gpio_ext_set_data(struct netxbig_gpio_ext *gpio_ext, int data) 76 { 77 int pin; 78 79 for (pin = 0; pin < gpio_ext->num_data; pin++) 80 gpio_set_value(gpio_ext->data[pin], (data >> pin) & 1); 81 } 82 83 static void gpio_ext_enable_select(struct netxbig_gpio_ext *gpio_ext) 84 { 85 /* Enable select is done on the raising edge. */ 86 gpio_set_value(gpio_ext->enable, 0); 87 gpio_set_value(gpio_ext->enable, 1); 88 } 89 90 static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext, 91 int addr, int value) 92 { 93 unsigned long flags; 94 95 spin_lock_irqsave(&gpio_ext_lock, flags); 96 gpio_ext_set_addr(gpio_ext, addr); 97 gpio_ext_set_data(gpio_ext, value); 98 gpio_ext_enable_select(gpio_ext); 99 spin_unlock_irqrestore(&gpio_ext_lock, flags); 100 } 101 102 static int gpio_ext_init(struct platform_device *pdev, 103 struct netxbig_gpio_ext *gpio_ext) 104 { 105 int err; 106 int i; 107 108 if (unlikely(!gpio_ext)) 109 return -EINVAL; 110 111 /* Configure address GPIOs. */ 112 for (i = 0; i < gpio_ext->num_addr; i++) { 113 err = devm_gpio_request_one(&pdev->dev, gpio_ext->addr[i], 114 GPIOF_OUT_INIT_LOW, 115 "GPIO extension addr"); 116 if (err) 117 return err; 118 } 119 /* Configure data GPIOs. */ 120 for (i = 0; i < gpio_ext->num_data; i++) { 121 err = devm_gpio_request_one(&pdev->dev, gpio_ext->data[i], 122 GPIOF_OUT_INIT_LOW, 123 "GPIO extension data"); 124 if (err) 125 return err; 126 } 127 /* Configure "enable select" GPIO. */ 128 err = devm_gpio_request_one(&pdev->dev, gpio_ext->enable, 129 GPIOF_OUT_INIT_LOW, 130 "GPIO extension enable"); 131 if (err) 132 return err; 133 134 return 0; 135 } 136 137 /* 138 * Class LED driver. 139 */ 140 141 struct netxbig_led_data { 142 struct netxbig_gpio_ext *gpio_ext; 143 struct led_classdev cdev; 144 int mode_addr; 145 int *mode_val; 146 int bright_addr; 147 struct netxbig_led_timer *timer; 148 int num_timer; 149 enum netxbig_led_mode mode; 150 int sata; 151 spinlock_t lock; 152 }; 153 154 static int netxbig_led_get_timer_mode(enum netxbig_led_mode *mode, 155 unsigned long delay_on, 156 unsigned long delay_off, 157 struct netxbig_led_timer *timer, 158 int num_timer) 159 { 160 int i; 161 162 for (i = 0; i < num_timer; i++) { 163 if (timer[i].delay_on == delay_on && 164 timer[i].delay_off == delay_off) { 165 *mode = timer[i].mode; 166 return 0; 167 } 168 } 169 return -EINVAL; 170 } 171 172 static int netxbig_led_blink_set(struct led_classdev *led_cdev, 173 unsigned long *delay_on, 174 unsigned long *delay_off) 175 { 176 struct netxbig_led_data *led_dat = 177 container_of(led_cdev, struct netxbig_led_data, cdev); 178 enum netxbig_led_mode mode; 179 int mode_val; 180 int ret; 181 182 /* Look for a LED mode with the requested timer frequency. */ 183 ret = netxbig_led_get_timer_mode(&mode, *delay_on, *delay_off, 184 led_dat->timer, led_dat->num_timer); 185 if (ret < 0) 186 return ret; 187 188 mode_val = led_dat->mode_val[mode]; 189 if (mode_val == NETXBIG_LED_INVALID_MODE) 190 return -EINVAL; 191 192 spin_lock_irq(&led_dat->lock); 193 194 gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); 195 led_dat->mode = mode; 196 197 spin_unlock_irq(&led_dat->lock); 198 199 return 0; 200 } 201 202 static void netxbig_led_set(struct led_classdev *led_cdev, 203 enum led_brightness value) 204 { 205 struct netxbig_led_data *led_dat = 206 container_of(led_cdev, struct netxbig_led_data, cdev); 207 enum netxbig_led_mode mode; 208 int mode_val; 209 int set_brightness = 1; 210 unsigned long flags; 211 212 spin_lock_irqsave(&led_dat->lock, flags); 213 214 if (value == LED_OFF) { 215 mode = NETXBIG_LED_OFF; 216 set_brightness = 0; 217 } else { 218 if (led_dat->sata) 219 mode = NETXBIG_LED_SATA; 220 else if (led_dat->mode == NETXBIG_LED_OFF) 221 mode = NETXBIG_LED_ON; 222 else /* Keep 'timer' mode. */ 223 mode = led_dat->mode; 224 } 225 mode_val = led_dat->mode_val[mode]; 226 227 gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); 228 led_dat->mode = mode; 229 /* 230 * Note that the brightness register is shared between all the 231 * SATA LEDs. So, change the brightness setting for a single 232 * SATA LED will affect all the others. 233 */ 234 if (set_brightness) 235 gpio_ext_set_value(led_dat->gpio_ext, 236 led_dat->bright_addr, value); 237 238 spin_unlock_irqrestore(&led_dat->lock, flags); 239 } 240 241 static ssize_t netxbig_led_sata_store(struct device *dev, 242 struct device_attribute *attr, 243 const char *buff, size_t count) 244 { 245 struct led_classdev *led_cdev = dev_get_drvdata(dev); 246 struct netxbig_led_data *led_dat = 247 container_of(led_cdev, struct netxbig_led_data, cdev); 248 unsigned long enable; 249 enum netxbig_led_mode mode; 250 int mode_val; 251 int ret; 252 253 ret = kstrtoul(buff, 10, &enable); 254 if (ret < 0) 255 return ret; 256 257 enable = !!enable; 258 259 spin_lock_irq(&led_dat->lock); 260 261 if (led_dat->sata == enable) { 262 ret = count; 263 goto exit_unlock; 264 } 265 266 if (led_dat->mode != NETXBIG_LED_ON && 267 led_dat->mode != NETXBIG_LED_SATA) 268 mode = led_dat->mode; /* Keep modes 'off' and 'timer'. */ 269 else if (enable) 270 mode = NETXBIG_LED_SATA; 271 else 272 mode = NETXBIG_LED_ON; 273 274 mode_val = led_dat->mode_val[mode]; 275 if (mode_val == NETXBIG_LED_INVALID_MODE) { 276 ret = -EINVAL; 277 goto exit_unlock; 278 } 279 280 gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); 281 led_dat->mode = mode; 282 led_dat->sata = enable; 283 284 ret = count; 285 286 exit_unlock: 287 spin_unlock_irq(&led_dat->lock); 288 289 return ret; 290 } 291 292 static ssize_t netxbig_led_sata_show(struct device *dev, 293 struct device_attribute *attr, char *buf) 294 { 295 struct led_classdev *led_cdev = dev_get_drvdata(dev); 296 struct netxbig_led_data *led_dat = 297 container_of(led_cdev, struct netxbig_led_data, cdev); 298 299 return sprintf(buf, "%d\n", led_dat->sata); 300 } 301 302 static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store); 303 304 static struct attribute *netxbig_led_attrs[] = { 305 &dev_attr_sata.attr, 306 NULL 307 }; 308 ATTRIBUTE_GROUPS(netxbig_led); 309 310 static int create_netxbig_led(struct platform_device *pdev, 311 struct netxbig_led_platform_data *pdata, 312 struct netxbig_led_data *led_dat, 313 const struct netxbig_led *template) 314 { 315 spin_lock_init(&led_dat->lock); 316 led_dat->gpio_ext = pdata->gpio_ext; 317 led_dat->cdev.name = template->name; 318 led_dat->cdev.default_trigger = template->default_trigger; 319 led_dat->cdev.blink_set = netxbig_led_blink_set; 320 led_dat->cdev.brightness_set = netxbig_led_set; 321 /* 322 * Because the GPIO extension bus don't allow to read registers 323 * value, there is no way to probe the LED initial state. 324 * So, the initial sysfs LED value for the "brightness" and "sata" 325 * attributes are inconsistent. 326 * 327 * Note that the initial LED state can't be reconfigured. 328 * The reason is that the LED behaviour must stay uniform during 329 * the whole boot process (bootloader+linux). 330 */ 331 led_dat->sata = 0; 332 led_dat->cdev.brightness = LED_OFF; 333 led_dat->cdev.max_brightness = template->bright_max; 334 led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; 335 led_dat->mode_addr = template->mode_addr; 336 led_dat->mode_val = template->mode_val; 337 led_dat->bright_addr = template->bright_addr; 338 led_dat->timer = pdata->timer; 339 led_dat->num_timer = pdata->num_timer; 340 /* 341 * If available, expose the SATA activity blink capability through 342 * a "sata" sysfs attribute. 343 */ 344 if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) 345 led_dat->cdev.groups = netxbig_led_groups; 346 347 return devm_led_classdev_register(&pdev->dev, &led_dat->cdev); 348 } 349 350 static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np, 351 struct netxbig_gpio_ext *gpio_ext) 352 { 353 int *addr, *data; 354 int num_addr, num_data; 355 int ret; 356 int i; 357 358 ret = of_gpio_named_count(np, "addr-gpios"); 359 if (ret < 0) { 360 dev_err(dev, 361 "Failed to count GPIOs in DT property addr-gpios\n"); 362 return ret; 363 } 364 num_addr = ret; 365 addr = devm_kcalloc(dev, num_addr, sizeof(*addr), GFP_KERNEL); 366 if (!addr) 367 return -ENOMEM; 368 369 for (i = 0; i < num_addr; i++) { 370 ret = of_get_named_gpio(np, "addr-gpios", i); 371 if (ret < 0) 372 return ret; 373 addr[i] = ret; 374 } 375 gpio_ext->addr = addr; 376 gpio_ext->num_addr = num_addr; 377 378 ret = of_gpio_named_count(np, "data-gpios"); 379 if (ret < 0) { 380 dev_err(dev, 381 "Failed to count GPIOs in DT property data-gpios\n"); 382 return ret; 383 } 384 num_data = ret; 385 data = devm_kcalloc(dev, num_data, sizeof(*data), GFP_KERNEL); 386 if (!data) 387 return -ENOMEM; 388 389 for (i = 0; i < num_data; i++) { 390 ret = of_get_named_gpio(np, "data-gpios", i); 391 if (ret < 0) 392 return ret; 393 data[i] = ret; 394 } 395 gpio_ext->data = data; 396 gpio_ext->num_data = num_data; 397 398 ret = of_get_named_gpio(np, "enable-gpio", 0); 399 if (ret < 0) { 400 dev_err(dev, 401 "Failed to get GPIO from DT property enable-gpio\n"); 402 return ret; 403 } 404 gpio_ext->enable = ret; 405 406 return 0; 407 } 408 409 static int netxbig_leds_get_of_pdata(struct device *dev, 410 struct netxbig_led_platform_data *pdata) 411 { 412 struct device_node *np = dev->of_node; 413 struct device_node *gpio_ext_np; 414 struct device_node *child; 415 struct netxbig_gpio_ext *gpio_ext; 416 struct netxbig_led_timer *timers; 417 struct netxbig_led *leds, *led; 418 int num_timers; 419 int num_leds = 0; 420 int ret; 421 int i; 422 423 /* GPIO extension */ 424 gpio_ext_np = of_parse_phandle(np, "gpio-ext", 0); 425 if (!gpio_ext_np) { 426 dev_err(dev, "Failed to get DT handle gpio-ext\n"); 427 return -EINVAL; 428 } 429 430 gpio_ext = devm_kzalloc(dev, sizeof(*gpio_ext), GFP_KERNEL); 431 if (!gpio_ext) { 432 of_node_put(gpio_ext_np); 433 return -ENOMEM; 434 } 435 ret = gpio_ext_get_of_pdata(dev, gpio_ext_np, gpio_ext); 436 of_node_put(gpio_ext_np); 437 if (ret) 438 return ret; 439 pdata->gpio_ext = gpio_ext; 440 441 /* Timers (optional) */ 442 ret = of_property_count_u32_elems(np, "timers"); 443 if (ret > 0) { 444 if (ret % 3) 445 return -EINVAL; 446 num_timers = ret / 3; 447 timers = devm_kcalloc(dev, num_timers, sizeof(*timers), 448 GFP_KERNEL); 449 if (!timers) 450 return -ENOMEM; 451 for (i = 0; i < num_timers; i++) { 452 u32 tmp; 453 454 of_property_read_u32_index(np, "timers", 3 * i, 455 &timers[i].mode); 456 if (timers[i].mode >= NETXBIG_LED_MODE_NUM) 457 return -EINVAL; 458 of_property_read_u32_index(np, "timers", 459 3 * i + 1, &tmp); 460 timers[i].delay_on = tmp; 461 of_property_read_u32_index(np, "timers", 462 3 * i + 2, &tmp); 463 timers[i].delay_off = tmp; 464 } 465 pdata->timer = timers; 466 pdata->num_timer = num_timers; 467 } 468 469 /* LEDs */ 470 num_leds = of_get_child_count(np); 471 if (!num_leds) { 472 dev_err(dev, "No LED subnodes found in DT\n"); 473 return -ENODEV; 474 } 475 476 leds = devm_kcalloc(dev, num_leds, sizeof(*leds), GFP_KERNEL); 477 if (!leds) 478 return -ENOMEM; 479 480 led = leds; 481 for_each_child_of_node(np, child) { 482 const char *string; 483 int *mode_val; 484 int num_modes; 485 486 ret = of_property_read_u32(child, "mode-addr", 487 &led->mode_addr); 488 if (ret) 489 goto err_node_put; 490 491 ret = of_property_read_u32(child, "bright-addr", 492 &led->bright_addr); 493 if (ret) 494 goto err_node_put; 495 496 ret = of_property_read_u32(child, "max-brightness", 497 &led->bright_max); 498 if (ret) 499 goto err_node_put; 500 501 mode_val = 502 devm_kcalloc(dev, 503 NETXBIG_LED_MODE_NUM, sizeof(*mode_val), 504 GFP_KERNEL); 505 if (!mode_val) { 506 ret = -ENOMEM; 507 goto err_node_put; 508 } 509 510 for (i = 0; i < NETXBIG_LED_MODE_NUM; i++) 511 mode_val[i] = NETXBIG_LED_INVALID_MODE; 512 513 ret = of_property_count_u32_elems(child, "mode-val"); 514 if (ret < 0 || ret % 2) { 515 ret = -EINVAL; 516 goto err_node_put; 517 } 518 num_modes = ret / 2; 519 if (num_modes > NETXBIG_LED_MODE_NUM) { 520 ret = -EINVAL; 521 goto err_node_put; 522 } 523 524 for (i = 0; i < num_modes; i++) { 525 int mode; 526 int val; 527 528 of_property_read_u32_index(child, 529 "mode-val", 2 * i, &mode); 530 of_property_read_u32_index(child, 531 "mode-val", 2 * i + 1, &val); 532 if (mode >= NETXBIG_LED_MODE_NUM) { 533 ret = -EINVAL; 534 goto err_node_put; 535 } 536 mode_val[mode] = val; 537 } 538 led->mode_val = mode_val; 539 540 if (!of_property_read_string(child, "label", &string)) 541 led->name = string; 542 else 543 led->name = child->name; 544 545 if (!of_property_read_string(child, 546 "linux,default-trigger", &string)) 547 led->default_trigger = string; 548 549 led++; 550 } 551 552 pdata->leds = leds; 553 pdata->num_leds = num_leds; 554 555 return 0; 556 557 err_node_put: 558 of_node_put(child); 559 return ret; 560 } 561 562 static const struct of_device_id of_netxbig_leds_match[] = { 563 { .compatible = "lacie,netxbig-leds", }, 564 {}, 565 }; 566 MODULE_DEVICE_TABLE(of, of_netxbig_leds_match); 567 568 static int netxbig_led_probe(struct platform_device *pdev) 569 { 570 struct netxbig_led_platform_data *pdata; 571 struct netxbig_led_data *leds_data; 572 int i; 573 int ret; 574 575 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 576 if (!pdata) 577 return -ENOMEM; 578 ret = netxbig_leds_get_of_pdata(&pdev->dev, pdata); 579 if (ret) 580 return ret; 581 582 leds_data = devm_kcalloc(&pdev->dev, 583 pdata->num_leds, sizeof(*leds_data), 584 GFP_KERNEL); 585 if (!leds_data) 586 return -ENOMEM; 587 588 ret = gpio_ext_init(pdev, pdata->gpio_ext); 589 if (ret < 0) 590 return ret; 591 592 for (i = 0; i < pdata->num_leds; i++) { 593 ret = create_netxbig_led(pdev, pdata, 594 &leds_data[i], &pdata->leds[i]); 595 if (ret < 0) 596 return ret; 597 } 598 599 return 0; 600 } 601 602 static struct platform_driver netxbig_led_driver = { 603 .probe = netxbig_led_probe, 604 .driver = { 605 .name = "leds-netxbig", 606 .of_match_table = of_netxbig_leds_match, 607 }, 608 }; 609 610 module_platform_driver(netxbig_led_driver); 611 612 MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); 613 MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards"); 614 MODULE_LICENSE("GPL"); 615 MODULE_ALIAS("platform:leds-netxbig"); 616