pc_keyb.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /***********************************************************************
  2. *
  3. * (C) Copyright 2004
  4. * DENX Software Engineering
  5. * Wolfgang Denk, wd@denx.de
  6. * All rights reserved.
  7. *
  8. * PS/2 keyboard driver
  9. *
  10. * Originally from linux source (drivers/char/pc_keyb.c)
  11. *
  12. ***********************************************************************/
  13. #include <common.h>
  14. #include <keyboard.h>
  15. #include <pc_keyb.h>
  16. #undef KBG_DEBUG
  17. #ifdef KBG_DEBUG
  18. #define PRINTF(fmt,args...) printf (fmt ,##args)
  19. #else
  20. #define PRINTF(fmt,args...)
  21. #endif
  22. /*
  23. * This reads the keyboard status port, and does the
  24. * appropriate action.
  25. *
  26. */
  27. static unsigned char handle_kbd_event(void)
  28. {
  29. unsigned char status = kbd_read_status();
  30. unsigned int work = 10000;
  31. while ((--work > 0) && (status & KBD_STAT_OBF)) {
  32. unsigned char scancode;
  33. scancode = kbd_read_input();
  34. /* Error bytes must be ignored to make the
  35. Synaptics touchpads compaq use work */
  36. /* Ignore error bytes */
  37. if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR))) {
  38. if (status & KBD_STAT_MOUSE_OBF)
  39. ; /* not supported: handle_mouse_event(scancode); */
  40. else
  41. handle_scancode(scancode);
  42. }
  43. status = kbd_read_status();
  44. }
  45. if (!work)
  46. PRINTF("pc_keyb: controller jammed (0x%02X).\n", status);
  47. return status;
  48. }
  49. static int kbd_read_data(void)
  50. {
  51. int val;
  52. unsigned char status;
  53. val = -1;
  54. status = kbd_read_status();
  55. if (status & KBD_STAT_OBF) {
  56. val = kbd_read_input();
  57. if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
  58. val = -2;
  59. }
  60. return val;
  61. }
  62. static int kbd_wait_for_input(void)
  63. {
  64. unsigned long timeout;
  65. int val;
  66. timeout = KBD_TIMEOUT;
  67. val=kbd_read_data();
  68. while(val < 0) {
  69. if(timeout--==0)
  70. return -1;
  71. udelay(1000);
  72. val=kbd_read_data();
  73. }
  74. return val;
  75. }
  76. static int kb_wait(void)
  77. {
  78. unsigned long timeout = KBC_TIMEOUT * 10;
  79. do {
  80. unsigned char status = handle_kbd_event();
  81. if (!(status & KBD_STAT_IBF))
  82. return 0; /* ok */
  83. udelay(1000);
  84. timeout--;
  85. } while (timeout);
  86. return 1;
  87. }
  88. static void kbd_write_command_w(int data)
  89. {
  90. if(kb_wait())
  91. PRINTF("timeout in kbd_write_command_w\n");
  92. kbd_write_command(data);
  93. }
  94. static void kbd_write_output_w(int data)
  95. {
  96. if(kb_wait())
  97. PRINTF("timeout in kbd_write_output_w\n");
  98. kbd_write_output(data);
  99. }
  100. static void kbd_send_data(unsigned char data)
  101. {
  102. kbd_write_output_w(data);
  103. kbd_wait_for_input();
  104. }
  105. static char * kbd_initialize(void)
  106. {
  107. int status;
  108. /*
  109. * Test the keyboard interface.
  110. * This seems to be the only way to get it going.
  111. * If the test is successful a x55 is placed in the input buffer.
  112. */
  113. kbd_write_command_w(KBD_CCMD_SELF_TEST);
  114. if (kbd_wait_for_input() != 0x55)
  115. return "Kbd: failed self test";
  116. /*
  117. * Perform a keyboard interface test. This causes the controller
  118. * to test the keyboard clock and data lines. The results of the
  119. * test are placed in the input buffer.
  120. */
  121. kbd_write_command_w(KBD_CCMD_KBD_TEST);
  122. if (kbd_wait_for_input() != 0x00)
  123. return "Kbd: interface failed self test";
  124. /*
  125. * Enable the keyboard by allowing the keyboard clock to run.
  126. */
  127. kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
  128. /*
  129. * Reset keyboard. If the read times out
  130. * then the assumption is that no keyboard is
  131. * plugged into the machine.
  132. * This defaults the keyboard to scan-code set 2.
  133. *
  134. * Set up to try again if the keyboard asks for RESEND.
  135. */
  136. do {
  137. kbd_write_output_w(KBD_CMD_RESET);
  138. status = kbd_wait_for_input();
  139. if (status == KBD_REPLY_ACK)
  140. break;
  141. if (status != KBD_REPLY_RESEND) {
  142. PRINTF("status: %X\n",status);
  143. return "Kbd: reset failed, no ACK";
  144. }
  145. } while (1);
  146. if (kbd_wait_for_input() != KBD_REPLY_POR)
  147. return "Kbd: reset failed, no POR";
  148. /*
  149. * Set keyboard controller mode. During this, the keyboard should be
  150. * in the disabled state.
  151. *
  152. * Set up to try again if the keyboard asks for RESEND.
  153. */
  154. do {
  155. kbd_write_output_w(KBD_CMD_DISABLE);
  156. status = kbd_wait_for_input();
  157. if (status == KBD_REPLY_ACK)
  158. break;
  159. if (status != KBD_REPLY_RESEND)
  160. return "Kbd: disable keyboard: no ACK";
  161. } while (1);
  162. kbd_write_command_w(KBD_CCMD_WRITE_MODE);
  163. kbd_write_output_w(KBD_MODE_KBD_INT
  164. | KBD_MODE_SYS
  165. | KBD_MODE_DISABLE_MOUSE
  166. | KBD_MODE_KCC);
  167. /* AMCC powerpc portables need this to use scan-code set 1 -- Cort */
  168. kbd_write_command_w(KBD_CCMD_READ_MODE);
  169. if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
  170. /*
  171. * If the controller does not support conversion,
  172. * Set the keyboard to scan-code set 1.
  173. */
  174. kbd_write_output_w(0xF0);
  175. kbd_wait_for_input();
  176. kbd_write_output_w(0x01);
  177. kbd_wait_for_input();
  178. }
  179. kbd_write_output_w(KBD_CMD_ENABLE);
  180. if (kbd_wait_for_input() != KBD_REPLY_ACK)
  181. return "Kbd: enable keyboard: no ACK";
  182. /*
  183. * Finally, set the typematic rate to maximum.
  184. */
  185. kbd_write_output_w(KBD_CMD_SET_RATE);
  186. if (kbd_wait_for_input() != KBD_REPLY_ACK)
  187. return "Kbd: Set rate: no ACK";
  188. kbd_write_output_w(0x00);
  189. if (kbd_wait_for_input() != KBD_REPLY_ACK)
  190. return "Kbd: Set rate: no ACK";
  191. return NULL;
  192. }
  193. static void kbd_interrupt(void *dev_id)
  194. {
  195. handle_kbd_event();
  196. }
  197. /******************************************************************
  198. * Init
  199. ******************************************************************/
  200. int kbd_init_hw(void)
  201. {
  202. char* result;
  203. kbd_request_region();
  204. result=kbd_initialize();
  205. if (result==NULL) {
  206. PRINTF("AT Keyboard initialized\n");
  207. kbd_request_irq(kbd_interrupt);
  208. return (1);
  209. } else {
  210. printf("%s\n",result);
  211. return (-1);
  212. }
  213. }
  214. void pckbd_leds(unsigned char leds)
  215. {
  216. kbd_send_data(KBD_CMD_SET_LEDS);
  217. kbd_send_data(leds);
  218. }