leds.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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/io.h>
  11. #include <linux/slab.h>
  12. #include <linux/leds.h>
  13. #include <mach/hardware.h>
  14. #include <mach/platform.h>
  15. #ifdef VERSATILE_SYS_BASE
  16. #define LEDREG (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
  17. #endif
  18. #ifdef REALVIEW_SYS_BASE
  19. #define LEDREG (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET)
  20. #endif
  21. struct versatile_led {
  22. struct led_classdev cdev;
  23. u8 mask;
  24. };
  25. /*
  26. * The triggers lines up below will only be used if the
  27. * LED triggers are compiled in.
  28. */
  29. static const struct {
  30. const char *name;
  31. const char *trigger;
  32. } versatile_leds[] = {
  33. { "versatile:0", "heartbeat", },
  34. { "versatile:1", "mmc0", },
  35. { "versatile:2", },
  36. { "versatile:3", },
  37. { "versatile:4", },
  38. { "versatile:5", },
  39. { "versatile:6", },
  40. { "versatile:7", },
  41. };
  42. static void versatile_led_set(struct led_classdev *cdev,
  43. enum led_brightness b)
  44. {
  45. struct versatile_led *led = container_of(cdev,
  46. struct versatile_led, cdev);
  47. u32 reg = readl(LEDREG);
  48. if (b != LED_OFF)
  49. reg |= led->mask;
  50. else
  51. reg &= ~led->mask;
  52. writel(reg, LEDREG);
  53. }
  54. static enum led_brightness versatile_led_get(struct led_classdev *cdev)
  55. {
  56. struct versatile_led *led = container_of(cdev,
  57. struct versatile_led, cdev);
  58. u32 reg = readl(LEDREG);
  59. return (reg & led->mask) ? LED_FULL : LED_OFF;
  60. }
  61. static int __init versatile_leds_init(void)
  62. {
  63. int i;
  64. /* All ON */
  65. writel(0xff, LEDREG);
  66. for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) {
  67. struct versatile_led *led;
  68. led = kzalloc(sizeof(*led), GFP_KERNEL);
  69. if (!led)
  70. break;
  71. led->cdev.name = versatile_leds[i].name;
  72. led->cdev.brightness_set = versatile_led_set;
  73. led->cdev.brightness_get = versatile_led_get;
  74. led->cdev.default_trigger = versatile_leds[i].trigger;
  75. led->mask = BIT(i);
  76. if (led_classdev_register(NULL, &led->cdev) < 0) {
  77. kfree(led);
  78. break;
  79. }
  80. }
  81. return 0;
  82. }
  83. /*
  84. * Since we may have triggers on any subsystem, defer registration
  85. * until after subsystem_init.
  86. */
  87. fs_initcall(versatile_leds_init);