ams_delta_serio.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * Amstrad E3 (Delta) keyboard port driver
  3. *
  4. * Copyright (c) 2006 Matt Callow
  5. * Copyright (c) 2010 Janusz Krzysztofik
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License version 2 as published by
  9. * the Free Software Foundation.
  10. *
  11. * Thanks to Cliff Lawson for his help
  12. *
  13. * The Amstrad Delta keyboard (aka mailboard) uses normal PC-AT style serial
  14. * transmission. The keyboard port is formed of two GPIO lines, for clock
  15. * and data. Due to strict timing requirements of the interface,
  16. * the serial data stream is read and processed by a FIQ handler.
  17. * The resulting words are fetched by this driver from a circular buffer.
  18. *
  19. * Standard AT keyboard driver (atkbd) is used for handling the keyboard data.
  20. * However, when used with the E3 mailboard that producecs non-standard
  21. * scancodes, a custom key table must be prepared and loaded from userspace.
  22. */
  23. #include <linux/irq.h>
  24. #include <linux/platform_data/ams-delta-fiq.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/regulator/consumer.h>
  27. #include <linux/serio.h>
  28. #include <linux/slab.h>
  29. #include <linux/module.h>
  30. #define DRIVER_NAME "ams-delta-serio"
  31. MODULE_AUTHOR("Matt Callow");
  32. MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
  33. MODULE_LICENSE("GPL");
  34. struct ams_delta_serio {
  35. struct serio *serio;
  36. struct regulator *vcc;
  37. unsigned int *fiq_buffer;
  38. };
  39. static int check_data(struct serio *serio, int data)
  40. {
  41. int i, parity = 0;
  42. /* check valid stop bit */
  43. if (!(data & 0x400)) {
  44. dev_warn(&serio->dev, "invalid stop bit, data=0x%X\n", data);
  45. return SERIO_FRAME;
  46. }
  47. /* calculate the parity */
  48. for (i = 1; i < 10; i++) {
  49. if (data & (1 << i))
  50. parity++;
  51. }
  52. /* it should be odd */
  53. if (!(parity & 0x01)) {
  54. dev_warn(&serio->dev,
  55. "parity check failed, data=0x%X parity=0x%X\n", data,
  56. parity);
  57. return SERIO_PARITY;
  58. }
  59. return 0;
  60. }
  61. static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
  62. {
  63. struct ams_delta_serio *priv = dev_id;
  64. int *circ_buff = &priv->fiq_buffer[FIQ_CIRC_BUFF];
  65. int data, dfl;
  66. u8 scancode;
  67. priv->fiq_buffer[FIQ_IRQ_PEND] = 0;
  68. /*
  69. * Read data from the circular buffer, check it
  70. * and then pass it on the serio
  71. */
  72. while (priv->fiq_buffer[FIQ_KEYS_CNT] > 0) {
  73. data = circ_buff[priv->fiq_buffer[FIQ_HEAD_OFFSET]++];
  74. priv->fiq_buffer[FIQ_KEYS_CNT]--;
  75. if (priv->fiq_buffer[FIQ_HEAD_OFFSET] ==
  76. priv->fiq_buffer[FIQ_BUF_LEN])
  77. priv->fiq_buffer[FIQ_HEAD_OFFSET] = 0;
  78. dfl = check_data(priv->serio, data);
  79. scancode = (u8) (data >> 1) & 0xFF;
  80. serio_interrupt(priv->serio, scancode, dfl);
  81. }
  82. return IRQ_HANDLED;
  83. }
  84. static int ams_delta_serio_open(struct serio *serio)
  85. {
  86. struct ams_delta_serio *priv = serio->port_data;
  87. /* enable keyboard */
  88. return regulator_enable(priv->vcc);
  89. }
  90. static void ams_delta_serio_close(struct serio *serio)
  91. {
  92. struct ams_delta_serio *priv = serio->port_data;
  93. /* disable keyboard */
  94. regulator_disable(priv->vcc);
  95. }
  96. static int ams_delta_serio_init(struct platform_device *pdev)
  97. {
  98. struct ams_delta_serio *priv;
  99. struct serio *serio;
  100. int irq, err;
  101. priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  102. if (!priv)
  103. return -ENOMEM;
  104. priv->fiq_buffer = pdev->dev.platform_data;
  105. if (!priv->fiq_buffer)
  106. return -EINVAL;
  107. priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
  108. if (IS_ERR(priv->vcc)) {
  109. err = PTR_ERR(priv->vcc);
  110. dev_err(&pdev->dev, "regulator request failed (%d)\n", err);
  111. /*
  112. * When running on a non-dt platform and requested regulator
  113. * is not available, devm_regulator_get() never returns
  114. * -EPROBE_DEFER as it is not able to justify if the regulator
  115. * may still appear later. On the other hand, the board can
  116. * still set full constriants flag at late_initcall in order
  117. * to instruct devm_regulator_get() to returnn a dummy one
  118. * if sufficient. Hence, if we get -ENODEV here, let's convert
  119. * it to -EPROBE_DEFER and wait for the board to decide or
  120. * let Deferred Probe infrastructure handle this error.
  121. */
  122. if (err == -ENODEV)
  123. err = -EPROBE_DEFER;
  124. return err;
  125. }
  126. irq = platform_get_irq(pdev, 0);
  127. if (irq < 0)
  128. return -ENXIO;
  129. err = devm_request_irq(&pdev->dev, irq, ams_delta_serio_interrupt,
  130. IRQ_TYPE_EDGE_RISING, DRIVER_NAME, priv);
  131. if (err < 0) {
  132. dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
  133. return err;
  134. }
  135. serio = kzalloc(sizeof(*serio), GFP_KERNEL);
  136. if (!serio)
  137. return -ENOMEM;
  138. priv->serio = serio;
  139. serio->id.type = SERIO_8042;
  140. serio->open = ams_delta_serio_open;
  141. serio->close = ams_delta_serio_close;
  142. strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name));
  143. strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
  144. serio->dev.parent = &pdev->dev;
  145. serio->port_data = priv;
  146. serio_register_port(serio);
  147. platform_set_drvdata(pdev, priv);
  148. dev_info(&serio->dev, "%s\n", serio->name);
  149. return 0;
  150. }
  151. static int ams_delta_serio_exit(struct platform_device *pdev)
  152. {
  153. struct ams_delta_serio *priv = platform_get_drvdata(pdev);
  154. serio_unregister_port(priv->serio);
  155. return 0;
  156. }
  157. static struct platform_driver ams_delta_serio_driver = {
  158. .probe = ams_delta_serio_init,
  159. .remove = ams_delta_serio_exit,
  160. .driver = {
  161. .name = DRIVER_NAME
  162. },
  163. };
  164. module_platform_driver(ams_delta_serio_driver);