0086-msm_serial-Add-support-for-poll_-get-put-_char.patch 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. From 48ab619dd6e308c57dac3e5d022a3099806bf79e Mon Sep 17 00:00:00 2001
  2. From: Stephen Boyd <[email protected]>
  3. Date: Tue, 14 Jan 2014 12:34:55 -0800
  4. Subject: [PATCH 086/182] msm_serial: Add support for poll_{get,put}_char()
  5. Implement the polling functionality for the MSM serial driver.
  6. This allows us to use KGDB on this hardware.
  7. Cc: David Brown <[email protected]>
  8. Signed-off-by: Stephen Boyd <[email protected]>
  9. Signed-off-by: Greg Kroah-Hartman <[email protected]>
  10. ---
  11. drivers/tty/serial/msm_serial.c | 140 ++++++++++++++++++++++++++++++++++++++-
  12. drivers/tty/serial/msm_serial.h | 9 +++
  13. 2 files changed, 146 insertions(+), 3 deletions(-)
  14. --- a/drivers/tty/serial/msm_serial.c
  15. +++ b/drivers/tty/serial/msm_serial.c
  16. @@ -39,6 +39,13 @@
  17. #include "msm_serial.h"
  18. +enum {
  19. + UARTDM_1P1 = 1,
  20. + UARTDM_1P2,
  21. + UARTDM_1P3,
  22. + UARTDM_1P4,
  23. +};
  24. +
  25. struct msm_port {
  26. struct uart_port uart;
  27. char name[16];
  28. @@ -309,6 +316,8 @@ static unsigned int msm_get_mctrl(struct
  29. static void msm_reset(struct uart_port *port)
  30. {
  31. + struct msm_port *msm_port = UART_TO_MSM(port);
  32. +
  33. /* reset everything */
  34. msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
  35. msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
  36. @@ -316,6 +325,10 @@ static void msm_reset(struct uart_port *
  37. msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
  38. msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
  39. msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
  40. +
  41. + /* Disable DM modes */
  42. + if (msm_port->is_uartdm)
  43. + msm_write(port, 0, UARTDM_DMEN);
  44. }
  45. static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
  46. @@ -711,6 +724,117 @@ static void msm_power(struct uart_port *
  47. }
  48. }
  49. +#ifdef CONFIG_CONSOLE_POLL
  50. +static int msm_poll_init(struct uart_port *port)
  51. +{
  52. + struct msm_port *msm_port = UART_TO_MSM(port);
  53. +
  54. + /* Enable single character mode on RX FIFO */
  55. + if (msm_port->is_uartdm >= UARTDM_1P4)
  56. + msm_write(port, UARTDM_DMEN_RX_SC_ENABLE, UARTDM_DMEN);
  57. +
  58. + return 0;
  59. +}
  60. +
  61. +static int msm_poll_get_char_single(struct uart_port *port)
  62. +{
  63. + struct msm_port *msm_port = UART_TO_MSM(port);
  64. + unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : UART_RF;
  65. +
  66. + if (!(msm_read(port, UART_SR) & UART_SR_RX_READY))
  67. + return NO_POLL_CHAR;
  68. + else
  69. + return msm_read(port, rf_reg) & 0xff;
  70. +}
  71. +
  72. +static int msm_poll_get_char_dm_1p3(struct uart_port *port)
  73. +{
  74. + int c;
  75. + static u32 slop;
  76. + static int count;
  77. + unsigned char *sp = (unsigned char *)&slop;
  78. +
  79. + /* Check if a previous read had more than one char */
  80. + if (count) {
  81. + c = sp[sizeof(slop) - count];
  82. + count--;
  83. + /* Or if FIFO is empty */
  84. + } else if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) {
  85. + /*
  86. + * If RX packing buffer has less than a word, force stale to
  87. + * push contents into RX FIFO
  88. + */
  89. + count = msm_read(port, UARTDM_RXFS);
  90. + count = (count >> UARTDM_RXFS_BUF_SHIFT) & UARTDM_RXFS_BUF_MASK;
  91. + if (count) {
  92. + msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR);
  93. + slop = msm_read(port, UARTDM_RF);
  94. + c = sp[0];
  95. + count--;
  96. + } else {
  97. + c = NO_POLL_CHAR;
  98. + }
  99. + /* FIFO has a word */
  100. + } else {
  101. + slop = msm_read(port, UARTDM_RF);
  102. + c = sp[0];
  103. + count = sizeof(slop) - 1;
  104. + }
  105. +
  106. + return c;
  107. +}
  108. +
  109. +static int msm_poll_get_char(struct uart_port *port)
  110. +{
  111. + u32 imr;
  112. + int c;
  113. + struct msm_port *msm_port = UART_TO_MSM(port);
  114. +
  115. + /* Disable all interrupts */
  116. + imr = msm_read(port, UART_IMR);
  117. + msm_write(port, 0, UART_IMR);
  118. +
  119. + if (msm_port->is_uartdm == UARTDM_1P3)
  120. + c = msm_poll_get_char_dm_1p3(port);
  121. + else
  122. + c = msm_poll_get_char_single(port);
  123. +
  124. + /* Enable interrupts */
  125. + msm_write(port, imr, UART_IMR);
  126. +
  127. + return c;
  128. +}
  129. +
  130. +static void msm_poll_put_char(struct uart_port *port, unsigned char c)
  131. +{
  132. + u32 imr;
  133. + struct msm_port *msm_port = UART_TO_MSM(port);
  134. +
  135. + /* Disable all interrupts */
  136. + imr = msm_read(port, UART_IMR);
  137. + msm_write(port, 0, UART_IMR);
  138. +
  139. + if (msm_port->is_uartdm)
  140. + reset_dm_count(port, 1);
  141. +
  142. + /* Wait until FIFO is empty */
  143. + while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
  144. + cpu_relax();
  145. +
  146. + /* Write a character */
  147. + msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
  148. +
  149. + /* Wait until FIFO is empty */
  150. + while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
  151. + cpu_relax();
  152. +
  153. + /* Enable interrupts */
  154. + msm_write(port, imr, UART_IMR);
  155. +
  156. + return;
  157. +}
  158. +#endif
  159. +
  160. static struct uart_ops msm_uart_pops = {
  161. .tx_empty = msm_tx_empty,
  162. .set_mctrl = msm_set_mctrl,
  163. @@ -729,6 +853,11 @@ static struct uart_ops msm_uart_pops = {
  164. .config_port = msm_config_port,
  165. .verify_port = msm_verify_port,
  166. .pm = msm_power,
  167. +#ifdef CONFIG_CONSOLE_POLL
  168. + .poll_init = msm_poll_init,
  169. + .poll_get_char = msm_poll_get_char,
  170. + .poll_put_char = msm_poll_put_char,
  171. +#endif
  172. };
  173. static struct msm_port msm_uart_ports[] = {
  174. @@ -900,7 +1029,10 @@ static struct uart_driver msm_uart_drive
  175. static atomic_t msm_uart_next_id = ATOMIC_INIT(0);
  176. static const struct of_device_id msm_uartdm_table[] = {
  177. - { .compatible = "qcom,msm-uartdm" },
  178. + { .compatible = "qcom,msm-uartdm-v1.1", .data = (void *)UARTDM_1P1 },
  179. + { .compatible = "qcom,msm-uartdm-v1.2", .data = (void *)UARTDM_1P2 },
  180. + { .compatible = "qcom,msm-uartdm-v1.3", .data = (void *)UARTDM_1P3 },
  181. + { .compatible = "qcom,msm-uartdm-v1.4", .data = (void *)UARTDM_1P4 },
  182. { }
  183. };
  184. @@ -909,6 +1041,7 @@ static int __init msm_serial_probe(struc
  185. struct msm_port *msm_port;
  186. struct resource *resource;
  187. struct uart_port *port;
  188. + const struct of_device_id *id;
  189. int irq;
  190. if (pdev->id == -1)
  191. @@ -923,8 +1056,9 @@ static int __init msm_serial_probe(struc
  192. port->dev = &pdev->dev;
  193. msm_port = UART_TO_MSM(port);
  194. - if (of_match_device(msm_uartdm_table, &pdev->dev))
  195. - msm_port->is_uartdm = 1;
  196. + id = of_match_device(msm_uartdm_table, &pdev->dev);
  197. + if (id)
  198. + msm_port->is_uartdm = (unsigned long)id->data;
  199. else
  200. msm_port->is_uartdm = 0;
  201. --- a/drivers/tty/serial/msm_serial.h
  202. +++ b/drivers/tty/serial/msm_serial.h
  203. @@ -59,6 +59,7 @@
  204. #define UART_CR_CMD_RESET_RFR (14 << 4)
  205. #define UART_CR_CMD_PROTECTION_EN (16 << 4)
  206. #define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
  207. +#define UART_CR_CMD_FORCE_STALE (4 << 8)
  208. #define UART_CR_CMD_RESET_TX_READY (3 << 8)
  209. #define UART_CR_TX_DISABLE (1 << 3)
  210. #define UART_CR_TX_ENABLE (1 << 2)
  211. @@ -113,6 +114,14 @@
  212. #define GSBI_PROTOCOL_UART 0x40
  213. #define GSBI_PROTOCOL_IDLE 0x0
  214. +#define UARTDM_RXFS 0x50
  215. +#define UARTDM_RXFS_BUF_SHIFT 0x7
  216. +#define UARTDM_RXFS_BUF_MASK 0x7
  217. +
  218. +#define UARTDM_DMEN 0x3C
  219. +#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
  220. +#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
  221. +
  222. #define UARTDM_DMRX 0x34
  223. #define UARTDM_NCF_TX 0x40
  224. #define UARTDM_RX_TOTAL_SNAP 0x38