leds-versatile.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * Driver for the 8 user LEDs found on the RealViews and Versatiles
  3. * Based on DaVinci's DM365 board code
  4. *
  5. * License terms: GNU General Public License (GPL) version 2
  6. * Author: Linus Walleij <triad@df.lth.se>
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/init.h>
  10. #include <linux/module.h>
  11. #include <linux/io.h>
  12. #include <linux/slab.h>
  13. #include <linux/leds.h>
  14. #include <linux/platform_device.h>
  15. struct versatile_led {
  16. void __iomem *base;
  17. struct led_classdev cdev;
  18. u8 mask;
  19. };
  20. /*
  21. * The triggers lines up below will only be used if the
  22. * LED triggers are compiled in.
  23. */
  24. static const struct {
  25. const char *name;
  26. const char *trigger;
  27. } versatile_leds[] = {
  28. { "versatile:0", "heartbeat", },
  29. { "versatile:1", "mmc0", },
  30. { "versatile:2", "cpu0" },
  31. { "versatile:3", "cpu1" },
  32. { "versatile:4", "cpu2" },
  33. { "versatile:5", "cpu3" },
  34. { "versatile:6", },
  35. { "versatile:7", },
  36. };
  37. static void versatile_led_set(struct led_classdev *cdev,
  38. enum led_brightness b)
  39. {
  40. struct versatile_led *led = container_of(cdev,
  41. struct versatile_led, cdev);
  42. u32 reg = readl(led->base);
  43. if (b != LED_OFF)
  44. reg |= led->mask;
  45. else
  46. reg &= ~led->mask;
  47. writel(reg, led->base);
  48. }
  49. static enum led_brightness versatile_led_get(struct led_classdev *cdev)
  50. {
  51. struct versatile_led *led = container_of(cdev,
  52. struct versatile_led, cdev);
  53. u32 reg = readl(led->base);
  54. return (reg & led->mask) ? LED_FULL : LED_OFF;
  55. }
  56. static int versatile_leds_probe(struct platform_device *dev)
  57. {
  58. int i;
  59. struct resource *res;
  60. void __iomem *base;
  61. res = platform_get_resource(dev, IORESOURCE_MEM, 0);
  62. base = devm_ioremap_resource(&dev->dev, res);
  63. if (IS_ERR(base))
  64. return PTR_ERR(base);
  65. /* All off */
  66. writel(0, base);
  67. for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) {
  68. struct versatile_led *led;
  69. led = kzalloc(sizeof(*led), GFP_KERNEL);
  70. if (!led)
  71. break;
  72. led->base = base;
  73. led->cdev.name = versatile_leds[i].name;
  74. led->cdev.brightness_set = versatile_led_set;
  75. led->cdev.brightness_get = versatile_led_get;
  76. led->cdev.default_trigger = versatile_leds[i].trigger;
  77. led->mask = BIT(i);
  78. if (led_classdev_register(NULL, &led->cdev) < 0) {
  79. kfree(led);
  80. break;
  81. }
  82. }
  83. return 0;
  84. }
  85. static struct platform_driver versatile_leds_driver = {
  86. .driver = {
  87. .name = "versatile-leds",
  88. },
  89. .probe = versatile_leds_probe,
  90. };
  91. module_platform_driver(versatile_leds_driver);
  92. MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
  93. MODULE_DESCRIPTION("ARM Versatile LED driver");
  94. MODULE_LICENSE("GPL v2");