leds.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * arch/arm/mach-shark/leds.c
  3. * by Alexander Schulz
  4. *
  5. * derived from:
  6. * arch/arm/kernel/leds-footbridge.c
  7. * Copyright (C) 1998-1999 Russell King
  8. *
  9. * DIGITAL Shark LED control routines.
  10. *
  11. * The leds use is as follows:
  12. * - Green front - toggles state every 50 timer interrupts
  13. * - Amber front - Unused, this is a dual color led (Amber/Green)
  14. * - Amber back - On if system is not idle
  15. *
  16. * Changelog:
  17. */
  18. #include <linux/kernel.h>
  19. #include <linux/module.h>
  20. #include <linux/init.h>
  21. #include <linux/spinlock.h>
  22. #include <linux/ioport.h>
  23. #include <asm/hardware.h>
  24. #include <asm/leds.h>
  25. #include <asm/io.h>
  26. #include <asm/system.h>
  27. #define LED_STATE_ENABLED 1
  28. #define LED_STATE_CLAIMED 2
  29. static char led_state;
  30. static short hw_led_state;
  31. static short saved_state;
  32. static DEFINE_SPINLOCK(leds_lock);
  33. short sequoia_read(int addr) {
  34. outw(addr,0x24);
  35. return inw(0x26);
  36. }
  37. void sequoia_write(short value,short addr) {
  38. outw(addr,0x24);
  39. outw(value,0x26);
  40. }
  41. static void sequoia_leds_event(led_event_t evt)
  42. {
  43. unsigned long flags;
  44. spin_lock_irqsave(&leds_lock, flags);
  45. hw_led_state = sequoia_read(0x09);
  46. switch (evt) {
  47. case led_start:
  48. hw_led_state |= SEQUOIA_LED_GREEN;
  49. hw_led_state |= SEQUOIA_LED_AMBER;
  50. #ifdef CONFIG_LEDS_CPU
  51. hw_led_state |= SEQUOIA_LED_BACK;
  52. #else
  53. hw_led_state &= ~SEQUOIA_LED_BACK;
  54. #endif
  55. led_state |= LED_STATE_ENABLED;
  56. break;
  57. case led_stop:
  58. hw_led_state &= ~SEQUOIA_LED_BACK;
  59. hw_led_state |= SEQUOIA_LED_GREEN;
  60. hw_led_state |= SEQUOIA_LED_AMBER;
  61. led_state &= ~LED_STATE_ENABLED;
  62. break;
  63. case led_claim:
  64. led_state |= LED_STATE_CLAIMED;
  65. saved_state = hw_led_state;
  66. hw_led_state &= ~SEQUOIA_LED_BACK;
  67. hw_led_state |= SEQUOIA_LED_GREEN;
  68. hw_led_state |= SEQUOIA_LED_AMBER;
  69. break;
  70. case led_release:
  71. led_state &= ~LED_STATE_CLAIMED;
  72. hw_led_state = saved_state;
  73. break;
  74. #ifdef CONFIG_LEDS_TIMER
  75. case led_timer:
  76. if (!(led_state & LED_STATE_CLAIMED))
  77. hw_led_state ^= SEQUOIA_LED_GREEN;
  78. break;
  79. #endif
  80. #ifdef CONFIG_LEDS_CPU
  81. case led_idle_start:
  82. if (!(led_state & LED_STATE_CLAIMED))
  83. hw_led_state &= ~SEQUOIA_LED_BACK;
  84. break;
  85. case led_idle_end:
  86. if (!(led_state & LED_STATE_CLAIMED))
  87. hw_led_state |= SEQUOIA_LED_BACK;
  88. break;
  89. #endif
  90. case led_green_on:
  91. if (led_state & LED_STATE_CLAIMED)
  92. hw_led_state &= ~SEQUOIA_LED_GREEN;
  93. break;
  94. case led_green_off:
  95. if (led_state & LED_STATE_CLAIMED)
  96. hw_led_state |= SEQUOIA_LED_GREEN;
  97. break;
  98. case led_amber_on:
  99. if (led_state & LED_STATE_CLAIMED)
  100. hw_led_state &= ~SEQUOIA_LED_AMBER;
  101. break;
  102. case led_amber_off:
  103. if (led_state & LED_STATE_CLAIMED)
  104. hw_led_state |= SEQUOIA_LED_AMBER;
  105. break;
  106. case led_red_on:
  107. if (led_state & LED_STATE_CLAIMED)
  108. hw_led_state |= SEQUOIA_LED_BACK;
  109. break;
  110. case led_red_off:
  111. if (led_state & LED_STATE_CLAIMED)
  112. hw_led_state &= ~SEQUOIA_LED_BACK;
  113. break;
  114. default:
  115. break;
  116. }
  117. if (led_state & LED_STATE_ENABLED)
  118. sequoia_write(hw_led_state,0x09);
  119. spin_unlock_irqrestore(&leds_lock, flags);
  120. }
  121. static int __init leds_init(void)
  122. {
  123. extern void (*leds_event)(led_event_t);
  124. short temp;
  125. leds_event = sequoia_leds_event;
  126. /* Make LEDs independent of power-state */
  127. request_region(0x24,4,"sequoia");
  128. temp = sequoia_read(0x09);
  129. temp |= 1<<10;
  130. sequoia_write(temp,0x09);
  131. leds_event(led_start);
  132. return 0;
  133. }
  134. __initcall(leds_init);