]>
Commit | Line | Data |
---|---|---|
e3b3d0f5 | 1 | // SPDX-License-Identifier: GPL-2.0 |
04896a77 | 2 | /* |
99edb3d1 | 3 | * Driver for msm7k serial device and console |
04896a77 RL |
4 | * |
5 | * Copyright (C) 2007 Google, Inc. | |
6 | * Author: Robert Love <rlove@google.com> | |
ec8f29e7 | 7 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. |
04896a77 RL |
8 | */ |
9 | ||
10 | #if defined(CONFIG_SERIAL_MSM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | |
11 | # define SUPPORT_SYSRQ | |
12 | #endif | |
13 | ||
e4276ff8 | 14 | #include <linux/kernel.h> |
cfdad2ab | 15 | #include <linux/atomic.h> |
3a878c43 II |
16 | #include <linux/dma-mapping.h> |
17 | #include <linux/dmaengine.h> | |
04896a77 RL |
18 | #include <linux/module.h> |
19 | #include <linux/io.h> | |
20 | #include <linux/ioport.h> | |
e4276ff8 | 21 | #include <linux/interrupt.h> |
04896a77 RL |
22 | #include <linux/init.h> |
23 | #include <linux/console.h> | |
24 | #include <linux/tty.h> | |
25 | #include <linux/tty_flip.h> | |
26 | #include <linux/serial_core.h> | |
99693945 | 27 | #include <linux/slab.h> |
04896a77 RL |
28 | #include <linux/clk.h> |
29 | #include <linux/platform_device.h> | |
ec8f29e7 | 30 | #include <linux/delay.h> |
cfdad2ab DB |
31 | #include <linux/of.h> |
32 | #include <linux/of_device.h> | |
e4276ff8 | 33 | #include <linux/wait.h> |
04896a77 | 34 | |
32173741 | 35 | #define UART_MR1 0x0000 |
04896a77 | 36 | |
32173741 SB |
37 | #define UART_MR1_AUTO_RFR_LEVEL0 0x3F |
38 | #define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00 | |
39 | #define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00 | |
40 | #define UART_MR1_RX_RDY_CTL BIT(7) | |
41 | #define UART_MR1_CTS_CTL BIT(6) | |
42 | ||
43 | #define UART_MR2 0x0004 | |
44 | #define UART_MR2_ERROR_MODE BIT(6) | |
45 | #define UART_MR2_BITS_PER_CHAR 0x30 | |
46 | #define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4) | |
47 | #define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4) | |
48 | #define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4) | |
49 | #define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4) | |
50 | #define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2) | |
51 | #define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2) | |
52 | #define UART_MR2_PARITY_MODE_NONE 0x0 | |
53 | #define UART_MR2_PARITY_MODE_ODD 0x1 | |
54 | #define UART_MR2_PARITY_MODE_EVEN 0x2 | |
55 | #define UART_MR2_PARITY_MODE_SPACE 0x3 | |
56 | #define UART_MR2_PARITY_MODE 0x3 | |
57 | ||
58 | #define UART_CSR 0x0008 | |
59 | ||
60 | #define UART_TF 0x000C | |
61 | #define UARTDM_TF 0x0070 | |
62 | ||
63 | #define UART_CR 0x0010 | |
64 | #define UART_CR_CMD_NULL (0 << 4) | |
65 | #define UART_CR_CMD_RESET_RX (1 << 4) | |
66 | #define UART_CR_CMD_RESET_TX (2 << 4) | |
67 | #define UART_CR_CMD_RESET_ERR (3 << 4) | |
68 | #define UART_CR_CMD_RESET_BREAK_INT (4 << 4) | |
69 | #define UART_CR_CMD_START_BREAK (5 << 4) | |
70 | #define UART_CR_CMD_STOP_BREAK (6 << 4) | |
71 | #define UART_CR_CMD_RESET_CTS (7 << 4) | |
72 | #define UART_CR_CMD_RESET_STALE_INT (8 << 4) | |
73 | #define UART_CR_CMD_PACKET_MODE (9 << 4) | |
74 | #define UART_CR_CMD_MODE_RESET (12 << 4) | |
75 | #define UART_CR_CMD_SET_RFR (13 << 4) | |
76 | #define UART_CR_CMD_RESET_RFR (14 << 4) | |
77 | #define UART_CR_CMD_PROTECTION_EN (16 << 4) | |
78 | #define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8) | |
79 | #define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) | |
80 | #define UART_CR_CMD_FORCE_STALE (4 << 8) | |
81 | #define UART_CR_CMD_RESET_TX_READY (3 << 8) | |
82 | #define UART_CR_TX_DISABLE BIT(3) | |
83 | #define UART_CR_TX_ENABLE BIT(2) | |
84 | #define UART_CR_RX_DISABLE BIT(1) | |
85 | #define UART_CR_RX_ENABLE BIT(0) | |
86 | #define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4)) | |
87 | ||
88 | #define UART_IMR 0x0014 | |
89 | #define UART_IMR_TXLEV BIT(0) | |
90 | #define UART_IMR_RXSTALE BIT(3) | |
91 | #define UART_IMR_RXLEV BIT(4) | |
92 | #define UART_IMR_DELTA_CTS BIT(5) | |
93 | #define UART_IMR_CURRENT_CTS BIT(6) | |
94 | #define UART_IMR_RXBREAK_START BIT(10) | |
95 | ||
96 | #define UART_IPR_RXSTALE_LAST 0x20 | |
97 | #define UART_IPR_STALE_LSB 0x1F | |
98 | #define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80 | |
99 | #define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80 | |
100 | ||
101 | #define UART_IPR 0x0018 | |
102 | #define UART_TFWR 0x001C | |
103 | #define UART_RFWR 0x0020 | |
104 | #define UART_HCR 0x0024 | |
105 | ||
106 | #define UART_MREG 0x0028 | |
107 | #define UART_NREG 0x002C | |
108 | #define UART_DREG 0x0030 | |
109 | #define UART_MNDREG 0x0034 | |
110 | #define UART_IRDA 0x0038 | |
111 | #define UART_MISR_MODE 0x0040 | |
112 | #define UART_MISR_RESET 0x0044 | |
113 | #define UART_MISR_EXPORT 0x0048 | |
114 | #define UART_MISR_VAL 0x004C | |
115 | #define UART_TEST_CTRL 0x0050 | |
116 | ||
117 | #define UART_SR 0x0008 | |
118 | #define UART_SR_HUNT_CHAR BIT(7) | |
119 | #define UART_SR_RX_BREAK BIT(6) | |
120 | #define UART_SR_PAR_FRAME_ERR BIT(5) | |
121 | #define UART_SR_OVERRUN BIT(4) | |
122 | #define UART_SR_TX_EMPTY BIT(3) | |
123 | #define UART_SR_TX_READY BIT(2) | |
124 | #define UART_SR_RX_FULL BIT(1) | |
125 | #define UART_SR_RX_READY BIT(0) | |
126 | ||
127 | #define UART_RF 0x000C | |
128 | #define UARTDM_RF 0x0070 | |
129 | #define UART_MISR 0x0010 | |
130 | #define UART_ISR 0x0014 | |
131 | #define UART_ISR_TX_READY BIT(7) | |
132 | ||
133 | #define UARTDM_RXFS 0x50 | |
134 | #define UARTDM_RXFS_BUF_SHIFT 0x7 | |
135 | #define UARTDM_RXFS_BUF_MASK 0x7 | |
136 | ||
137 | #define UARTDM_DMEN 0x3C | |
138 | #define UARTDM_DMEN_RX_SC_ENABLE BIT(5) | |
139 | #define UARTDM_DMEN_TX_SC_ENABLE BIT(4) | |
140 | ||
141 | #define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */ | |
142 | #define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */ | |
143 | ||
144 | #define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */ | |
145 | #define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */ | |
146 | ||
147 | #define UARTDM_DMRX 0x34 | |
148 | #define UARTDM_NCF_TX 0x40 | |
149 | #define UARTDM_RX_TOTAL_SNAP 0x38 | |
150 | ||
151 | #define UARTDM_BURST_SIZE 16 /* in bytes */ | |
152 | #define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */ | |
153 | #define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */ | |
154 | #define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4) | |
3a878c43 | 155 | |
f7e54d7a SB |
156 | enum { |
157 | UARTDM_1P1 = 1, | |
158 | UARTDM_1P2, | |
159 | UARTDM_1P3, | |
160 | UARTDM_1P4, | |
161 | }; | |
162 | ||
3a878c43 II |
163 | struct msm_dma { |
164 | struct dma_chan *chan; | |
165 | enum dma_data_direction dir; | |
166 | dma_addr_t phys; | |
167 | unsigned char *virt; | |
168 | dma_cookie_t cookie; | |
169 | u32 enable_bit; | |
170 | unsigned int count; | |
171 | struct dma_async_tx_descriptor *desc; | |
172 | }; | |
173 | ||
04896a77 RL |
174 | struct msm_port { |
175 | struct uart_port uart; | |
176 | char name[16]; | |
177 | struct clk *clk; | |
ec8f29e7 | 178 | struct clk *pclk; |
04896a77 | 179 | unsigned int imr; |
ec8f29e7 SM |
180 | int is_uartdm; |
181 | unsigned int old_snap_state; | |
0896d4d4 | 182 | bool break_detected; |
3a878c43 | 183 | struct msm_dma tx_dma; |
99693945 | 184 | struct msm_dma rx_dma; |
04896a77 RL |
185 | }; |
186 | ||
32173741 SB |
187 | #define UART_TO_MSM(uart_port) container_of(uart_port, struct msm_port, uart) |
188 | ||
189 | static | |
190 | void msm_write(struct uart_port *port, unsigned int val, unsigned int off) | |
191 | { | |
192 | writel_relaxed(val, port->membase + off); | |
193 | } | |
194 | ||
195 | static | |
196 | unsigned int msm_read(struct uart_port *port, unsigned int off) | |
197 | { | |
198 | return readl_relaxed(port->membase + off); | |
199 | } | |
200 | ||
201 | /* | |
202 | * Setup the MND registers to use the TCXO clock. | |
203 | */ | |
204 | static void msm_serial_set_mnd_regs_tcxo(struct uart_port *port) | |
205 | { | |
206 | msm_write(port, 0x06, UART_MREG); | |
207 | msm_write(port, 0xF1, UART_NREG); | |
208 | msm_write(port, 0x0F, UART_DREG); | |
209 | msm_write(port, 0x1A, UART_MNDREG); | |
210 | port->uartclk = 1843200; | |
211 | } | |
212 | ||
213 | /* | |
214 | * Setup the MND registers to use the TCXO clock divided by 4. | |
215 | */ | |
216 | static void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port) | |
217 | { | |
218 | msm_write(port, 0x18, UART_MREG); | |
219 | msm_write(port, 0xF6, UART_NREG); | |
220 | msm_write(port, 0x0F, UART_DREG); | |
221 | msm_write(port, 0x0A, UART_MNDREG); | |
222 | port->uartclk = 1843200; | |
223 | } | |
224 | ||
225 | static void msm_serial_set_mnd_regs(struct uart_port *port) | |
226 | { | |
2a31f094 SB |
227 | struct msm_port *msm_port = UART_TO_MSM(port); |
228 | ||
229 | /* | |
230 | * These registers don't exist so we change the clk input rate | |
231 | * on uartdm hardware instead | |
232 | */ | |
233 | if (msm_port->is_uartdm) | |
234 | return; | |
235 | ||
32173741 SB |
236 | if (port->uartclk == 19200000) |
237 | msm_serial_set_mnd_regs_tcxo(port); | |
238 | else if (port->uartclk == 4800000) | |
239 | msm_serial_set_mnd_regs_tcxoby4(port); | |
240 | } | |
241 | ||
3a878c43 | 242 | static void msm_handle_tx(struct uart_port *port); |
99693945 | 243 | static void msm_start_rx_dma(struct msm_port *msm_port); |
3a878c43 | 244 | |
9a3f5bf2 | 245 | static void msm_stop_dma(struct uart_port *port, struct msm_dma *dma) |
3a878c43 II |
246 | { |
247 | struct device *dev = port->dev; | |
248 | unsigned int mapped; | |
249 | u32 val; | |
250 | ||
251 | mapped = dma->count; | |
252 | dma->count = 0; | |
253 | ||
254 | dmaengine_terminate_all(dma->chan); | |
255 | ||
256 | /* | |
257 | * DMA Stall happens if enqueue and flush command happens concurrently. | |
258 | * For example before changing the baud rate/protocol configuration and | |
259 | * sending flush command to ADM, disable the channel of UARTDM. | |
260 | * Note: should not reset the receiver here immediately as it is not | |
261 | * suggested to do disable/reset or reset/disable at the same time. | |
262 | */ | |
263 | val = msm_read(port, UARTDM_DMEN); | |
264 | val &= ~dma->enable_bit; | |
265 | msm_write(port, val, UARTDM_DMEN); | |
266 | ||
267 | if (mapped) | |
268 | dma_unmap_single(dev, dma->phys, mapped, dma->dir); | |
269 | } | |
270 | ||
271 | static void msm_release_dma(struct msm_port *msm_port) | |
272 | { | |
273 | struct msm_dma *dma; | |
274 | ||
275 | dma = &msm_port->tx_dma; | |
276 | if (dma->chan) { | |
277 | msm_stop_dma(&msm_port->uart, dma); | |
278 | dma_release_channel(dma->chan); | |
279 | } | |
280 | ||
281 | memset(dma, 0, sizeof(*dma)); | |
99693945 II |
282 | |
283 | dma = &msm_port->rx_dma; | |
284 | if (dma->chan) { | |
285 | msm_stop_dma(&msm_port->uart, dma); | |
286 | dma_release_channel(dma->chan); | |
287 | kfree(dma->virt); | |
288 | } | |
289 | ||
290 | memset(dma, 0, sizeof(*dma)); | |
3a878c43 II |
291 | } |
292 | ||
293 | static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base) | |
294 | { | |
295 | struct device *dev = msm_port->uart.dev; | |
296 | struct dma_slave_config conf; | |
297 | struct msm_dma *dma; | |
298 | u32 crci = 0; | |
299 | int ret; | |
300 | ||
301 | dma = &msm_port->tx_dma; | |
302 | ||
303 | /* allocate DMA resources, if available */ | |
304 | dma->chan = dma_request_slave_channel_reason(dev, "tx"); | |
305 | if (IS_ERR(dma->chan)) | |
306 | goto no_tx; | |
307 | ||
308 | of_property_read_u32(dev->of_node, "qcom,tx-crci", &crci); | |
309 | ||
310 | memset(&conf, 0, sizeof(conf)); | |
311 | conf.direction = DMA_MEM_TO_DEV; | |
312 | conf.device_fc = true; | |
313 | conf.dst_addr = base + UARTDM_TF; | |
314 | conf.dst_maxburst = UARTDM_BURST_SIZE; | |
315 | conf.slave_id = crci; | |
316 | ||
317 | ret = dmaengine_slave_config(dma->chan, &conf); | |
318 | if (ret) | |
319 | goto rel_tx; | |
320 | ||
321 | dma->dir = DMA_TO_DEVICE; | |
322 | ||
323 | if (msm_port->is_uartdm < UARTDM_1P4) | |
324 | dma->enable_bit = UARTDM_DMEN_TX_DM_ENABLE; | |
325 | else | |
326 | dma->enable_bit = UARTDM_DMEN_TX_BAM_ENABLE; | |
327 | ||
328 | return; | |
329 | ||
330 | rel_tx: | |
331 | dma_release_channel(dma->chan); | |
332 | no_tx: | |
333 | memset(dma, 0, sizeof(*dma)); | |
334 | } | |
335 | ||
99693945 II |
336 | static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base) |
337 | { | |
338 | struct device *dev = msm_port->uart.dev; | |
339 | struct dma_slave_config conf; | |
340 | struct msm_dma *dma; | |
341 | u32 crci = 0; | |
342 | int ret; | |
343 | ||
344 | dma = &msm_port->rx_dma; | |
345 | ||
346 | /* allocate DMA resources, if available */ | |
347 | dma->chan = dma_request_slave_channel_reason(dev, "rx"); | |
348 | if (IS_ERR(dma->chan)) | |
349 | goto no_rx; | |
350 | ||
351 | of_property_read_u32(dev->of_node, "qcom,rx-crci", &crci); | |
352 | ||
353 | dma->virt = kzalloc(UARTDM_RX_SIZE, GFP_KERNEL); | |
354 | if (!dma->virt) | |
355 | goto rel_rx; | |
356 | ||
357 | memset(&conf, 0, sizeof(conf)); | |
358 | conf.direction = DMA_DEV_TO_MEM; | |
359 | conf.device_fc = true; | |
360 | conf.src_addr = base + UARTDM_RF; | |
361 | conf.src_maxburst = UARTDM_BURST_SIZE; | |
362 | conf.slave_id = crci; | |
363 | ||
364 | ret = dmaengine_slave_config(dma->chan, &conf); | |
365 | if (ret) | |
366 | goto err; | |
367 | ||
368 | dma->dir = DMA_FROM_DEVICE; | |
369 | ||
370 | if (msm_port->is_uartdm < UARTDM_1P4) | |
371 | dma->enable_bit = UARTDM_DMEN_RX_DM_ENABLE; | |
372 | else | |
373 | dma->enable_bit = UARTDM_DMEN_RX_BAM_ENABLE; | |
374 | ||
375 | return; | |
376 | err: | |
377 | kfree(dma->virt); | |
378 | rel_rx: | |
379 | dma_release_channel(dma->chan); | |
380 | no_rx: | |
381 | memset(dma, 0, sizeof(*dma)); | |
382 | } | |
383 | ||
558abdb0 | 384 | static inline void msm_wait_for_xmitr(struct uart_port *port) |
ec8f29e7 | 385 | { |
d4f538e7 JRO |
386 | unsigned int timeout = 500000; |
387 | ||
4a5662d6 SB |
388 | while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) { |
389 | if (msm_read(port, UART_ISR) & UART_ISR_TX_READY) | |
390 | break; | |
391 | udelay(1); | |
d4f538e7 JRO |
392 | if (!timeout--) |
393 | break; | |
4a5662d6 SB |
394 | } |
395 | msm_write(port, UART_CR_CMD_RESET_TX_READY, UART_CR); | |
ec8f29e7 SM |
396 | } |
397 | ||
04896a77 RL |
398 | static void msm_stop_tx(struct uart_port *port) |
399 | { | |
400 | struct msm_port *msm_port = UART_TO_MSM(port); | |
401 | ||
402 | msm_port->imr &= ~UART_IMR_TXLEV; | |
403 | msm_write(port, msm_port->imr, UART_IMR); | |
404 | } | |
405 | ||
406 | static void msm_start_tx(struct uart_port *port) | |
407 | { | |
408 | struct msm_port *msm_port = UART_TO_MSM(port); | |
3a878c43 II |
409 | struct msm_dma *dma = &msm_port->tx_dma; |
410 | ||
411 | /* Already started in DMA mode */ | |
412 | if (dma->count) | |
413 | return; | |
04896a77 RL |
414 | |
415 | msm_port->imr |= UART_IMR_TXLEV; | |
416 | msm_write(port, msm_port->imr, UART_IMR); | |
417 | } | |
418 | ||
3a878c43 II |
419 | static void msm_reset_dm_count(struct uart_port *port, int count) |
420 | { | |
421 | msm_wait_for_xmitr(port); | |
422 | msm_write(port, count, UARTDM_NCF_TX); | |
423 | msm_read(port, UARTDM_NCF_TX); | |
424 | } | |
425 | ||
426 | static void msm_complete_tx_dma(void *args) | |
427 | { | |
428 | struct msm_port *msm_port = args; | |
429 | struct uart_port *port = &msm_port->uart; | |
430 | struct circ_buf *xmit = &port->state->xmit; | |
431 | struct msm_dma *dma = &msm_port->tx_dma; | |
432 | struct dma_tx_state state; | |
433 | enum dma_status status; | |
434 | unsigned long flags; | |
435 | unsigned int count; | |
436 | u32 val; | |
437 | ||
438 | spin_lock_irqsave(&port->lock, flags); | |
439 | ||
440 | /* Already stopped */ | |
441 | if (!dma->count) | |
442 | goto done; | |
443 | ||
444 | status = dmaengine_tx_status(dma->chan, dma->cookie, &state); | |
445 | ||
446 | dma_unmap_single(port->dev, dma->phys, dma->count, dma->dir); | |
447 | ||
448 | val = msm_read(port, UARTDM_DMEN); | |
449 | val &= ~dma->enable_bit; | |
450 | msm_write(port, val, UARTDM_DMEN); | |
451 | ||
452 | if (msm_port->is_uartdm > UARTDM_1P3) { | |
453 | msm_write(port, UART_CR_CMD_RESET_TX, UART_CR); | |
454 | msm_write(port, UART_CR_TX_ENABLE, UART_CR); | |
455 | } | |
456 | ||
457 | count = dma->count - state.residue; | |
458 | port->icount.tx += count; | |
459 | dma->count = 0; | |
460 | ||
461 | xmit->tail += count; | |
462 | xmit->tail &= UART_XMIT_SIZE - 1; | |
463 | ||
464 | /* Restore "Tx FIFO below watermark" interrupt */ | |
465 | msm_port->imr |= UART_IMR_TXLEV; | |
466 | msm_write(port, msm_port->imr, UART_IMR); | |
467 | ||
468 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | |
469 | uart_write_wakeup(port); | |
470 | ||
471 | msm_handle_tx(port); | |
472 | done: | |
473 | spin_unlock_irqrestore(&port->lock, flags); | |
474 | } | |
475 | ||
476 | static int msm_handle_tx_dma(struct msm_port *msm_port, unsigned int count) | |
477 | { | |
478 | struct circ_buf *xmit = &msm_port->uart.state->xmit; | |
479 | struct uart_port *port = &msm_port->uart; | |
480 | struct msm_dma *dma = &msm_port->tx_dma; | |
481 | void *cpu_addr; | |
482 | int ret; | |
483 | u32 val; | |
484 | ||
485 | cpu_addr = &xmit->buf[xmit->tail]; | |
486 | ||
487 | dma->phys = dma_map_single(port->dev, cpu_addr, count, dma->dir); | |
488 | ret = dma_mapping_error(port->dev, dma->phys); | |
489 | if (ret) | |
490 | return ret; | |
491 | ||
492 | dma->desc = dmaengine_prep_slave_single(dma->chan, dma->phys, | |
493 | count, DMA_MEM_TO_DEV, | |
494 | DMA_PREP_INTERRUPT | | |
495 | DMA_PREP_FENCE); | |
496 | if (!dma->desc) { | |
497 | ret = -EIO; | |
498 | goto unmap; | |
499 | } | |
500 | ||
501 | dma->desc->callback = msm_complete_tx_dma; | |
502 | dma->desc->callback_param = msm_port; | |
503 | ||
504 | dma->cookie = dmaengine_submit(dma->desc); | |
505 | ret = dma_submit_error(dma->cookie); | |
506 | if (ret) | |
507 | goto unmap; | |
508 | ||
509 | /* | |
510 | * Using DMA complete for Tx FIFO reload, no need for | |
511 | * "Tx FIFO below watermark" one, disable it | |
512 | */ | |
513 | msm_port->imr &= ~UART_IMR_TXLEV; | |
514 | msm_write(port, msm_port->imr, UART_IMR); | |
515 | ||
516 | dma->count = count; | |
517 | ||
518 | val = msm_read(port, UARTDM_DMEN); | |
519 | val |= dma->enable_bit; | |
520 | ||
521 | if (msm_port->is_uartdm < UARTDM_1P4) | |
522 | msm_write(port, val, UARTDM_DMEN); | |
523 | ||
524 | msm_reset_dm_count(port, count); | |
525 | ||
526 | if (msm_port->is_uartdm > UARTDM_1P3) | |
527 | msm_write(port, val, UARTDM_DMEN); | |
528 | ||
529 | dma_async_issue_pending(dma->chan); | |
530 | return 0; | |
531 | unmap: | |
532 | dma_unmap_single(port->dev, dma->phys, count, dma->dir); | |
533 | return ret; | |
534 | } | |
99693945 II |
535 | |
536 | static void msm_complete_rx_dma(void *args) | |
537 | { | |
538 | struct msm_port *msm_port = args; | |
539 | struct uart_port *port = &msm_port->uart; | |
540 | struct tty_port *tport = &port->state->port; | |
541 | struct msm_dma *dma = &msm_port->rx_dma; | |
542 | int count = 0, i, sysrq; | |
543 | unsigned long flags; | |
544 | u32 val; | |
545 | ||
546 | spin_lock_irqsave(&port->lock, flags); | |
547 | ||
548 | /* Already stopped */ | |
549 | if (!dma->count) | |
550 | goto done; | |
551 | ||
552 | val = msm_read(port, UARTDM_DMEN); | |
553 | val &= ~dma->enable_bit; | |
554 | msm_write(port, val, UARTDM_DMEN); | |
555 | ||
99693945 II |
556 | if (msm_read(port, UART_SR) & UART_SR_OVERRUN) { |
557 | port->icount.overrun++; | |
558 | tty_insert_flip_char(tport, 0, TTY_OVERRUN); | |
559 | msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); | |
560 | } | |
561 | ||
562 | count = msm_read(port, UARTDM_RX_TOTAL_SNAP); | |
563 | ||
564 | port->icount.rx += count; | |
565 | ||
566 | dma->count = 0; | |
567 | ||
568 | dma_unmap_single(port->dev, dma->phys, UARTDM_RX_SIZE, dma->dir); | |
569 | ||
570 | for (i = 0; i < count; i++) { | |
571 | char flag = TTY_NORMAL; | |
572 | ||
573 | if (msm_port->break_detected && dma->virt[i] == 0) { | |
574 | port->icount.brk++; | |
575 | flag = TTY_BREAK; | |
576 | msm_port->break_detected = false; | |
577 | if (uart_handle_break(port)) | |
578 | continue; | |
579 | } | |
580 | ||
581 | if (!(port->read_status_mask & UART_SR_RX_BREAK)) | |
582 | flag = TTY_NORMAL; | |
583 | ||
584 | spin_unlock_irqrestore(&port->lock, flags); | |
585 | sysrq = uart_handle_sysrq_char(port, dma->virt[i]); | |
586 | spin_lock_irqsave(&port->lock, flags); | |
587 | if (!sysrq) | |
588 | tty_insert_flip_char(tport, dma->virt[i], flag); | |
589 | } | |
590 | ||
591 | msm_start_rx_dma(msm_port); | |
592 | done: | |
593 | spin_unlock_irqrestore(&port->lock, flags); | |
594 | ||
595 | if (count) | |
596 | tty_flip_buffer_push(tport); | |
597 | } | |
598 | ||
599 | static void msm_start_rx_dma(struct msm_port *msm_port) | |
600 | { | |
601 | struct msm_dma *dma = &msm_port->rx_dma; | |
602 | struct uart_port *uart = &msm_port->uart; | |
603 | u32 val; | |
604 | int ret; | |
605 | ||
606 | if (!dma->chan) | |
607 | return; | |
608 | ||
609 | dma->phys = dma_map_single(uart->dev, dma->virt, | |
610 | UARTDM_RX_SIZE, dma->dir); | |
611 | ret = dma_mapping_error(uart->dev, dma->phys); | |
612 | if (ret) | |
613 | return; | |
614 | ||
615 | dma->desc = dmaengine_prep_slave_single(dma->chan, dma->phys, | |
616 | UARTDM_RX_SIZE, DMA_DEV_TO_MEM, | |
617 | DMA_PREP_INTERRUPT); | |
618 | if (!dma->desc) | |
619 | goto unmap; | |
620 | ||
621 | dma->desc->callback = msm_complete_rx_dma; | |
622 | dma->desc->callback_param = msm_port; | |
623 | ||
624 | dma->cookie = dmaengine_submit(dma->desc); | |
625 | ret = dma_submit_error(dma->cookie); | |
626 | if (ret) | |
627 | goto unmap; | |
628 | /* | |
629 | * Using DMA for FIFO off-load, no need for "Rx FIFO over | |
630 | * watermark" or "stale" interrupts, disable them | |
631 | */ | |
632 | msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE); | |
633 | ||
634 | /* | |
635 | * Well, when DMA is ADM3 engine(implied by <= UARTDM v1.3), | |
636 | * we need RXSTALE to flush input DMA fifo to memory | |
637 | */ | |
638 | if (msm_port->is_uartdm < UARTDM_1P4) | |
639 | msm_port->imr |= UART_IMR_RXSTALE; | |
640 | ||
641 | msm_write(uart, msm_port->imr, UART_IMR); | |
642 | ||
643 | dma->count = UARTDM_RX_SIZE; | |
644 | ||
645 | dma_async_issue_pending(dma->chan); | |
646 | ||
647 | msm_write(uart, UART_CR_CMD_RESET_STALE_INT, UART_CR); | |
648 | msm_write(uart, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); | |
649 | ||
650 | val = msm_read(uart, UARTDM_DMEN); | |
651 | val |= dma->enable_bit; | |
652 | ||
653 | if (msm_port->is_uartdm < UARTDM_1P4) | |
654 | msm_write(uart, val, UARTDM_DMEN); | |
655 | ||
656 | msm_write(uart, UARTDM_RX_SIZE, UARTDM_DMRX); | |
657 | ||
658 | if (msm_port->is_uartdm > UARTDM_1P3) | |
659 | msm_write(uart, val, UARTDM_DMEN); | |
660 | ||
661 | return; | |
662 | unmap: | |
663 | dma_unmap_single(uart->dev, dma->phys, UARTDM_RX_SIZE, dma->dir); | |
664 | } | |
665 | ||
04896a77 RL |
666 | static void msm_stop_rx(struct uart_port *port) |
667 | { | |
668 | struct msm_port *msm_port = UART_TO_MSM(port); | |
99693945 | 669 | struct msm_dma *dma = &msm_port->rx_dma; |
04896a77 RL |
670 | |
671 | msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE); | |
672 | msm_write(port, msm_port->imr, UART_IMR); | |
99693945 II |
673 | |
674 | if (dma->chan) | |
675 | msm_stop_dma(port, dma); | |
04896a77 RL |
676 | } |
677 | ||
678 | static void msm_enable_ms(struct uart_port *port) | |
679 | { | |
680 | struct msm_port *msm_port = UART_TO_MSM(port); | |
681 | ||
682 | msm_port->imr |= UART_IMR_DELTA_CTS; | |
683 | msm_write(port, msm_port->imr, UART_IMR); | |
684 | } | |
685 | ||
558abdb0 | 686 | static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) |
ec8f29e7 | 687 | { |
92a19f9c | 688 | struct tty_port *tport = &port->state->port; |
ec8f29e7 SM |
689 | unsigned int sr; |
690 | int count = 0; | |
691 | struct msm_port *msm_port = UART_TO_MSM(port); | |
692 | ||
693 | if ((msm_read(port, UART_SR) & UART_SR_OVERRUN)) { | |
694 | port->icount.overrun++; | |
92a19f9c | 695 | tty_insert_flip_char(tport, 0, TTY_OVERRUN); |
ec8f29e7 SM |
696 | msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); |
697 | } | |
698 | ||
699 | if (misr & UART_IMR_RXSTALE) { | |
700 | count = msm_read(port, UARTDM_RX_TOTAL_SNAP) - | |
701 | msm_port->old_snap_state; | |
702 | msm_port->old_snap_state = 0; | |
703 | } else { | |
704 | count = 4 * (msm_read(port, UART_RFWR)); | |
705 | msm_port->old_snap_state += count; | |
706 | } | |
707 | ||
708 | /* TODO: Precise error reporting */ | |
709 | ||
710 | port->icount.rx += count; | |
711 | ||
712 | while (count > 0) { | |
68252424 | 713 | unsigned char buf[4]; |
0896d4d4 | 714 | int sysrq, r_count, i; |
ec8f29e7 SM |
715 | |
716 | sr = msm_read(port, UART_SR); | |
717 | if ((sr & UART_SR_RX_READY) == 0) { | |
718 | msm_port->old_snap_state -= count; | |
719 | break; | |
720 | } | |
ec8f29e7 | 721 | |
0896d4d4 SB |
722 | ioread32_rep(port->membase + UARTDM_RF, buf, 1); |
723 | r_count = min_t(int, count, sizeof(buf)); | |
724 | ||
725 | for (i = 0; i < r_count; i++) { | |
726 | char flag = TTY_NORMAL; | |
727 | ||
728 | if (msm_port->break_detected && buf[i] == 0) { | |
729 | port->icount.brk++; | |
730 | flag = TTY_BREAK; | |
731 | msm_port->break_detected = false; | |
732 | if (uart_handle_break(port)) | |
733 | continue; | |
734 | } | |
735 | ||
736 | if (!(port->read_status_mask & UART_SR_RX_BREAK)) | |
737 | flag = TTY_NORMAL; | |
738 | ||
739 | spin_unlock(&port->lock); | |
740 | sysrq = uart_handle_sysrq_char(port, buf[i]); | |
741 | spin_lock(&port->lock); | |
742 | if (!sysrq) | |
743 | tty_insert_flip_char(tport, buf[i], flag); | |
744 | } | |
745 | count -= r_count; | |
ec8f29e7 SM |
746 | } |
747 | ||
f77232da | 748 | spin_unlock(&port->lock); |
2e124b4a | 749 | tty_flip_buffer_push(tport); |
f77232da VK |
750 | spin_lock(&port->lock); |
751 | ||
ec8f29e7 SM |
752 | if (misr & (UART_IMR_RXSTALE)) |
753 | msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); | |
754 | msm_write(port, 0xFFFFFF, UARTDM_DMRX); | |
755 | msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); | |
99693945 II |
756 | |
757 | /* Try to use DMA */ | |
758 | msm_start_rx_dma(msm_port); | |
ec8f29e7 SM |
759 | } |
760 | ||
558abdb0 | 761 | static void msm_handle_rx(struct uart_port *port) |
04896a77 | 762 | { |
92a19f9c | 763 | struct tty_port *tport = &port->state->port; |
04896a77 RL |
764 | unsigned int sr; |
765 | ||
766 | /* | |
767 | * Handle overrun. My understanding of the hardware is that overrun | |
768 | * is not tied to the RX buffer, so we handle the case out of band. | |
769 | */ | |
770 | if ((msm_read(port, UART_SR) & UART_SR_OVERRUN)) { | |
771 | port->icount.overrun++; | |
92a19f9c | 772 | tty_insert_flip_char(tport, 0, TTY_OVERRUN); |
04896a77 RL |
773 | msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); |
774 | } | |
775 | ||
776 | /* and now the main RX loop */ | |
777 | while ((sr = msm_read(port, UART_SR)) & UART_SR_RX_READY) { | |
778 | unsigned int c; | |
779 | char flag = TTY_NORMAL; | |
660beb0e | 780 | int sysrq; |
04896a77 RL |
781 | |
782 | c = msm_read(port, UART_RF); | |
783 | ||
784 | if (sr & UART_SR_RX_BREAK) { | |
785 | port->icount.brk++; | |
786 | if (uart_handle_break(port)) | |
787 | continue; | |
788 | } else if (sr & UART_SR_PAR_FRAME_ERR) { | |
789 | port->icount.frame++; | |
790 | } else { | |
791 | port->icount.rx++; | |
792 | } | |
793 | ||
794 | /* Mask conditions we're ignorning. */ | |
795 | sr &= port->read_status_mask; | |
796 | ||
ddea392e | 797 | if (sr & UART_SR_RX_BREAK) |
04896a77 | 798 | flag = TTY_BREAK; |
ddea392e | 799 | else if (sr & UART_SR_PAR_FRAME_ERR) |
04896a77 | 800 | flag = TTY_FRAME; |
04896a77 | 801 | |
660beb0e SB |
802 | spin_unlock(&port->lock); |
803 | sysrq = uart_handle_sysrq_char(port, c); | |
804 | spin_lock(&port->lock); | |
805 | if (!sysrq) | |
92a19f9c | 806 | tty_insert_flip_char(tport, c, flag); |
04896a77 RL |
807 | } |
808 | ||
f77232da | 809 | spin_unlock(&port->lock); |
2e124b4a | 810 | tty_flip_buffer_push(tport); |
f77232da | 811 | spin_lock(&port->lock); |
04896a77 RL |
812 | } |
813 | ||
3a878c43 | 814 | static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count) |
04896a77 | 815 | { |
ebd2c8f6 | 816 | struct circ_buf *xmit = &port->state->xmit; |
04896a77 | 817 | struct msm_port *msm_port = UART_TO_MSM(port); |
3a878c43 | 818 | unsigned int num_chars; |
17fae28e | 819 | unsigned int tf_pointer = 0; |
68252424 SB |
820 | void __iomem *tf; |
821 | ||
822 | if (msm_port->is_uartdm) | |
823 | tf = port->membase + UARTDM_TF; | |
824 | else | |
825 | tf = port->membase + UART_TF; | |
17fae28e | 826 | |
3a878c43 | 827 | if (tx_count && msm_port->is_uartdm) |
558abdb0 | 828 | msm_reset_dm_count(port, tx_count); |
04896a77 | 829 | |
17fae28e SB |
830 | while (tf_pointer < tx_count) { |
831 | int i; | |
832 | char buf[4] = { 0 }; | |
ec8f29e7 | 833 | |
17fae28e | 834 | if (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) |
04896a77 | 835 | break; |
04896a77 | 836 | |
ec8f29e7 | 837 | if (msm_port->is_uartdm) |
4f749f24 JH |
838 | num_chars = min(tx_count - tf_pointer, |
839 | (unsigned int)sizeof(buf)); | |
17fae28e SB |
840 | else |
841 | num_chars = 1; | |
04896a77 | 842 | |
17fae28e SB |
843 | for (i = 0; i < num_chars; i++) { |
844 | buf[i] = xmit->buf[xmit->tail + i]; | |
845 | port->icount.tx++; | |
846 | } | |
847 | ||
68252424 | 848 | iowrite32_rep(tf, buf, 1); |
17fae28e SB |
849 | xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1); |
850 | tf_pointer += num_chars; | |
04896a77 RL |
851 | } |
852 | ||
17fae28e SB |
853 | /* disable tx interrupts if nothing more to send */ |
854 | if (uart_circ_empty(xmit)) | |
855 | msm_stop_tx(port); | |
856 | ||
04896a77 RL |
857 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
858 | uart_write_wakeup(port); | |
859 | } | |
860 | ||
3a878c43 II |
861 | static void msm_handle_tx(struct uart_port *port) |
862 | { | |
863 | struct msm_port *msm_port = UART_TO_MSM(port); | |
864 | struct circ_buf *xmit = &msm_port->uart.state->xmit; | |
865 | struct msm_dma *dma = &msm_port->tx_dma; | |
866 | unsigned int pio_count, dma_count, dma_min; | |
957641a8 | 867 | char buf[4] = { 0 }; |
3a878c43 II |
868 | void __iomem *tf; |
869 | int err = 0; | |
870 | ||
871 | if (port->x_char) { | |
872 | if (msm_port->is_uartdm) | |
873 | tf = port->membase + UARTDM_TF; | |
874 | else | |
875 | tf = port->membase + UART_TF; | |
876 | ||
957641a8 JRO |
877 | buf[0] = port->x_char; |
878 | ||
3a878c43 II |
879 | if (msm_port->is_uartdm) |
880 | msm_reset_dm_count(port, 1); | |
881 | ||
957641a8 | 882 | iowrite32_rep(tf, buf, 1); |
3a878c43 II |
883 | port->icount.tx++; |
884 | port->x_char = 0; | |
885 | return; | |
886 | } | |
887 | ||
888 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | |
889 | msm_stop_tx(port); | |
890 | return; | |
891 | } | |
892 | ||
30acf549 | 893 | pio_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); |
3a878c43 II |
894 | dma_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); |
895 | ||
896 | dma_min = 1; /* Always DMA */ | |
897 | if (msm_port->is_uartdm > UARTDM_1P3) { | |
898 | dma_count = UARTDM_TX_AIGN(dma_count); | |
899 | dma_min = UARTDM_BURST_SIZE; | |
900 | } else { | |
901 | if (dma_count > UARTDM_TX_MAX) | |
902 | dma_count = UARTDM_TX_MAX; | |
903 | } | |
904 | ||
905 | if (pio_count > port->fifosize) | |
906 | pio_count = port->fifosize; | |
907 | ||
908 | if (!dma->chan || dma_count < dma_min) | |
909 | msm_handle_tx_pio(port, pio_count); | |
910 | else | |
911 | err = msm_handle_tx_dma(msm_port, dma_count); | |
912 | ||
913 | if (err) /* fall back to PIO mode */ | |
914 | msm_handle_tx_pio(port, pio_count); | |
915 | } | |
916 | ||
558abdb0 | 917 | static void msm_handle_delta_cts(struct uart_port *port) |
04896a77 RL |
918 | { |
919 | msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); | |
920 | port->icount.cts++; | |
bdc04e31 | 921 | wake_up_interruptible(&port->state->port.delta_msr_wait); |
04896a77 RL |
922 | } |
923 | ||
558abdb0 | 924 | static irqreturn_t msm_uart_irq(int irq, void *dev_id) |
04896a77 RL |
925 | { |
926 | struct uart_port *port = dev_id; | |
927 | struct msm_port *msm_port = UART_TO_MSM(port); | |
99693945 | 928 | struct msm_dma *dma = &msm_port->rx_dma; |
3a878c43 | 929 | unsigned long flags; |
04896a77 | 930 | unsigned int misr; |
99693945 | 931 | u32 val; |
04896a77 | 932 | |
3a878c43 | 933 | spin_lock_irqsave(&port->lock, flags); |
04896a77 RL |
934 | misr = msm_read(port, UART_MISR); |
935 | msm_write(port, 0, UART_IMR); /* disable interrupt */ | |
936 | ||
0896d4d4 SB |
937 | if (misr & UART_IMR_RXBREAK_START) { |
938 | msm_port->break_detected = true; | |
939 | msm_write(port, UART_CR_CMD_RESET_RXBREAK_START, UART_CR); | |
940 | } | |
941 | ||
ec8f29e7 | 942 | if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE)) { |
99693945 II |
943 | if (dma->count) { |
944 | val = UART_CR_CMD_STALE_EVENT_DISABLE; | |
945 | msm_write(port, val, UART_CR); | |
946 | val = UART_CR_CMD_RESET_STALE_INT; | |
947 | msm_write(port, val, UART_CR); | |
948 | /* | |
949 | * Flush DMA input fifo to memory, this will also | |
950 | * trigger DMA RX completion | |
951 | */ | |
952 | dmaengine_terminate_all(dma->chan); | |
953 | } else if (msm_port->is_uartdm) { | |
558abdb0 | 954 | msm_handle_rx_dm(port, misr); |
99693945 | 955 | } else { |
558abdb0 | 956 | msm_handle_rx(port); |
99693945 | 957 | } |
ec8f29e7 | 958 | } |
04896a77 | 959 | if (misr & UART_IMR_TXLEV) |
558abdb0 | 960 | msm_handle_tx(port); |
04896a77 | 961 | if (misr & UART_IMR_DELTA_CTS) |
558abdb0 | 962 | msm_handle_delta_cts(port); |
04896a77 RL |
963 | |
964 | msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */ | |
3a878c43 | 965 | spin_unlock_irqrestore(&port->lock, flags); |
04896a77 RL |
966 | |
967 | return IRQ_HANDLED; | |
968 | } | |
969 | ||
970 | static unsigned int msm_tx_empty(struct uart_port *port) | |
971 | { | |
972 | return (msm_read(port, UART_SR) & UART_SR_TX_EMPTY) ? TIOCSER_TEMT : 0; | |
973 | } | |
974 | ||
975 | static unsigned int msm_get_mctrl(struct uart_port *port) | |
976 | { | |
977 | return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR | TIOCM_RTS; | |
978 | } | |
979 | ||
ec8f29e7 | 980 | static void msm_reset(struct uart_port *port) |
04896a77 | 981 | { |
f7e54d7a | 982 | struct msm_port *msm_port = UART_TO_MSM(port); |
2c48d598 | 983 | unsigned int mr; |
f7e54d7a | 984 | |
ec8f29e7 SM |
985 | /* reset everything */ |
986 | msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); | |
987 | msm_write(port, UART_CR_CMD_RESET_TX, UART_CR); | |
988 | msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); | |
989 | msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR); | |
990 | msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); | |
2c48d598 JH |
991 | msm_write(port, UART_CR_CMD_RESET_RFR, UART_CR); |
992 | mr = msm_read(port, UART_MR1); | |
993 | mr &= ~UART_MR1_RX_RDY_CTL; | |
994 | msm_write(port, mr, UART_MR1); | |
f7e54d7a SB |
995 | |
996 | /* Disable DM modes */ | |
997 | if (msm_port->is_uartdm) | |
998 | msm_write(port, 0, UARTDM_DMEN); | |
ec8f29e7 | 999 | } |
04896a77 | 1000 | |
f8fb952f | 1001 | static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl) |
ec8f29e7 SM |
1002 | { |
1003 | unsigned int mr; | |
e919cefb | 1004 | |
04896a77 RL |
1005 | mr = msm_read(port, UART_MR1); |
1006 | ||
1007 | if (!(mctrl & TIOCM_RTS)) { | |
1008 | mr &= ~UART_MR1_RX_RDY_CTL; | |
1009 | msm_write(port, mr, UART_MR1); | |
1010 | msm_write(port, UART_CR_CMD_RESET_RFR, UART_CR); | |
1011 | } else { | |
1012 | mr |= UART_MR1_RX_RDY_CTL; | |
1013 | msm_write(port, mr, UART_MR1); | |
1014 | } | |
1015 | } | |
1016 | ||
1017 | static void msm_break_ctl(struct uart_port *port, int break_ctl) | |
1018 | { | |
1019 | if (break_ctl) | |
1020 | msm_write(port, UART_CR_CMD_START_BREAK, UART_CR); | |
1021 | else | |
1022 | msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR); | |
1023 | } | |
1024 | ||
6909dadd SB |
1025 | struct msm_baud_map { |
1026 | u16 divisor; | |
1027 | u8 code; | |
1028 | u8 rxstale; | |
1029 | }; | |
1030 | ||
1031 | static const struct msm_baud_map * | |
98952bf5 SB |
1032 | msm_find_best_baud(struct uart_port *port, unsigned int baud, |
1033 | unsigned long *rate) | |
6909dadd | 1034 | { |
98952bf5 SB |
1035 | struct msm_port *msm_port = UART_TO_MSM(port); |
1036 | unsigned int divisor, result; | |
1037 | unsigned long target, old, best_rate = 0, diff, best_diff = ULONG_MAX; | |
1038 | const struct msm_baud_map *entry, *end, *best; | |
6909dadd | 1039 | static const struct msm_baud_map table[] = { |
6909dadd | 1040 | { 1, 0xff, 31 }, |
98952bf5 SB |
1041 | { 2, 0xee, 16 }, |
1042 | { 3, 0xdd, 8 }, | |
1043 | { 4, 0xcc, 6 }, | |
1044 | { 6, 0xbb, 6 }, | |
1045 | { 8, 0xaa, 6 }, | |
1046 | { 12, 0x99, 6 }, | |
1047 | { 16, 0x88, 1 }, | |
1048 | { 24, 0x77, 1 }, | |
1049 | { 32, 0x66, 1 }, | |
1050 | { 48, 0x55, 1 }, | |
1051 | { 96, 0x44, 1 }, | |
1052 | { 192, 0x33, 1 }, | |
1053 | { 384, 0x22, 1 }, | |
1054 | { 768, 0x11, 1 }, | |
1055 | { 1536, 0x00, 1 }, | |
6909dadd SB |
1056 | }; |
1057 | ||
98952bf5 SB |
1058 | best = table; /* Default to smallest divider */ |
1059 | target = clk_round_rate(msm_port->clk, 16 * baud); | |
1060 | divisor = DIV_ROUND_CLOSEST(target, 16 * baud); | |
1061 | ||
1062 | end = table + ARRAY_SIZE(table); | |
1063 | entry = table; | |
1064 | while (entry < end) { | |
1065 | if (entry->divisor <= divisor) { | |
1066 | result = target / entry->divisor / 16; | |
1067 | diff = abs(result - baud); | |
1068 | ||
1069 | /* Keep track of best entry */ | |
1070 | if (diff < best_diff) { | |
1071 | best_diff = diff; | |
1072 | best = entry; | |
1073 | best_rate = target; | |
1074 | } | |
6909dadd | 1075 | |
98952bf5 SB |
1076 | if (result == baud) |
1077 | break; | |
1078 | } else if (entry->divisor > divisor) { | |
1079 | old = target; | |
1080 | target = clk_round_rate(msm_port->clk, old + 1); | |
1081 | /* | |
1082 | * The rate didn't get any faster so we can't do | |
1083 | * better at dividing it down | |
1084 | */ | |
1085 | if (target == old) | |
1086 | break; | |
1087 | ||
1088 | /* Start the divisor search over at this new rate */ | |
1089 | entry = table; | |
1090 | divisor = DIV_ROUND_CLOSEST(target, 16 * baud); | |
1091 | continue; | |
1092 | } | |
1093 | entry++; | |
1094 | } | |
6909dadd | 1095 | |
98952bf5 SB |
1096 | *rate = best_rate; |
1097 | return best; | |
6909dadd SB |
1098 | } |
1099 | ||
850b37a7 II |
1100 | static int msm_set_baud_rate(struct uart_port *port, unsigned int baud, |
1101 | unsigned long *saved_flags) | |
04896a77 | 1102 | { |
12b9b9f1 | 1103 | unsigned int rxstale, watermark, mask; |
ec8f29e7 | 1104 | struct msm_port *msm_port = UART_TO_MSM(port); |
6909dadd | 1105 | const struct msm_baud_map *entry; |
98952bf5 | 1106 | unsigned long flags, rate; |
850b37a7 II |
1107 | |
1108 | flags = *saved_flags; | |
1109 | spin_unlock_irqrestore(&port->lock, flags); | |
1110 | ||
98952bf5 SB |
1111 | entry = msm_find_best_baud(port, baud, &rate); |
1112 | clk_set_rate(msm_port->clk, rate); | |
1113 | baud = rate / 16 / entry->divisor; | |
850b37a7 II |
1114 | |
1115 | spin_lock_irqsave(&port->lock, flags); | |
1116 | *saved_flags = flags; | |
98952bf5 SB |
1117 | port->uartclk = rate; |
1118 | ||
1119 | msm_write(port, entry->code, UART_CSR); | |
850b37a7 | 1120 | |
04896a77 | 1121 | /* RX stale watermark */ |
6909dadd | 1122 | rxstale = entry->rxstale; |
04896a77 | 1123 | watermark = UART_IPR_STALE_LSB & rxstale; |
12b9b9f1 PG |
1124 | if (msm_port->is_uartdm) { |
1125 | mask = UART_DM_IPR_STALE_TIMEOUT_MSB; | |
1126 | } else { | |
1127 | watermark |= UART_IPR_RXSTALE_LAST; | |
1128 | mask = UART_IPR_STALE_TIMEOUT_MSB; | |
1129 | } | |
1130 | ||
1131 | watermark |= mask & (rxstale << 2); | |
1132 | ||
04896a77 RL |
1133 | msm_write(port, watermark, UART_IPR); |
1134 | ||
1135 | /* set RX watermark */ | |
1136 | watermark = (port->fifosize * 3) / 4; | |
1137 | msm_write(port, watermark, UART_RFWR); | |
1138 | ||
1139 | /* set TX watermark */ | |
1140 | msm_write(port, 10, UART_TFWR); | |
44da59e4 | 1141 | |
a12f1b40 SB |
1142 | msm_write(port, UART_CR_CMD_PROTECTION_EN, UART_CR); |
1143 | msm_reset(port); | |
1144 | ||
1145 | /* Enable RX and TX */ | |
1146 | msm_write(port, UART_CR_TX_ENABLE | UART_CR_RX_ENABLE, UART_CR); | |
1147 | ||
1148 | /* turn on RX and CTS interrupts */ | |
1149 | msm_port->imr = UART_IMR_RXLEV | UART_IMR_RXSTALE | | |
1150 | UART_IMR_CURRENT_CTS | UART_IMR_RXBREAK_START; | |
1151 | ||
1152 | msm_write(port, msm_port->imr, UART_IMR); | |
1153 | ||
ec8f29e7 SM |
1154 | if (msm_port->is_uartdm) { |
1155 | msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); | |
1156 | msm_write(port, 0xFFFFFF, UARTDM_DMRX); | |
1157 | msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); | |
1158 | } | |
1159 | ||
44da59e4 | 1160 | return baud; |
04896a77 RL |
1161 | } |
1162 | ||
04896a77 RL |
1163 | static void msm_init_clock(struct uart_port *port) |
1164 | { | |
1165 | struct msm_port *msm_port = UART_TO_MSM(port); | |
1166 | ||
f98cf83d | 1167 | clk_prepare_enable(msm_port->clk); |
bfaddb7d | 1168 | clk_prepare_enable(msm_port->pclk); |
18c79d76 | 1169 | msm_serial_set_mnd_regs(port); |
04896a77 RL |
1170 | } |
1171 | ||
1172 | static int msm_startup(struct uart_port *port) | |
1173 | { | |
1174 | struct msm_port *msm_port = UART_TO_MSM(port); | |
12b9b9f1 | 1175 | unsigned int data, rfr_level, mask; |
04896a77 RL |
1176 | int ret; |
1177 | ||
1178 | snprintf(msm_port->name, sizeof(msm_port->name), | |
1179 | "msm_serial%d", port->line); | |
1180 | ||
04896a77 RL |
1181 | msm_init_clock(port); |
1182 | ||
1183 | if (likely(port->fifosize > 12)) | |
1184 | rfr_level = port->fifosize - 12; | |
1185 | else | |
1186 | rfr_level = port->fifosize; | |
1187 | ||
1188 | /* set automatic RFR level */ | |
1189 | data = msm_read(port, UART_MR1); | |
12b9b9f1 PG |
1190 | |
1191 | if (msm_port->is_uartdm) | |
1192 | mask = UART_DM_MR1_AUTO_RFR_LEVEL1; | |
1193 | else | |
1194 | mask = UART_MR1_AUTO_RFR_LEVEL1; | |
1195 | ||
1196 | data &= ~mask; | |
04896a77 | 1197 | data &= ~UART_MR1_AUTO_RFR_LEVEL0; |
12b9b9f1 | 1198 | data |= mask & (rfr_level << 2); |
04896a77 RL |
1199 | data |= UART_MR1_AUTO_RFR_LEVEL0 & rfr_level; |
1200 | msm_write(port, data, UART_MR1); | |
12b9b9f1 | 1201 | |
99693945 | 1202 | if (msm_port->is_uartdm) { |
3a878c43 | 1203 | msm_request_tx_dma(msm_port, msm_port->uart.mapbase); |
99693945 II |
1204 | msm_request_rx_dma(msm_port, msm_port->uart.mapbase); |
1205 | } | |
3a878c43 | 1206 | |
4d691f75 NU |
1207 | ret = request_irq(port->irq, msm_uart_irq, IRQF_TRIGGER_HIGH, |
1208 | msm_port->name, port); | |
1209 | if (unlikely(ret)) | |
1210 | goto err_irq; | |
1211 | ||
04896a77 | 1212 | return 0; |
4d691f75 NU |
1213 | |
1214 | err_irq: | |
1215 | if (msm_port->is_uartdm) | |
1216 | msm_release_dma(msm_port); | |
1217 | ||
1218 | clk_disable_unprepare(msm_port->pclk); | |
1219 | clk_disable_unprepare(msm_port->clk); | |
1220 | ||
1221 | return ret; | |
04896a77 RL |
1222 | } |
1223 | ||
1224 | static void msm_shutdown(struct uart_port *port) | |
1225 | { | |
1226 | struct msm_port *msm_port = UART_TO_MSM(port); | |
1227 | ||
1228 | msm_port->imr = 0; | |
1229 | msm_write(port, 0, UART_IMR); /* disable interrupts */ | |
1230 | ||
3a878c43 II |
1231 | if (msm_port->is_uartdm) |
1232 | msm_release_dma(msm_port); | |
1233 | ||
f98cf83d | 1234 | clk_disable_unprepare(msm_port->clk); |
04896a77 RL |
1235 | |
1236 | free_irq(port->irq, port); | |
1237 | } | |
1238 | ||
1239 | static void msm_set_termios(struct uart_port *port, struct ktermios *termios, | |
1240 | struct ktermios *old) | |
1241 | { | |
99693945 II |
1242 | struct msm_port *msm_port = UART_TO_MSM(port); |
1243 | struct msm_dma *dma = &msm_port->rx_dma; | |
04896a77 RL |
1244 | unsigned long flags; |
1245 | unsigned int baud, mr; | |
1246 | ||
1247 | spin_lock_irqsave(&port->lock, flags); | |
1248 | ||
99693945 II |
1249 | if (dma->chan) /* Terminate if any */ |
1250 | msm_stop_dma(port, dma); | |
1251 | ||
04896a77 | 1252 | /* calculate and set baud rate */ |
850b37a7 II |
1253 | baud = uart_get_baud_rate(port, termios, old, 300, 4000000); |
1254 | baud = msm_set_baud_rate(port, baud, &flags); | |
44da59e4 AC |
1255 | if (tty_termios_baud_rate(termios)) |
1256 | tty_termios_encode_baud_rate(termios, baud, baud); | |
ec8f29e7 | 1257 | |
04896a77 RL |
1258 | /* calculate parity */ |
1259 | mr = msm_read(port, UART_MR2); | |
1260 | mr &= ~UART_MR2_PARITY_MODE; | |
1261 | if (termios->c_cflag & PARENB) { | |
1262 | if (termios->c_cflag & PARODD) | |
1263 | mr |= UART_MR2_PARITY_MODE_ODD; | |
1264 | else if (termios->c_cflag & CMSPAR) | |
1265 | mr |= UART_MR2_PARITY_MODE_SPACE; | |
1266 | else | |
1267 | mr |= UART_MR2_PARITY_MODE_EVEN; | |
1268 | } | |
1269 | ||
1270 | /* calculate bits per char */ | |
1271 | mr &= ~UART_MR2_BITS_PER_CHAR; | |
1272 | switch (termios->c_cflag & CSIZE) { | |
1273 | case CS5: | |
1274 | mr |= UART_MR2_BITS_PER_CHAR_5; | |
1275 | break; | |
1276 | case CS6: | |
1277 | mr |= UART_MR2_BITS_PER_CHAR_6; | |
1278 | break; | |
1279 | case CS7: | |
1280 | mr |= UART_MR2_BITS_PER_CHAR_7; | |
1281 | break; | |
1282 | case CS8: | |
1283 | default: | |
1284 | mr |= UART_MR2_BITS_PER_CHAR_8; | |
1285 | break; | |
1286 | } | |
1287 | ||
1288 | /* calculate stop bits */ | |
1289 | mr &= ~(UART_MR2_STOP_BIT_LEN_ONE | UART_MR2_STOP_BIT_LEN_TWO); | |
1290 | if (termios->c_cflag & CSTOPB) | |
1291 | mr |= UART_MR2_STOP_BIT_LEN_TWO; | |
1292 | else | |
1293 | mr |= UART_MR2_STOP_BIT_LEN_ONE; | |
1294 | ||
1295 | /* set parity, bits per char, and stop bit */ | |
1296 | msm_write(port, mr, UART_MR2); | |
1297 | ||
1298 | /* calculate and set hardware flow control */ | |
1299 | mr = msm_read(port, UART_MR1); | |
1300 | mr &= ~(UART_MR1_CTS_CTL | UART_MR1_RX_RDY_CTL); | |
1301 | if (termios->c_cflag & CRTSCTS) { | |
1302 | mr |= UART_MR1_CTS_CTL; | |
1303 | mr |= UART_MR1_RX_RDY_CTL; | |
1304 | } | |
1305 | msm_write(port, mr, UART_MR1); | |
1306 | ||
1307 | /* Configure status bits to ignore based on termio flags. */ | |
1308 | port->read_status_mask = 0; | |
1309 | if (termios->c_iflag & INPCK) | |
1310 | port->read_status_mask |= UART_SR_PAR_FRAME_ERR; | |
ef8b9ddc | 1311 | if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) |
04896a77 RL |
1312 | port->read_status_mask |= UART_SR_RX_BREAK; |
1313 | ||
1314 | uart_update_timeout(port, termios->c_cflag, baud); | |
1315 | ||
99693945 II |
1316 | /* Try to use DMA */ |
1317 | msm_start_rx_dma(msm_port); | |
1318 | ||
04896a77 RL |
1319 | spin_unlock_irqrestore(&port->lock, flags); |
1320 | } | |
1321 | ||
1322 | static const char *msm_type(struct uart_port *port) | |
1323 | { | |
1324 | return "MSM"; | |
1325 | } | |
1326 | ||
1327 | static void msm_release_port(struct uart_port *port) | |
1328 | { | |
1329 | struct platform_device *pdev = to_platform_device(port->dev); | |
ec8f29e7 | 1330 | struct resource *uart_resource; |
04896a77 RL |
1331 | resource_size_t size; |
1332 | ||
ec8f29e7 SM |
1333 | uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1334 | if (unlikely(!uart_resource)) | |
04896a77 | 1335 | return; |
ec8f29e7 | 1336 | size = resource_size(uart_resource); |
04896a77 RL |
1337 | |
1338 | release_mem_region(port->mapbase, size); | |
1339 | iounmap(port->membase); | |
1340 | port->membase = NULL; | |
1341 | } | |
1342 | ||
1343 | static int msm_request_port(struct uart_port *port) | |
1344 | { | |
1345 | struct platform_device *pdev = to_platform_device(port->dev); | |
ec8f29e7 | 1346 | struct resource *uart_resource; |
04896a77 | 1347 | resource_size_t size; |
ec8f29e7 | 1348 | int ret; |
04896a77 | 1349 | |
886a451b | 1350 | uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
ec8f29e7 | 1351 | if (unlikely(!uart_resource)) |
04896a77 | 1352 | return -ENXIO; |
04896a77 | 1353 | |
ec8f29e7 SM |
1354 | size = resource_size(uart_resource); |
1355 | ||
1356 | if (!request_mem_region(port->mapbase, size, "msm_serial")) | |
04896a77 RL |
1357 | return -EBUSY; |
1358 | ||
1359 | port->membase = ioremap(port->mapbase, size); | |
1360 | if (!port->membase) { | |
ec8f29e7 SM |
1361 | ret = -EBUSY; |
1362 | goto fail_release_port; | |
1363 | } | |
1364 | ||
04896a77 | 1365 | return 0; |
ec8f29e7 | 1366 | |
ec8f29e7 SM |
1367 | fail_release_port: |
1368 | release_mem_region(port->mapbase, size); | |
1369 | return ret; | |
04896a77 RL |
1370 | } |
1371 | ||
1372 | static void msm_config_port(struct uart_port *port, int flags) | |
1373 | { | |
ec8f29e7 | 1374 | int ret; |
e919cefb | 1375 | |
04896a77 RL |
1376 | if (flags & UART_CONFIG_TYPE) { |
1377 | port->type = PORT_MSM; | |
ec8f29e7 SM |
1378 | ret = msm_request_port(port); |
1379 | if (ret) | |
1380 | return; | |
04896a77 RL |
1381 | } |
1382 | } | |
1383 | ||
1384 | static int msm_verify_port(struct uart_port *port, struct serial_struct *ser) | |
1385 | { | |
1386 | if (unlikely(ser->type != PORT_UNKNOWN && ser->type != PORT_MSM)) | |
1387 | return -EINVAL; | |
1388 | if (unlikely(port->irq != ser->irq)) | |
1389 | return -EINVAL; | |
1390 | return 0; | |
1391 | } | |
1392 | ||
1393 | static void msm_power(struct uart_port *port, unsigned int state, | |
1394 | unsigned int oldstate) | |
1395 | { | |
1396 | struct msm_port *msm_port = UART_TO_MSM(port); | |
1397 | ||
1398 | switch (state) { | |
1399 | case 0: | |
f98cf83d | 1400 | clk_prepare_enable(msm_port->clk); |
bfaddb7d | 1401 | clk_prepare_enable(msm_port->pclk); |
04896a77 RL |
1402 | break; |
1403 | case 3: | |
f98cf83d | 1404 | clk_disable_unprepare(msm_port->clk); |
bfaddb7d | 1405 | clk_disable_unprepare(msm_port->pclk); |
04896a77 RL |
1406 | break; |
1407 | default: | |
6a7cfe46 | 1408 | pr_err("msm_serial: Unknown PM state %d\n", state); |
04896a77 RL |
1409 | } |
1410 | } | |
1411 | ||
f7e54d7a | 1412 | #ifdef CONFIG_CONSOLE_POLL |
f7e54d7a SB |
1413 | static int msm_poll_get_char_single(struct uart_port *port) |
1414 | { | |
1415 | struct msm_port *msm_port = UART_TO_MSM(port); | |
1416 | unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : UART_RF; | |
1417 | ||
1418 | if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) | |
1419 | return NO_POLL_CHAR; | |
6f47abcb KP |
1420 | |
1421 | return msm_read(port, rf_reg) & 0xff; | |
f7e54d7a SB |
1422 | } |
1423 | ||
8b374399 | 1424 | static int msm_poll_get_char_dm(struct uart_port *port) |
f7e54d7a SB |
1425 | { |
1426 | int c; | |
1427 | static u32 slop; | |
1428 | static int count; | |
1429 | unsigned char *sp = (unsigned char *)&slop; | |
1430 | ||
1431 | /* Check if a previous read had more than one char */ | |
1432 | if (count) { | |
1433 | c = sp[sizeof(slop) - count]; | |
1434 | count--; | |
1435 | /* Or if FIFO is empty */ | |
1436 | } else if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) { | |
1437 | /* | |
1438 | * If RX packing buffer has less than a word, force stale to | |
1439 | * push contents into RX FIFO | |
1440 | */ | |
1441 | count = msm_read(port, UARTDM_RXFS); | |
1442 | count = (count >> UARTDM_RXFS_BUF_SHIFT) & UARTDM_RXFS_BUF_MASK; | |
1443 | if (count) { | |
1444 | msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR); | |
1445 | slop = msm_read(port, UARTDM_RF); | |
1446 | c = sp[0]; | |
1447 | count--; | |
8b374399 SB |
1448 | msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); |
1449 | msm_write(port, 0xFFFFFF, UARTDM_DMRX); | |
1450 | msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, | |
1451 | UART_CR); | |
f7e54d7a SB |
1452 | } else { |
1453 | c = NO_POLL_CHAR; | |
1454 | } | |
1455 | /* FIFO has a word */ | |
1456 | } else { | |
1457 | slop = msm_read(port, UARTDM_RF); | |
1458 | c = sp[0]; | |
1459 | count = sizeof(slop) - 1; | |
1460 | } | |
1461 | ||
1462 | return c; | |
1463 | } | |
1464 | ||
1465 | static int msm_poll_get_char(struct uart_port *port) | |
1466 | { | |
1467 | u32 imr; | |
1468 | int c; | |
1469 | struct msm_port *msm_port = UART_TO_MSM(port); | |
1470 | ||
1471 | /* Disable all interrupts */ | |
1472 | imr = msm_read(port, UART_IMR); | |
1473 | msm_write(port, 0, UART_IMR); | |
1474 | ||
8b374399 SB |
1475 | if (msm_port->is_uartdm) |
1476 | c = msm_poll_get_char_dm(port); | |
f7e54d7a SB |
1477 | else |
1478 | c = msm_poll_get_char_single(port); | |
1479 | ||
1480 | /* Enable interrupts */ | |
1481 | msm_write(port, imr, UART_IMR); | |
1482 | ||
1483 | return c; | |
1484 | } | |
1485 | ||
1486 | static void msm_poll_put_char(struct uart_port *port, unsigned char c) | |
1487 | { | |
1488 | u32 imr; | |
1489 | struct msm_port *msm_port = UART_TO_MSM(port); | |
1490 | ||
1491 | /* Disable all interrupts */ | |
1492 | imr = msm_read(port, UART_IMR); | |
1493 | msm_write(port, 0, UART_IMR); | |
1494 | ||
1495 | if (msm_port->is_uartdm) | |
558abdb0 | 1496 | msm_reset_dm_count(port, 1); |
f7e54d7a SB |
1497 | |
1498 | /* Wait until FIFO is empty */ | |
1499 | while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) | |
1500 | cpu_relax(); | |
1501 | ||
1502 | /* Write a character */ | |
1503 | msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF); | |
1504 | ||
1505 | /* Wait until FIFO is empty */ | |
1506 | while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) | |
1507 | cpu_relax(); | |
1508 | ||
1509 | /* Enable interrupts */ | |
1510 | msm_write(port, imr, UART_IMR); | |
f7e54d7a SB |
1511 | } |
1512 | #endif | |
1513 | ||
04896a77 RL |
1514 | static struct uart_ops msm_uart_pops = { |
1515 | .tx_empty = msm_tx_empty, | |
1516 | .set_mctrl = msm_set_mctrl, | |
1517 | .get_mctrl = msm_get_mctrl, | |
1518 | .stop_tx = msm_stop_tx, | |
1519 | .start_tx = msm_start_tx, | |
1520 | .stop_rx = msm_stop_rx, | |
1521 | .enable_ms = msm_enable_ms, | |
1522 | .break_ctl = msm_break_ctl, | |
1523 | .startup = msm_startup, | |
1524 | .shutdown = msm_shutdown, | |
1525 | .set_termios = msm_set_termios, | |
1526 | .type = msm_type, | |
1527 | .release_port = msm_release_port, | |
1528 | .request_port = msm_request_port, | |
1529 | .config_port = msm_config_port, | |
1530 | .verify_port = msm_verify_port, | |
1531 | .pm = msm_power, | |
f7e54d7a | 1532 | #ifdef CONFIG_CONSOLE_POLL |
f7e54d7a SB |
1533 | .poll_get_char = msm_poll_get_char, |
1534 | .poll_put_char = msm_poll_put_char, | |
1535 | #endif | |
04896a77 RL |
1536 | }; |
1537 | ||
1538 | static struct msm_port msm_uart_ports[] = { | |
1539 | { | |
1540 | .uart = { | |
1541 | .iotype = UPIO_MEM, | |
1542 | .ops = &msm_uart_pops, | |
1543 | .flags = UPF_BOOT_AUTOCONF, | |
ec8f29e7 | 1544 | .fifosize = 64, |
04896a77 RL |
1545 | .line = 0, |
1546 | }, | |
1547 | }, | |
1548 | { | |
1549 | .uart = { | |
1550 | .iotype = UPIO_MEM, | |
1551 | .ops = &msm_uart_pops, | |
1552 | .flags = UPF_BOOT_AUTOCONF, | |
ec8f29e7 | 1553 | .fifosize = 64, |
04896a77 RL |
1554 | .line = 1, |
1555 | }, | |
1556 | }, | |
1557 | { | |
1558 | .uart = { | |
1559 | .iotype = UPIO_MEM, | |
1560 | .ops = &msm_uart_pops, | |
1561 | .flags = UPF_BOOT_AUTOCONF, | |
1562 | .fifosize = 64, | |
1563 | .line = 2, | |
1564 | }, | |
1565 | }, | |
1566 | }; | |
1567 | ||
1568 | #define UART_NR ARRAY_SIZE(msm_uart_ports) | |
1569 | ||
558abdb0 | 1570 | static inline struct uart_port *msm_get_port_from_line(unsigned int line) |
04896a77 RL |
1571 | { |
1572 | return &msm_uart_ports[line].uart; | |
1573 | } | |
1574 | ||
1575 | #ifdef CONFIG_SERIAL_MSM_CONSOLE | |
0efe7296 SB |
1576 | static void __msm_console_write(struct uart_port *port, const char *s, |
1577 | unsigned int count, bool is_uartdm) | |
04896a77 | 1578 | { |
a3957e80 | 1579 | int i; |
a3957e80 SB |
1580 | int num_newlines = 0; |
1581 | bool replaced = false; | |
68252424 | 1582 | void __iomem *tf; |
9fc977d9 | 1583 | int locked = 1; |
04896a77 | 1584 | |
0efe7296 | 1585 | if (is_uartdm) |
68252424 SB |
1586 | tf = port->membase + UARTDM_TF; |
1587 | else | |
1588 | tf = port->membase + UART_TF; | |
1589 | ||
a3957e80 SB |
1590 | /* Account for newlines that will get a carriage return added */ |
1591 | for (i = 0; i < count; i++) | |
1592 | if (s[i] == '\n') | |
1593 | num_newlines++; | |
1594 | count += num_newlines; | |
1595 | ||
9fc977d9 LY |
1596 | if (port->sysrq) |
1597 | locked = 0; | |
1598 | else if (oops_in_progress) | |
1599 | locked = spin_trylock(&port->lock); | |
1600 | else | |
1601 | spin_lock(&port->lock); | |
1602 | ||
0efe7296 | 1603 | if (is_uartdm) |
558abdb0 | 1604 | msm_reset_dm_count(port, count); |
a3957e80 SB |
1605 | |
1606 | i = 0; | |
1607 | while (i < count) { | |
1608 | int j; | |
1609 | unsigned int num_chars; | |
1610 | char buf[4] = { 0 }; | |
a3957e80 | 1611 | |
0efe7296 | 1612 | if (is_uartdm) |
a3957e80 SB |
1613 | num_chars = min(count - i, (unsigned int)sizeof(buf)); |
1614 | else | |
1615 | num_chars = 1; | |
1616 | ||
1617 | for (j = 0; j < num_chars; j++) { | |
1618 | char c = *s; | |
1619 | ||
1620 | if (c == '\n' && !replaced) { | |
1621 | buf[j] = '\r'; | |
1622 | j++; | |
1623 | replaced = true; | |
1624 | } | |
1625 | if (j < num_chars) { | |
1626 | buf[j] = c; | |
1627 | s++; | |
1628 | replaced = false; | |
1629 | } | |
1630 | } | |
1631 | ||
1632 | while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) | |
1633 | cpu_relax(); | |
1634 | ||
68252424 | 1635 | iowrite32_rep(tf, buf, 1); |
a3957e80 SB |
1636 | i += num_chars; |
1637 | } | |
9fc977d9 LY |
1638 | |
1639 | if (locked) | |
1640 | spin_unlock(&port->lock); | |
04896a77 RL |
1641 | } |
1642 | ||
0efe7296 SB |
1643 | static void msm_console_write(struct console *co, const char *s, |
1644 | unsigned int count) | |
1645 | { | |
1646 | struct uart_port *port; | |
1647 | struct msm_port *msm_port; | |
1648 | ||
1649 | BUG_ON(co->index < 0 || co->index >= UART_NR); | |
1650 | ||
558abdb0 | 1651 | port = msm_get_port_from_line(co->index); |
0efe7296 SB |
1652 | msm_port = UART_TO_MSM(port); |
1653 | ||
1654 | __msm_console_write(port, s, count, msm_port->is_uartdm); | |
1655 | } | |
1656 | ||
04896a77 RL |
1657 | static int __init msm_console_setup(struct console *co, char *options) |
1658 | { | |
1659 | struct uart_port *port; | |
4daba334 PG |
1660 | int baud = 115200; |
1661 | int bits = 8; | |
1662 | int parity = 'n'; | |
1663 | int flow = 'n'; | |
04896a77 RL |
1664 | |
1665 | if (unlikely(co->index >= UART_NR || co->index < 0)) | |
1666 | return -ENXIO; | |
1667 | ||
558abdb0 | 1668 | port = msm_get_port_from_line(co->index); |
04896a77 RL |
1669 | |
1670 | if (unlikely(!port->membase)) | |
1671 | return -ENXIO; | |
1672 | ||
04896a77 RL |
1673 | msm_init_clock(port); |
1674 | ||
1675 | if (options) | |
1676 | uart_parse_options(options, &baud, &parity, &bits, &flow); | |
1677 | ||
6a7cfe46 | 1678 | pr_info("msm_serial: console setup on port #%d\n", port->line); |
04896a77 RL |
1679 | |
1680 | return uart_set_options(port, co, baud, parity, bits, flow); | |
1681 | } | |
1682 | ||
0efe7296 SB |
1683 | static void |
1684 | msm_serial_early_write(struct console *con, const char *s, unsigned n) | |
1685 | { | |
1686 | struct earlycon_device *dev = con->data; | |
1687 | ||
1688 | __msm_console_write(&dev->port, s, n, false); | |
1689 | } | |
1690 | ||
1691 | static int __init | |
1692 | msm_serial_early_console_setup(struct earlycon_device *device, const char *opt) | |
1693 | { | |
1694 | if (!device->port.membase) | |
1695 | return -ENODEV; | |
1696 | ||
1697 | device->con->write = msm_serial_early_write; | |
1698 | return 0; | |
1699 | } | |
0efe7296 SB |
1700 | OF_EARLYCON_DECLARE(msm_serial, "qcom,msm-uart", |
1701 | msm_serial_early_console_setup); | |
1702 | ||
1703 | static void | |
1704 | msm_serial_early_write_dm(struct console *con, const char *s, unsigned n) | |
1705 | { | |
1706 | struct earlycon_device *dev = con->data; | |
1707 | ||
1708 | __msm_console_write(&dev->port, s, n, true); | |
1709 | } | |
1710 | ||
1711 | static int __init | |
1712 | msm_serial_early_console_setup_dm(struct earlycon_device *device, | |
1713 | const char *opt) | |
1714 | { | |
1715 | if (!device->port.membase) | |
1716 | return -ENODEV; | |
1717 | ||
1718 | device->con->write = msm_serial_early_write_dm; | |
1719 | return 0; | |
1720 | } | |
0efe7296 SB |
1721 | OF_EARLYCON_DECLARE(msm_serial_dm, "qcom,msm-uartdm", |
1722 | msm_serial_early_console_setup_dm); | |
1723 | ||
04896a77 RL |
1724 | static struct uart_driver msm_uart_driver; |
1725 | ||
1726 | static struct console msm_console = { | |
1727 | .name = "ttyMSM", | |
1728 | .write = msm_console_write, | |
1729 | .device = uart_console_device, | |
1730 | .setup = msm_console_setup, | |
1731 | .flags = CON_PRINTBUFFER, | |
1732 | .index = -1, | |
1733 | .data = &msm_uart_driver, | |
1734 | }; | |
1735 | ||
1736 | #define MSM_CONSOLE (&msm_console) | |
1737 | ||
1738 | #else | |
1739 | #define MSM_CONSOLE NULL | |
1740 | #endif | |
1741 | ||
1742 | static struct uart_driver msm_uart_driver = { | |
1743 | .owner = THIS_MODULE, | |
1744 | .driver_name = "msm_serial", | |
1745 | .dev_name = "ttyMSM", | |
1746 | .nr = UART_NR, | |
1747 | .cons = MSM_CONSOLE, | |
1748 | }; | |
1749 | ||
cfdad2ab DB |
1750 | static atomic_t msm_uart_next_id = ATOMIC_INIT(0); |
1751 | ||
c3b5d3be | 1752 | static const struct of_device_id msm_uartdm_table[] = { |
f7e54d7a SB |
1753 | { .compatible = "qcom,msm-uartdm-v1.1", .data = (void *)UARTDM_1P1 }, |
1754 | { .compatible = "qcom,msm-uartdm-v1.2", .data = (void *)UARTDM_1P2 }, | |
1755 | { .compatible = "qcom,msm-uartdm-v1.3", .data = (void *)UARTDM_1P3 }, | |
1756 | { .compatible = "qcom,msm-uartdm-v1.4", .data = (void *)UARTDM_1P4 }, | |
c3b5d3be SB |
1757 | { } |
1758 | }; | |
1759 | ||
4cc29462 | 1760 | static int msm_serial_probe(struct platform_device *pdev) |
04896a77 RL |
1761 | { |
1762 | struct msm_port *msm_port; | |
1763 | struct resource *resource; | |
1764 | struct uart_port *port; | |
f7e54d7a | 1765 | const struct of_device_id *id; |
97f75471 | 1766 | int irq, line; |
04896a77 | 1767 | |
97f75471 SB |
1768 | if (pdev->dev.of_node) |
1769 | line = of_alias_get_id(pdev->dev.of_node, "serial"); | |
1770 | else | |
1771 | line = pdev->id; | |
1772 | ||
7920408b SB |
1773 | if (line < 0) |
1774 | line = atomic_inc_return(&msm_uart_next_id) - 1; | |
1775 | ||
97f75471 | 1776 | if (unlikely(line < 0 || line >= UART_NR)) |
04896a77 RL |
1777 | return -ENXIO; |
1778 | ||
97f75471 | 1779 | dev_info(&pdev->dev, "msm_serial: detected port #%d\n", line); |
04896a77 | 1780 | |
558abdb0 | 1781 | port = msm_get_port_from_line(line); |
04896a77 RL |
1782 | port->dev = &pdev->dev; |
1783 | msm_port = UART_TO_MSM(port); | |
1784 | ||
f7e54d7a SB |
1785 | id = of_match_device(msm_uartdm_table, &pdev->dev); |
1786 | if (id) | |
1787 | msm_port->is_uartdm = (unsigned long)id->data; | |
ec8f29e7 SM |
1788 | else |
1789 | msm_port->is_uartdm = 0; | |
1790 | ||
bfaddb7d | 1791 | msm_port->clk = devm_clk_get(&pdev->dev, "core"); |
519b371d SB |
1792 | if (IS_ERR(msm_port->clk)) |
1793 | return PTR_ERR(msm_port->clk); | |
1794 | ||
1795 | if (msm_port->is_uartdm) { | |
bfaddb7d | 1796 | msm_port->pclk = devm_clk_get(&pdev->dev, "iface"); |
519b371d SB |
1797 | if (IS_ERR(msm_port->pclk)) |
1798 | return PTR_ERR(msm_port->pclk); | |
519b371d | 1799 | } |
ec8f29e7 | 1800 | |
04896a77 | 1801 | port->uartclk = clk_get_rate(msm_port->clk); |
6a7cfe46 | 1802 | dev_info(&pdev->dev, "uartclk = %d\n", port->uartclk); |
04896a77 | 1803 | |
886a451b | 1804 | resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
04896a77 RL |
1805 | if (unlikely(!resource)) |
1806 | return -ENXIO; | |
1807 | port->mapbase = resource->start; | |
1808 | ||
1e091751 RK |
1809 | irq = platform_get_irq(pdev, 0); |
1810 | if (unlikely(irq < 0)) | |
04896a77 | 1811 | return -ENXIO; |
1e091751 | 1812 | port->irq = irq; |
04896a77 RL |
1813 | |
1814 | platform_set_drvdata(pdev, port); | |
1815 | ||
1816 | return uart_add_one_port(&msm_uart_driver, port); | |
1817 | } | |
1818 | ||
ae8d8a14 | 1819 | static int msm_serial_remove(struct platform_device *pdev) |
04896a77 | 1820 | { |
519b371d | 1821 | struct uart_port *port = platform_get_drvdata(pdev); |
04896a77 | 1822 | |
519b371d | 1823 | uart_remove_one_port(&msm_uart_driver, port); |
04896a77 RL |
1824 | |
1825 | return 0; | |
1826 | } | |
1827 | ||
af300539 | 1828 | static const struct of_device_id msm_match_table[] = { |
cfdad2ab | 1829 | { .compatible = "qcom,msm-uart" }, |
c3b5d3be | 1830 | { .compatible = "qcom,msm-uartdm" }, |
cfdad2ab DB |
1831 | {} |
1832 | }; | |
abe81f3b | 1833 | MODULE_DEVICE_TABLE(of, msm_match_table); |
cfdad2ab | 1834 | |
04896a77 | 1835 | static struct platform_driver msm_platform_driver = { |
04896a77 | 1836 | .remove = msm_serial_remove, |
31964ffe | 1837 | .probe = msm_serial_probe, |
04896a77 RL |
1838 | .driver = { |
1839 | .name = "msm_serial", | |
cfdad2ab | 1840 | .of_match_table = msm_match_table, |
04896a77 RL |
1841 | }, |
1842 | }; | |
1843 | ||
1844 | static int __init msm_serial_init(void) | |
1845 | { | |
1846 | int ret; | |
1847 | ||
1848 | ret = uart_register_driver(&msm_uart_driver); | |
1849 | if (unlikely(ret)) | |
1850 | return ret; | |
1851 | ||
31964ffe | 1852 | ret = platform_driver_register(&msm_platform_driver); |
04896a77 RL |
1853 | if (unlikely(ret)) |
1854 | uart_unregister_driver(&msm_uart_driver); | |
1855 | ||
6a7cfe46 | 1856 | pr_info("msm_serial: driver initialized\n"); |
04896a77 RL |
1857 | |
1858 | return ret; | |
1859 | } | |
1860 | ||
1861 | static void __exit msm_serial_exit(void) | |
1862 | { | |
04896a77 RL |
1863 | platform_driver_unregister(&msm_platform_driver); |
1864 | uart_unregister_driver(&msm_uart_driver); | |
1865 | } | |
1866 | ||
1867 | module_init(msm_serial_init); | |
1868 | module_exit(msm_serial_exit); | |
1869 | ||
1870 | MODULE_AUTHOR("Robert Love <rlove@google.com>"); | |
1871 | MODULE_DESCRIPTION("Driver for msm7x serial device"); | |
1872 | MODULE_LICENSE("GPL"); |