diff options
-rw-r--r-- | Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt | 3 | ||||
-rw-r--r-- | drivers/tty/serial/msm_serial.c | 232 | ||||
-rw-r--r-- | drivers/tty/serial/msm_serial.h | 4 |
3 files changed, 236 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt b/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt index a600023d9ec1..182777fac9a2 100644 --- a/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt +++ b/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt | |||
@@ -29,6 +29,9 @@ Optional properties: | |||
29 | - qcom,tx-crci: Identificator <u32> for Client Rate Control Interface to be | 29 | - qcom,tx-crci: Identificator <u32> for Client Rate Control Interface to be |
30 | used with TX DMA channel. Required when using DMA for transmission | 30 | used with TX DMA channel. Required when using DMA for transmission |
31 | with UARTDM v1.3 and bellow. | 31 | with UARTDM v1.3 and bellow. |
32 | - qcom,rx-crci: Identificator <u32> for Client Rate Control Interface to be | ||
33 | used with RX DMA channel. Required when using DMA for reception | ||
34 | with UARTDM v1.3 and bellow. | ||
32 | 35 | ||
33 | Note: Aliases may be defined to ensure the correct ordering of the UARTs. | 36 | Note: Aliases may be defined to ensure the correct ordering of the UARTs. |
34 | The alias serialN will result in the UART being assigned port N. If any | 37 | The alias serialN will result in the UART being assigned port N. If any |
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 7006d979d9d2..3efb80f511db 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/tty_flip.h> | 33 | #include <linux/tty_flip.h> |
34 | #include <linux/serial_core.h> | 34 | #include <linux/serial_core.h> |
35 | #include <linux/serial.h> | 35 | #include <linux/serial.h> |
36 | #include <linux/slab.h> | ||
36 | #include <linux/clk.h> | 37 | #include <linux/clk.h> |
37 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
38 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
@@ -44,6 +45,7 @@ | |||
44 | #define UARTDM_BURST_SIZE 16 /* in bytes */ | 45 | #define UARTDM_BURST_SIZE 16 /* in bytes */ |
45 | #define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */ | 46 | #define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */ |
46 | #define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */ | 47 | #define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */ |
48 | #define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4) | ||
47 | 49 | ||
48 | enum { | 50 | enum { |
49 | UARTDM_1P1 = 1, | 51 | UARTDM_1P1 = 1, |
@@ -73,9 +75,11 @@ struct msm_port { | |||
73 | unsigned int old_snap_state; | 75 | unsigned int old_snap_state; |
74 | bool break_detected; | 76 | bool break_detected; |
75 | struct msm_dma tx_dma; | 77 | struct msm_dma tx_dma; |
78 | struct msm_dma rx_dma; | ||
76 | }; | 79 | }; |
77 | 80 | ||
78 | static void msm_handle_tx(struct uart_port *port); | 81 | static void msm_handle_tx(struct uart_port *port); |
82 | static void msm_start_rx_dma(struct msm_port *msm_port); | ||
79 | 83 | ||
80 | void msm_stop_dma(struct uart_port *port, struct msm_dma *dma) | 84 | void msm_stop_dma(struct uart_port *port, struct msm_dma *dma) |
81 | { | 85 | { |
@@ -114,6 +118,15 @@ static void msm_release_dma(struct msm_port *msm_port) | |||
114 | } | 118 | } |
115 | 119 | ||
116 | memset(dma, 0, sizeof(*dma)); | 120 | memset(dma, 0, sizeof(*dma)); |
121 | |||
122 | dma = &msm_port->rx_dma; | ||
123 | if (dma->chan) { | ||
124 | msm_stop_dma(&msm_port->uart, dma); | ||
125 | dma_release_channel(dma->chan); | ||
126 | kfree(dma->virt); | ||
127 | } | ||
128 | |||
129 | memset(dma, 0, sizeof(*dma)); | ||
117 | } | 130 | } |
118 | 131 | ||
119 | static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base) | 132 | static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base) |
@@ -159,6 +172,54 @@ no_tx: | |||
159 | memset(dma, 0, sizeof(*dma)); | 172 | memset(dma, 0, sizeof(*dma)); |
160 | } | 173 | } |
161 | 174 | ||
175 | static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base) | ||
176 | { | ||
177 | struct device *dev = msm_port->uart.dev; | ||
178 | struct dma_slave_config conf; | ||
179 | struct msm_dma *dma; | ||
180 | u32 crci = 0; | ||
181 | int ret; | ||
182 | |||
183 | dma = &msm_port->rx_dma; | ||
184 | |||
185 | /* allocate DMA resources, if available */ | ||
186 | dma->chan = dma_request_slave_channel_reason(dev, "rx"); | ||
187 | if (IS_ERR(dma->chan)) | ||
188 | goto no_rx; | ||
189 | |||
190 | of_property_read_u32(dev->of_node, "qcom,rx-crci", &crci); | ||
191 | |||
192 | dma->virt = kzalloc(UARTDM_RX_SIZE, GFP_KERNEL); | ||
193 | if (!dma->virt) | ||
194 | goto rel_rx; | ||
195 | |||
196 | memset(&conf, 0, sizeof(conf)); | ||
197 | conf.direction = DMA_DEV_TO_MEM; | ||
198 | conf.device_fc = true; | ||
199 | conf.src_addr = base + UARTDM_RF; | ||
200 | conf.src_maxburst = UARTDM_BURST_SIZE; | ||
201 | conf.slave_id = crci; | ||
202 | |||
203 | ret = dmaengine_slave_config(dma->chan, &conf); | ||
204 | if (ret) | ||
205 | goto err; | ||
206 | |||
207 | dma->dir = DMA_FROM_DEVICE; | ||
208 | |||
209 | if (msm_port->is_uartdm < UARTDM_1P4) | ||
210 | dma->enable_bit = UARTDM_DMEN_RX_DM_ENABLE; | ||
211 | else | ||
212 | dma->enable_bit = UARTDM_DMEN_RX_BAM_ENABLE; | ||
213 | |||
214 | return; | ||
215 | err: | ||
216 | kfree(dma->virt); | ||
217 | rel_rx: | ||
218 | dma_release_channel(dma->chan); | ||
219 | no_rx: | ||
220 | memset(dma, 0, sizeof(*dma)); | ||
221 | } | ||
222 | |||
162 | static inline void msm_wait_for_xmitr(struct uart_port *port) | 223 | static inline void msm_wait_for_xmitr(struct uart_port *port) |
163 | { | 224 | { |
164 | while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) { | 225 | while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) { |
@@ -306,12 +367,151 @@ unmap: | |||
306 | dma_unmap_single(port->dev, dma->phys, count, dma->dir); | 367 | dma_unmap_single(port->dev, dma->phys, count, dma->dir); |
307 | return ret; | 368 | return ret; |
308 | } | 369 | } |
370 | |||
371 | static void msm_complete_rx_dma(void *args) | ||
372 | { | ||
373 | struct msm_port *msm_port = args; | ||
374 | struct uart_port *port = &msm_port->uart; | ||
375 | struct tty_port *tport = &port->state->port; | ||
376 | struct msm_dma *dma = &msm_port->rx_dma; | ||
377 | int count = 0, i, sysrq; | ||
378 | unsigned long flags; | ||
379 | u32 val; | ||
380 | |||
381 | spin_lock_irqsave(&port->lock, flags); | ||
382 | |||
383 | /* Already stopped */ | ||
384 | if (!dma->count) | ||
385 | goto done; | ||
386 | |||
387 | val = msm_read(port, UARTDM_DMEN); | ||
388 | val &= ~dma->enable_bit; | ||
389 | msm_write(port, val, UARTDM_DMEN); | ||
390 | |||
391 | /* Restore interrupts */ | ||
392 | msm_port->imr |= UART_IMR_RXLEV | UART_IMR_RXSTALE; | ||
393 | msm_write(port, msm_port->imr, UART_IMR); | ||
394 | |||
395 | if (msm_read(port, UART_SR) & UART_SR_OVERRUN) { | ||
396 | port->icount.overrun++; | ||
397 | tty_insert_flip_char(tport, 0, TTY_OVERRUN); | ||
398 | msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); | ||
399 | } | ||
400 | |||
401 | count = msm_read(port, UARTDM_RX_TOTAL_SNAP); | ||
402 | |||
403 | port->icount.rx += count; | ||
404 | |||
405 | dma->count = 0; | ||
406 | |||
407 | dma_unmap_single(port->dev, dma->phys, UARTDM_RX_SIZE, dma->dir); | ||
408 | |||
409 | for (i = 0; i < count; i++) { | ||
410 | char flag = TTY_NORMAL; | ||
411 | |||
412 | if (msm_port->break_detected && dma->virt[i] == 0) { | ||
413 | port->icount.brk++; | ||
414 | flag = TTY_BREAK; | ||
415 | msm_port->break_detected = false; | ||
416 | if (uart_handle_break(port)) | ||
417 | continue; | ||
418 | } | ||
419 | |||
420 | if (!(port->read_status_mask & UART_SR_RX_BREAK)) | ||
421 | flag = TTY_NORMAL; | ||
422 | |||
423 | spin_unlock_irqrestore(&port->lock, flags); | ||
424 | sysrq = uart_handle_sysrq_char(port, dma->virt[i]); | ||
425 | spin_lock_irqsave(&port->lock, flags); | ||
426 | if (!sysrq) | ||
427 | tty_insert_flip_char(tport, dma->virt[i], flag); | ||
428 | } | ||
429 | |||
430 | msm_start_rx_dma(msm_port); | ||
431 | done: | ||
432 | spin_unlock_irqrestore(&port->lock, flags); | ||
433 | |||
434 | if (count) | ||
435 | tty_flip_buffer_push(tport); | ||
436 | } | ||
437 | |||
438 | static void msm_start_rx_dma(struct msm_port *msm_port) | ||
439 | { | ||
440 | struct msm_dma *dma = &msm_port->rx_dma; | ||
441 | struct uart_port *uart = &msm_port->uart; | ||
442 | u32 val; | ||
443 | int ret; | ||
444 | |||
445 | if (!dma->chan) | ||
446 | return; | ||
447 | |||
448 | dma->phys = dma_map_single(uart->dev, dma->virt, | ||
449 | UARTDM_RX_SIZE, dma->dir); | ||
450 | ret = dma_mapping_error(uart->dev, dma->phys); | ||
451 | if (ret) | ||
452 | return; | ||
453 | |||
454 | dma->desc = dmaengine_prep_slave_single(dma->chan, dma->phys, | ||
455 | UARTDM_RX_SIZE, DMA_DEV_TO_MEM, | ||
456 | DMA_PREP_INTERRUPT); | ||
457 | if (!dma->desc) | ||
458 | goto unmap; | ||
459 | |||
460 | dma->desc->callback = msm_complete_rx_dma; | ||
461 | dma->desc->callback_param = msm_port; | ||
462 | |||
463 | dma->cookie = dmaengine_submit(dma->desc); | ||
464 | ret = dma_submit_error(dma->cookie); | ||
465 | if (ret) | ||
466 | goto unmap; | ||
467 | /* | ||
468 | * Using DMA for FIFO off-load, no need for "Rx FIFO over | ||
469 | * watermark" or "stale" interrupts, disable them | ||
470 | */ | ||
471 | msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE); | ||
472 | |||
473 | /* | ||
474 | * Well, when DMA is ADM3 engine(implied by <= UARTDM v1.3), | ||
475 | * we need RXSTALE to flush input DMA fifo to memory | ||
476 | */ | ||
477 | if (msm_port->is_uartdm < UARTDM_1P4) | ||
478 | msm_port->imr |= UART_IMR_RXSTALE; | ||
479 | |||
480 | msm_write(uart, msm_port->imr, UART_IMR); | ||
481 | |||
482 | dma->count = UARTDM_RX_SIZE; | ||
483 | |||
484 | dma_async_issue_pending(dma->chan); | ||
485 | |||
486 | msm_write(uart, UART_CR_CMD_RESET_STALE_INT, UART_CR); | ||
487 | msm_write(uart, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); | ||
488 | |||
489 | val = msm_read(uart, UARTDM_DMEN); | ||
490 | val |= dma->enable_bit; | ||
491 | |||
492 | if (msm_port->is_uartdm < UARTDM_1P4) | ||
493 | msm_write(uart, val, UARTDM_DMEN); | ||
494 | |||
495 | msm_write(uart, UARTDM_RX_SIZE, UARTDM_DMRX); | ||
496 | |||
497 | if (msm_port->is_uartdm > UARTDM_1P3) | ||
498 | msm_write(uart, val, UARTDM_DMEN); | ||
499 | |||
500 | return; | ||
501 | unmap: | ||
502 | dma_unmap_single(uart->dev, dma->phys, UARTDM_RX_SIZE, dma->dir); | ||
503 | } | ||
504 | |||
309 | static void msm_stop_rx(struct uart_port *port) | 505 | static void msm_stop_rx(struct uart_port *port) |
310 | { | 506 | { |
311 | struct msm_port *msm_port = UART_TO_MSM(port); | 507 | struct msm_port *msm_port = UART_TO_MSM(port); |
508 | struct msm_dma *dma = &msm_port->rx_dma; | ||
312 | 509 | ||
313 | msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE); | 510 | msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE); |
314 | msm_write(port, msm_port->imr, UART_IMR); | 511 | msm_write(port, msm_port->imr, UART_IMR); |
512 | |||
513 | if (dma->chan) | ||
514 | msm_stop_dma(port, dma); | ||
315 | } | 515 | } |
316 | 516 | ||
317 | static void msm_enable_ms(struct uart_port *port) | 517 | static void msm_enable_ms(struct uart_port *port) |
@@ -392,6 +592,9 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) | |||
392 | msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); | 592 | msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); |
393 | msm_write(port, 0xFFFFFF, UARTDM_DMRX); | 593 | msm_write(port, 0xFFFFFF, UARTDM_DMRX); |
394 | msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); | 594 | msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); |
595 | |||
596 | /* Try to use DMA */ | ||
597 | msm_start_rx_dma(msm_port); | ||
395 | } | 598 | } |
396 | 599 | ||
397 | static void msm_handle_rx(struct uart_port *port) | 600 | static void msm_handle_rx(struct uart_port *port) |
@@ -558,8 +761,10 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id) | |||
558 | { | 761 | { |
559 | struct uart_port *port = dev_id; | 762 | struct uart_port *port = dev_id; |
560 | struct msm_port *msm_port = UART_TO_MSM(port); | 763 | struct msm_port *msm_port = UART_TO_MSM(port); |
764 | struct msm_dma *dma = &msm_port->rx_dma; | ||
561 | unsigned long flags; | 765 | unsigned long flags; |
562 | unsigned int misr; | 766 | unsigned int misr; |
767 | u32 val; | ||
563 | 768 | ||
564 | spin_lock_irqsave(&port->lock, flags); | 769 | spin_lock_irqsave(&port->lock, flags); |
565 | misr = msm_read(port, UART_MISR); | 770 | misr = msm_read(port, UART_MISR); |
@@ -571,10 +776,21 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id) | |||
571 | } | 776 | } |
572 | 777 | ||
573 | if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE)) { | 778 | if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE)) { |
574 | if (msm_port->is_uartdm) | 779 | if (dma->count) { |
780 | val = UART_CR_CMD_STALE_EVENT_DISABLE; | ||
781 | msm_write(port, val, UART_CR); | ||
782 | val = UART_CR_CMD_RESET_STALE_INT; | ||
783 | msm_write(port, val, UART_CR); | ||
784 | /* | ||
785 | * Flush DMA input fifo to memory, this will also | ||
786 | * trigger DMA RX completion | ||
787 | */ | ||
788 | dmaengine_terminate_all(dma->chan); | ||
789 | } else if (msm_port->is_uartdm) { | ||
575 | msm_handle_rx_dm(port, misr); | 790 | msm_handle_rx_dm(port, misr); |
576 | else | 791 | } else { |
577 | msm_handle_rx(port); | 792 | msm_handle_rx(port); |
793 | } | ||
578 | } | 794 | } |
579 | if (misr & UART_IMR_TXLEV) | 795 | if (misr & UART_IMR_TXLEV) |
580 | msm_handle_tx(port); | 796 | msm_handle_tx(port); |
@@ -773,8 +989,10 @@ static int msm_startup(struct uart_port *port) | |||
773 | data |= UART_MR1_AUTO_RFR_LEVEL0 & rfr_level; | 989 | data |= UART_MR1_AUTO_RFR_LEVEL0 & rfr_level; |
774 | msm_write(port, data, UART_MR1); | 990 | msm_write(port, data, UART_MR1); |
775 | 991 | ||
776 | if (msm_port->is_uartdm) | 992 | if (msm_port->is_uartdm) { |
777 | msm_request_tx_dma(msm_port, msm_port->uart.mapbase); | 993 | msm_request_tx_dma(msm_port, msm_port->uart.mapbase); |
994 | msm_request_rx_dma(msm_port, msm_port->uart.mapbase); | ||
995 | } | ||
778 | 996 | ||
779 | return 0; | 997 | return 0; |
780 | } | 998 | } |
@@ -797,11 +1015,16 @@ static void msm_shutdown(struct uart_port *port) | |||
797 | static void msm_set_termios(struct uart_port *port, struct ktermios *termios, | 1015 | static void msm_set_termios(struct uart_port *port, struct ktermios *termios, |
798 | struct ktermios *old) | 1016 | struct ktermios *old) |
799 | { | 1017 | { |
1018 | struct msm_port *msm_port = UART_TO_MSM(port); | ||
1019 | struct msm_dma *dma = &msm_port->rx_dma; | ||
800 | unsigned long flags; | 1020 | unsigned long flags; |
801 | unsigned int baud, mr; | 1021 | unsigned int baud, mr; |
802 | 1022 | ||
803 | spin_lock_irqsave(&port->lock, flags); | 1023 | spin_lock_irqsave(&port->lock, flags); |
804 | 1024 | ||
1025 | if (dma->chan) /* Terminate if any */ | ||
1026 | msm_stop_dma(port, dma); | ||
1027 | |||
805 | /* calculate and set baud rate */ | 1028 | /* calculate and set baud rate */ |
806 | baud = uart_get_baud_rate(port, termios, old, 300, 115200); | 1029 | baud = uart_get_baud_rate(port, termios, old, 300, 115200); |
807 | baud = msm_set_baud_rate(port, baud); | 1030 | baud = msm_set_baud_rate(port, baud); |
@@ -866,6 +1089,9 @@ static void msm_set_termios(struct uart_port *port, struct ktermios *termios, | |||
866 | 1089 | ||
867 | uart_update_timeout(port, termios->c_cflag, baud); | 1090 | uart_update_timeout(port, termios->c_cflag, baud); |
868 | 1091 | ||
1092 | /* Try to use DMA */ | ||
1093 | msm_start_rx_dma(msm_port); | ||
1094 | |||
869 | spin_unlock_irqrestore(&port->lock, flags); | 1095 | spin_unlock_irqrestore(&port->lock, flags); |
870 | } | 1096 | } |
871 | 1097 | ||
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h index 103ae61b9d06..178645826f16 100644 --- a/drivers/tty/serial/msm_serial.h +++ b/drivers/tty/serial/msm_serial.h | |||
@@ -59,6 +59,7 @@ | |||
59 | #define UART_CR_CMD_SET_RFR (13 << 4) | 59 | #define UART_CR_CMD_SET_RFR (13 << 4) |
60 | #define UART_CR_CMD_RESET_RFR (14 << 4) | 60 | #define UART_CR_CMD_RESET_RFR (14 << 4) |
61 | #define UART_CR_CMD_PROTECTION_EN (16 << 4) | 61 | #define UART_CR_CMD_PROTECTION_EN (16 << 4) |
62 | #define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8) | ||
62 | #define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) | 63 | #define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) |
63 | #define UART_CR_CMD_FORCE_STALE (4 << 8) | 64 | #define UART_CR_CMD_FORCE_STALE (4 << 8) |
64 | #define UART_CR_CMD_RESET_TX_READY (3 << 8) | 65 | #define UART_CR_CMD_RESET_TX_READY (3 << 8) |
@@ -124,6 +125,9 @@ | |||
124 | #define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */ | 125 | #define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */ |
125 | #define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */ | 126 | #define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */ |
126 | 127 | ||
128 | #define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */ | ||
129 | #define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */ | ||
130 | |||
127 | #define UARTDM_DMRX 0x34 | 131 | #define UARTDM_DMRX 0x34 |
128 | #define UARTDM_NCF_TX 0x40 | 132 | #define UARTDM_NCF_TX 0x40 |
129 | #define UARTDM_RX_TOTAL_SNAP 0x38 | 133 | #define UARTDM_RX_TOTAL_SNAP 0x38 |