s3c2410_kbd.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (C) 2002 SAMSUNG ELECTRONICS 
  3.  *                    SW.LEE <hitchcar@sec.samsung.com>
  4.  *
  5.  *  This keyboard driver drives a PS/2 keyboard and mouse connected
  6.  *  to the KMI interfaces.  The KMI interfaces are nothing more than
  7.  *  a uart; there is no inteligence in them to do keycode translation.
  8.  *  We leave all that up to the keyboard itself.
  9.  *
  10.  * Author: SW.LEE <hitchcar@sec.samsung.com>
  11.  * Date  : $Date: 2002/10/14 09:00:06 $ 
  12.  *
  13.  * $Revision: 1.1.2.6 $
  14.    unknown         SW.LEE <hitchcar@sec.samsung.com>
  15.    - initial
  16.    Wed Aug 14 2002 Yong-iL Joh <tolkien@mizi.com>
  17.    - new irq scheme
  18.    Mon Aug 19 2002 Yong-iL Joh <tolkien@mizi.com>
  19.    - rearrange smdk's keyboard mapping.
  20.    - TODO: add kbd_setkeycode/kbd_getkeycode
  21.  *
  22.  * This file is subject to the terms and conditions of the GNU General Public
  23.  * License.  See the file COPYING in the main directory of this archive
  24.  * for more details.
  25.  */
  26. #include <linux/config.h>
  27. #include <linux/kernel.h>
  28. #include <linux/sched.h>
  29. #include <linux/interrupt.h> /* for in_interrupt */
  30. #include <linux/timer.h>
  31. #include <linux/init.h>
  32. #include <linux/delay.h> /* for udelay */
  33. #include <linux/kbd_kern.h> /* for keyboard_tasklet */
  34. #include <linux/kbd_ll.h>
  35. #include <asm/io.h>
  36. #include <asm/irq.h>
  37. #include <asm/hardware.h>
  38. #include <asm/keyboard.h>
  39. /*
  40.  * Responses : SPI STATUS Reigster SPSTA
  41.  */
  42. #define SPI_COLLISION_ERROR     0x4
  43. #define SPI_MULTI_MASTER_ERROR  0x2
  44. #define SPI_RX_TX_READY         0x1
  45. #define UNSET_OUTPUT() write_gpio_bit(GPIO_KBD_nSS, 0)
  46. #define SET_OUTPUT() write_gpio_bit(GPIO_KBD_nSS, 1)
  47. #define SPI_WRITE(c) (SPTDAT1  = c)
  48. #define SPI_READ(c) (c = SPRDAT1 )
  49. /*
  50.  * key map
  51.  */
  52. static char kbmap[128] = {
  53. KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  54. KK_NONE, KK_AGR,  KK_BSLH, KK_TAB,  KK_Z,    KK_A,    KK_X,    KK_NONE,
  55. KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  56. KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  57. KK_NONE, KK_21,   KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  58. KK_NONE, KK_ESC,  KK_DEL,  KK_Q,    KK_CAPS, KK_S,    KK_C,    KK_3,
  59. KK_NONE, KK_1,    KK_NONE, KK_W,    KK_NONE, KK_D,    KK_V,    KK_4,
  60. KK_NONE, KK_2,    KK_T,    KK_E,    KK_NONE, KK_F,    KK_B,    KK_5, 
  61. KK_NONE, KK_9,    KK_Y,    KK_R,    KK_K,    KK_G,    KK_N,    KK_6,
  62. KK_NONE, KK_0,    KK_U,    KK_O,    KK_L,    KK_H,    KK_M,    KK_7,
  63. KK_NONE, KK_MINS, KK_I,    KK_P,    KK_SEMI, KK_J,    KK_COMA, KK_8,
  64. KK_NONE, KK_EQLS, KK_ENTR, KK_LSBK, KK_SQOT, KK_FSLH, KK_DOT,  KK_NONE,
  65. KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  66. KK_NONE, KK_BKSP, KK_DOWN, KK_RSBK, KK_UP,   KK_LEFT, KK_SPCE, KK_RGHT,
  67. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  68. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
  69. static char kbmapFN[128] = {
  70. KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  71. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  72. KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  73. KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  74. KK_NONE, KK_21,   KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  75. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F3,
  76. KK_NONE, KK_F1,   KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F4,
  77. KK_NONE, KK_F2,   KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F5,
  78. KK_NONE, KK_F9,   KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F6,
  79. KK_NONE, KK_F10,  KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F7,
  80. KK_NONE, KK_NUML, KK_NONE, KK_INS,  KK_PRNT, KK_NONE, KK_NONE, KK_F8,
  81. KK_NONE, KK_BRK,  KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  82. KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  83. KK_NONE, KK_NONE, KK_PGDN, KK_SCRL, KK_PGUP, KK_HOME, KK_NONE, KK_END,
  84. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  85. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
  86. static char kbmapNL[128] = {
  87. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  88. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  89. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  90. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  91. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  92. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  93. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  94. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  95. KK_NONE, KP_9,    KK_NONE, KK_NONE, KP_2,    KK_NONE, KK_NONE, KK_NONE,
  96. KK_NONE, KP_STR,  KP_4,    KP_6,    KP_3,    KK_NONE, KP_0,    KP_7,
  97. KK_NONE, KK_NONE, KP_5,    KP_MNS , KP_PLS,  KP_1,    KK_NONE, KP_8,
  98. KK_NONE, KK_NONE, KP_ENT,  KK_NONE, KK_NONE, KP_SLH,  KP_DOT,  KK_NONE,
  99. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  100. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  101. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  102. KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
  103. /****************************************************/
  104. /*
  105.  * The "program" we send to the keyboard to set it up how we want it:
  106.  *  - default typematic delays
  107.  *  - scancode set 1
  108.  */
  109. #define KBCTL_NODATA -1
  110. #define KBCTL_AGAIN -2
  111. static void key_interrupt(int nr, void *devid, struct pt_regs *regs)
  112. {
  113.     static int lastc = -1;
  114.     static int key_fn_down = 0;
  115.     static int key_numl_down = 0;
  116.     u_int val = 0; 
  117.     int x = 0 ,y = 0;
  118.     int   ret = 0;
  119.     kbd_pt_regs = regs;
  120.     UNSET_OUTPUT();
  121.     while (!((SPSTA1) & SPSTA_READY));
  122.     SPI_WRITE(0x0);
  123.     while (!((SPSTA1) & SPSTA_READY));
  124.     SPI_READ(val);
  125.     SET_OUTPUT();
  126.     x = val & 0xff; /* get char by sending one */
  127.     if (x == lastc || x == 0 || x == 0xff) {
  128.       ret =  KBCTL_NODATA;
  129.       tasklet_schedule(&keyboard_tasklet);
  130.     }
  131.     lastc = x;
  132.     if ( x & 0x80) { /* key up */
  133.       x &= 0x7f;
  134.       if (x == 0x21) { /* fn key up */
  135. key_fn_down = 0;
  136. ret = KBCTL_AGAIN;
  137.       } else {
  138. if (key_fn_down) {  /* this is a fn modified key */
  139.   y = kbmapFN[x];
  140.   if (y == KK_NUML)
  141.     ret = KBCTL_AGAIN;
  142. } else { 
  143.   if (key_numl_down)  /* this is a numlock modified key */
  144.     y = kbmapNL[x];
  145.   else
  146.     y = kbmap[x];
  147. }
  148.       }
  149.       ret =  (y | 0x80);
  150.     } else { /* key down */
  151.       if (x == 0x21) { /* fn key down */
  152. key_fn_down = 1;
  153. ret = KBCTL_AGAIN;
  154.       } else {
  155. if (key_fn_down) { /* this is a fn modified key */
  156.   y = kbmapFN[x];
  157.   if (y == KK_NUML) { /* toggle local numlock */
  158.     key_numl_down = !key_numl_down;
  159.     ret = KBCTL_AGAIN;
  160.   }
  161. } else {
  162.   if (key_numl_down) /* this is a numlock modified key */
  163.     y = kbmapNL[x];
  164.   else 
  165.     y = kbmap[x];
  166. }
  167.       }
  168.       ret = y;
  169.     }
  170.     if ( ret != KBCTL_NODATA ) {
  171.       if (  ret != KBCTL_AGAIN && ret != KK_NONE)
  172. handle_scancode(ret, !(ret & 0x80));
  173.       tasklet_schedule(&keyboard_tasklet);
  174.     } 
  175. }
  176. /*
  177.  * You must see SPIcoder 06 UR5HCSPI-06 manual and Schematic of S3C2410  
  178.  */
  179. static int __init HW_kbd_init(void)
  180. {
  181.     int ret = -ENODEV;
  182.     int delay ;
  183.         set_external_irq(IRQ_KBD, EXT_FALLING_EDGE, GPIO_PULLUP_DIS);
  184.         set_gpio_ctrl(GPIO_KBD_SPIMISO);
  185.         set_gpio_ctrl(GPIO_KBD_SPIMOSI);
  186.         set_gpio_ctrl(GPIO_KBD_SPICLK);
  187.         set_gpio_ctrl(GPIO_KBD_nSS);
  188.         set_gpio_ctrl(GPIO_KBD_PWR);
  189.         write_gpio_bit(GPIO_KBD_PWR, 0);
  190.     // Setup SPI registers
  191.     /* Interrupt mode, prescaler enable, master mode,
  192.        active high clock, format B, normal mode */
  193.     SPCON1 = (SPCON_SMOD_INT | SPCON_ENSCK | SPCON_MSTR |
  194.       SPCON_CPOL_HIGH | SPCON_CPHA_FMTB);
  195.     /*  Developer MUST change the value of prescaler properly
  196. whenever value of PCLK is changed. */
  197.     SPPRE1 = 255;
  198.     // 99.121K = 203M/4/2/(255+1) PCLK=50.75Mhz FCLK=203Mhz SPICLK=99.121Khz
  199.  
  200.     for (delay=0; delay < 10; delay++)
  201.       SPI_WRITE(0xff);
  202.     /*
  203.      * Claim the appropriate interrupts
  204.      */
  205.     ret = request_irq(IRQ_KBD, key_interrupt, SA_INTERRUPT,
  206.       "keyboard", key_interrupt);
  207.     if (ret) {
  208.       printk(KERN_INFO "request IRQ failed (%d)n", IRQ_KBD);
  209.       return ret;
  210.     }
  211.     return ret;
  212. }
  213. static int s3c_kbd_translate(u_char scancode, u_char *keycode, char raw_mode)
  214. {
  215. //    *keycode = scancode & 0x7f;
  216.     *keycode = scancode;
  217.     return 1;
  218. }
  219. int __init s3c2410_kbd_init(void) {
  220.     int  ret = -ENODEV;
  221.     ret = HW_kbd_init();
  222.     if (ret)
  223.       return ret;
  224.     /* include/asm/keyboard.h , we have not key_ops_struct */
  225.     k_translate = s3c_kbd_translate;
  226.     return 0;
  227. }
  228. /*
  229.  | $Id: s3c2410_kbd.c,v 1.1.2.6 2002/10/14 09:00:06 nandy Exp $
  230.  |
  231.  | Local Variables:
  232.  | mode: c
  233.  | mode: font-lock
  234.  | version-control: t
  235.  | delete-old-versions: t
  236.  | End:
  237.  |
  238.  | -*- End-Of-File -*-
  239.  */