leds.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * DIGITAL Shark LED control routines.
  3. *
  4. * Driver for the 3 user LEDs found on the Shark
  5. * Based on Versatile and RealView machine LED code
  6. *
  7. * License terms: GNU General Public License (GPL) version 2
  8. * Author: Bryan Wu <bryan.wu@canonical.com>
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/init.h>
  12. #include <linux/io.h>
  13. #include <linux/ioport.h>
  14. #include <linux/slab.h>
  15. #include <linux/leds.h>
  16. #include <asm/mach-types.h>
  17. #if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
  18. struct shark_led {
  19. struct led_classdev cdev;
  20. u8 mask;
  21. };
  22. /*
  23. * The triggers lines up below will only be used if the
  24. * LED triggers are compiled in.
  25. */
  26. static const struct {
  27. const char *name;
  28. const char *trigger;
  29. } shark_leds[] = {
  30. { "shark:amber0", "default-on", }, /* Bit 5 */
  31. { "shark:green", "heartbeat", }, /* Bit 6 */
  32. { "shark:amber1", "cpu0" }, /* Bit 7 */
  33. };
  34. static u16 led_reg_read(void)
  35. {
  36. outw(0x09, 0x24);
  37. return inw(0x26);
  38. }
  39. static void led_reg_write(u16 value)
  40. {
  41. outw(0x09, 0x24);
  42. outw(value, 0x26);
  43. }
  44. static void shark_led_set(struct led_classdev *cdev,
  45. enum led_brightness b)
  46. {
  47. struct shark_led *led = container_of(cdev,
  48. struct shark_led, cdev);
  49. u16 reg = led_reg_read();
  50. if (b != LED_OFF)
  51. reg |= led->mask;
  52. else
  53. reg &= ~led->mask;
  54. led_reg_write(reg);
  55. }
  56. static enum led_brightness shark_led_get(struct led_classdev *cdev)
  57. {
  58. struct shark_led *led = container_of(cdev,
  59. struct shark_led, cdev);
  60. u16 reg = led_reg_read();
  61. return (reg & led->mask) ? LED_FULL : LED_OFF;
  62. }
  63. static int __init shark_leds_init(void)
  64. {
  65. int i;
  66. u16 reg;
  67. if (!machine_is_shark())
  68. return -ENODEV;
  69. for (i = 0; i < ARRAY_SIZE(shark_leds); i++) {
  70. struct shark_led *led;
  71. led = kzalloc(sizeof(*led), GFP_KERNEL);
  72. if (!led)
  73. break;
  74. led->cdev.name = shark_leds[i].name;
  75. led->cdev.brightness_set = shark_led_set;
  76. led->cdev.brightness_get = shark_led_get;
  77. led->cdev.default_trigger = shark_leds[i].trigger;
  78. /* Count in 5 bits offset */
  79. led->mask = BIT(i + 5);
  80. if (led_classdev_register(NULL, &led->cdev) < 0) {
  81. kfree(led);
  82. break;
  83. }
  84. }
  85. /* Make LEDs independent of power-state */
  86. request_region(0x24, 4, "led_reg");
  87. reg = led_reg_read();
  88. reg |= 1 << 10;
  89. led_reg_write(reg);
  90. return 0;
  91. }
  92. /*
  93. * Since we may have triggers on any subsystem, defer registration
  94. * until after subsystem_init.
  95. */
  96. fs_initcall(shark_leds_init);
  97. #endif