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