ams_delta_serio.c 5.0 KB

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