i8042.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2002 ELTEC Elektronik AG
  4. * Frank Gottschling <fgottschling@eltec.de>
  5. */
  6. /* i8042.c - Intel 8042 keyboard driver routines */
  7. #include <common.h>
  8. #include <dm.h>
  9. #include <errno.h>
  10. #include <i8042.h>
  11. #include <input.h>
  12. #include <keyboard.h>
  13. #include <asm/io.h>
  14. DECLARE_GLOBAL_DATA_PTR;
  15. /* defines */
  16. #define in8(p) inb(p)
  17. #define out8(p, v) outb(v, p)
  18. enum {
  19. QUIRK_DUP_POR = 1 << 0,
  20. };
  21. /* locals */
  22. struct i8042_kbd_priv {
  23. bool extended; /* true if an extended keycode is expected next */
  24. int quirks; /* quirks that we support */
  25. };
  26. static unsigned char ext_key_map[] = {
  27. 0x1c, /* keypad enter */
  28. 0x1d, /* right control */
  29. 0x35, /* keypad slash */
  30. 0x37, /* print screen */
  31. 0x38, /* right alt */
  32. 0x46, /* break */
  33. 0x47, /* editpad home */
  34. 0x48, /* editpad up */
  35. 0x49, /* editpad pgup */
  36. 0x4b, /* editpad left */
  37. 0x4d, /* editpad right */
  38. 0x4f, /* editpad end */
  39. 0x50, /* editpad dn */
  40. 0x51, /* editpad pgdn */
  41. 0x52, /* editpad ins */
  42. 0x53, /* editpad del */
  43. 0x00 /* map end */
  44. };
  45. static int kbd_input_empty(void)
  46. {
  47. int kbd_timeout = KBD_TIMEOUT * 1000;
  48. while ((in8(I8042_STS_REG) & STATUS_IBF) && kbd_timeout--)
  49. udelay(1);
  50. return kbd_timeout != -1;
  51. }
  52. static int kbd_output_full(void)
  53. {
  54. int kbd_timeout = KBD_TIMEOUT * 1000;
  55. while (((in8(I8042_STS_REG) & STATUS_OBF) == 0) && kbd_timeout--)
  56. udelay(1);
  57. return kbd_timeout != -1;
  58. }
  59. /**
  60. * check_leds() - Check the keyboard LEDs and update them it needed
  61. *
  62. * @ret: Value to return
  63. * @return value of @ret
  64. */
  65. static int i8042_kbd_update_leds(struct udevice *dev, int leds)
  66. {
  67. kbd_input_empty();
  68. out8(I8042_DATA_REG, CMD_SET_KBD_LED);
  69. kbd_input_empty();
  70. out8(I8042_DATA_REG, leds & 0x7);
  71. return 0;
  72. }
  73. static int kbd_write(int reg, int value)
  74. {
  75. if (!kbd_input_empty())
  76. return -1;
  77. out8(reg, value);
  78. return 0;
  79. }
  80. static int kbd_read(int reg)
  81. {
  82. if (!kbd_output_full())
  83. return -1;
  84. return in8(reg);
  85. }
  86. static int kbd_cmd_read(int cmd)
  87. {
  88. if (kbd_write(I8042_CMD_REG, cmd))
  89. return -1;
  90. return kbd_read(I8042_DATA_REG);
  91. }
  92. static int kbd_cmd_write(int cmd, int data)
  93. {
  94. if (kbd_write(I8042_CMD_REG, cmd))
  95. return -1;
  96. return kbd_write(I8042_DATA_REG, data);
  97. }
  98. static int kbd_reset(int quirk)
  99. {
  100. int config;
  101. /* controller self test */
  102. if (kbd_cmd_read(CMD_SELF_TEST) != KBC_TEST_OK)
  103. goto err;
  104. /* keyboard reset */
  105. if (kbd_write(I8042_DATA_REG, CMD_RESET_KBD) ||
  106. kbd_read(I8042_DATA_REG) != KBD_ACK ||
  107. kbd_read(I8042_DATA_REG) != KBD_POR)
  108. goto err;
  109. if (kbd_write(I8042_DATA_REG, CMD_DRAIN_OUTPUT) ||
  110. kbd_read(I8042_DATA_REG) != KBD_ACK)
  111. goto err;
  112. /* set AT translation and disable irq */
  113. config = kbd_cmd_read(CMD_RD_CONFIG);
  114. if (config == -1)
  115. goto err;
  116. /* Sometimes get a second byte */
  117. else if ((quirk & QUIRK_DUP_POR) && config == KBD_POR)
  118. config = kbd_cmd_read(CMD_RD_CONFIG);
  119. config |= CONFIG_AT_TRANS;
  120. config &= ~(CONFIG_KIRQ_EN | CONFIG_MIRQ_EN);
  121. if (kbd_cmd_write(CMD_WR_CONFIG, config))
  122. goto err;
  123. /* enable keyboard */
  124. if (kbd_write(I8042_CMD_REG, CMD_KBD_EN) ||
  125. !kbd_input_empty())
  126. goto err;
  127. return 0;
  128. err:
  129. debug("%s: Keyboard failure\n", __func__);
  130. return -1;
  131. }
  132. static int kbd_controller_present(void)
  133. {
  134. return in8(I8042_STS_REG) != 0xff;
  135. }
  136. /*
  137. * Implement a weak default function for boards that optionally
  138. * need to skip the i8042 initialization.
  139. *
  140. * TODO(sjg@chromium.org): Use device tree for this?
  141. */
  142. int __weak board_i8042_skip(void)
  143. {
  144. /* As default, don't skip */
  145. return 0;
  146. }
  147. void i8042_flush(void)
  148. {
  149. int timeout;
  150. /*
  151. * The delay is to give the keyboard controller some time
  152. * to fill the next byte.
  153. */
  154. while (1) {
  155. timeout = 100; /* wait for no longer than 100us */
  156. while (timeout > 0 && !(in8(I8042_STS_REG) & STATUS_OBF)) {
  157. udelay(1);
  158. timeout--;
  159. }
  160. /* Try to pull next byte if not timeout */
  161. if (in8(I8042_STS_REG) & STATUS_OBF)
  162. in8(I8042_DATA_REG);
  163. else
  164. break;
  165. }
  166. }
  167. int i8042_disable(void)
  168. {
  169. if (kbd_input_empty() == 0)
  170. return -1;
  171. /* Disable keyboard */
  172. out8(I8042_CMD_REG, CMD_KBD_DIS);
  173. if (kbd_input_empty() == 0)
  174. return -1;
  175. return 0;
  176. }
  177. static int i8042_kbd_check(struct input_config *input)
  178. {
  179. struct i8042_kbd_priv *priv = dev_get_priv(input->dev);
  180. if ((in8(I8042_STS_REG) & STATUS_OBF) == 0) {
  181. return 0;
  182. } else {
  183. bool release = false;
  184. int scan_code;
  185. int i;
  186. scan_code = in8(I8042_DATA_REG);
  187. if (scan_code == 0xfa) {
  188. return 0;
  189. } else if (scan_code == 0xe0) {
  190. priv->extended = true;
  191. return 0;
  192. }
  193. if (scan_code & 0x80) {
  194. scan_code &= 0x7f;
  195. release = true;
  196. }
  197. if (priv->extended) {
  198. priv->extended = false;
  199. for (i = 0; ext_key_map[i]; i++) {
  200. if (ext_key_map[i] == scan_code) {
  201. scan_code = 0x60 + i;
  202. break;
  203. }
  204. }
  205. /* not found ? */
  206. if (!ext_key_map[i])
  207. return 0;
  208. }
  209. input_add_keycode(input, scan_code, release);
  210. return 1;
  211. }
  212. }
  213. /* i8042_kbd_init - reset keyboard and init state flags */
  214. static int i8042_start(struct udevice *dev)
  215. {
  216. struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
  217. struct i8042_kbd_priv *priv = dev_get_priv(dev);
  218. struct input_config *input = &uc_priv->input;
  219. int keymap, try;
  220. char *penv;
  221. int ret;
  222. if (!kbd_controller_present() || board_i8042_skip()) {
  223. debug("i8042 keyboard controller is not present\n");
  224. return -ENOENT;
  225. }
  226. /* Init keyboard device (default US layout) */
  227. keymap = KBD_US;
  228. penv = env_get("keymap");
  229. if (penv != NULL) {
  230. if (strncmp(penv, "de", 3) == 0)
  231. keymap = KBD_GER;
  232. }
  233. for (try = 0; kbd_reset(priv->quirks) != 0; try++) {
  234. if (try >= KBD_RESET_TRIES)
  235. return -1;
  236. }
  237. ret = input_add_tables(input, keymap == KBD_GER);
  238. if (ret)
  239. return ret;
  240. i8042_kbd_update_leds(dev, NORMAL);
  241. debug("%s: started\n", __func__);
  242. return 0;
  243. }
  244. /**
  245. * Set up the i8042 keyboard. This is called by the stdio device handler
  246. *
  247. * We want to do this init when the keyboard is actually used rather than
  248. * at start-up, since keyboard input may not currently be selected.
  249. *
  250. * Once the keyboard starts there will be a period during which we must
  251. * wait for the keyboard to init. We do this only when a key is first
  252. * read - see kbd_wait_for_fifo_init().
  253. *
  254. * @return 0 if ok, -ve on error
  255. */
  256. static int i8042_kbd_probe(struct udevice *dev)
  257. {
  258. struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
  259. struct i8042_kbd_priv *priv = dev_get_priv(dev);
  260. struct stdio_dev *sdev = &uc_priv->sdev;
  261. struct input_config *input = &uc_priv->input;
  262. int ret;
  263. if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
  264. "intel,duplicate-por"))
  265. priv->quirks |= QUIRK_DUP_POR;
  266. /* Register the device. i8042_start() will be called soon */
  267. input->dev = dev;
  268. input->read_keys = i8042_kbd_check;
  269. input_allow_repeats(input, true);
  270. strcpy(sdev->name, "i8042-kbd");
  271. ret = input_stdio_register(sdev);
  272. if (ret) {
  273. debug("%s: input_stdio_register() failed\n", __func__);
  274. return ret;
  275. }
  276. debug("%s: ready\n", __func__);
  277. return 0;
  278. }
  279. static const struct keyboard_ops i8042_kbd_ops = {
  280. .start = i8042_start,
  281. .update_leds = i8042_kbd_update_leds,
  282. };
  283. static const struct udevice_id i8042_kbd_ids[] = {
  284. { .compatible = "intel,i8042-keyboard" },
  285. { }
  286. };
  287. U_BOOT_DRIVER(i8042_kbd) = {
  288. .name = "i8042_kbd",
  289. .id = UCLASS_KEYBOARD,
  290. .of_match = i8042_kbd_ids,
  291. .probe = i8042_kbd_probe,
  292. .ops = &i8042_kbd_ops,
  293. .priv_auto_alloc_size = sizeof(struct i8042_kbd_priv),
  294. };