diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 10:45:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 10:45:16 -0500 |
commit | d07e43d70eef15a44a2c328a913d8d633a90e088 (patch) | |
tree | 7a7cac7c90f4b8f19edfb2aecfa27d77e266eafc | |
parent | 1ebaf4f4e6912199f8a4e30ba3ab55da2b71bcdf (diff) | |
parent | 3af08bd7adb09b0806c51c06b87db08cc7075568 (diff) |
Merge branch 'omap-serial' of git://git.linaro.org/people/rmk/linux-arm
Pull ARM OMAP serial updates from Russell King:
"This series is a major reworking of the OMAP serial driver code fixing
various bugs in the hardware-assisted flow control, extending up into
serial_core for a couple of issues. These fixes have been done as a
set of progressive changes and transformations in the hope that no new
bugs will be introduced by this series.
The problems are many-fold, from the driver not being informed about
updated settings, to the driver not knowing what the intentions of the
upper layers are.
The first four patches tackle the serial_core layer, allowing it to
provide the necessary information to drivers, and the remaining
patches allow the OMAP serial driver to take advantage of this.
This brings hardware assisted RTS/CTS and XON/OFF flow control into a
useful state.
These patches have been in linux-next for most of the last cycle;
indeed they predate the previous merge window. They've also been
posted to the OMAP people."
* 'omap-serial' of git://git.linaro.org/people/rmk/linux-arm: (21 commits)
SERIAL: omap: fix hardware assisted flow control
SERIAL: omap: simplify (2)
SERIAL: omap: move xon/xoff setting earlier
SERIAL: omap: always set TCR
SERIAL: omap: simplify
SERIAL: omap: don't read back LCR/MCR/EFR
SERIAL: omap: serial_omap_configure_xonxoff() contents into set_termios
SERIAL: omap: configure xon/xoff before setting modem control lines
SERIAL: omap: remove OMAP_UART_SYSC_RESET and OMAP_UART_FIFO_CLR
SERIAL: omap: move driver private definitions and structures to driver
SERIAL: omap: remove 'irq_pending' bitfield
SERIAL: omap: fix MCR TCRTLR bit handling
SERIAL: omap: fix set_mctrl() breakage
SERIAL: omap: no need to re-read EFR
SERIAL: omap: remove setting of EFR SCD bit
SERIAL: omap: allow hardware assisted IXANY mode to be disabled
SERIAL: omap: allow hardware assisted rts/cts modes to be disabled
SERIAL: core: add throttle/unthrottle callbacks for hardware assisted flow control
SERIAL: core: add hardware assisted h/w flow control support
SERIAL: core: add hardware assisted s/w flow control support
...
Conflicts:
drivers/tty/serial/omap-serial.c
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap-serial.h | 55 | ||||
-rw-r--r-- | drivers/tty/serial/omap-serial.c | 231 | ||||
-rw-r--r-- | drivers/tty/serial/serial_core.c | 71 | ||||
-rw-r--r-- | include/linux/serial_core.h | 6 |
4 files changed, 213 insertions, 150 deletions
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 1957a8516e9..ff9b0aab528 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h | |||
@@ -30,35 +30,6 @@ | |||
30 | */ | 30 | */ |
31 | #define OMAP_SERIAL_NAME "ttyO" | 31 | #define OMAP_SERIAL_NAME "ttyO" |
32 | 32 | ||
33 | #define OMAP_MODE13X_SPEED 230400 | ||
34 | |||
35 | #define OMAP_UART_SCR_TX_EMPTY 0x08 | ||
36 | |||
37 | /* WER = 0x7F | ||
38 | * Enable module level wakeup in WER reg | ||
39 | */ | ||
40 | #define OMAP_UART_WER_MOD_WKUP 0X7F | ||
41 | |||
42 | /* Enable XON/XOFF flow control on output */ | ||
43 | #define OMAP_UART_SW_TX 0x04 | ||
44 | |||
45 | /* Enable XON/XOFF flow control on input */ | ||
46 | #define OMAP_UART_SW_RX 0x04 | ||
47 | |||
48 | #define OMAP_UART_SYSC_RESET 0X07 | ||
49 | #define OMAP_UART_TCR_TRIG 0X0F | ||
50 | #define OMAP_UART_SW_CLR 0XF0 | ||
51 | #define OMAP_UART_FIFO_CLR 0X06 | ||
52 | |||
53 | #define OMAP_UART_DMA_CH_FREE -1 | ||
54 | |||
55 | #define OMAP_MAX_HSUART_PORTS 6 | ||
56 | |||
57 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA | ||
58 | |||
59 | #define UART_ERRATA_i202_MDR1_ACCESS BIT(0) | ||
60 | #define UART_ERRATA_i291_DMA_FORCEIDLE BIT(1) | ||
61 | |||
62 | struct omap_uart_port_info { | 33 | struct omap_uart_port_info { |
63 | bool dma_enabled; /* To specify DMA Mode */ | 34 | bool dma_enabled; /* To specify DMA Mode */ |
64 | unsigned int uartclk; /* UART clock rate */ | 35 | unsigned int uartclk; /* UART clock rate */ |
@@ -77,30 +48,4 @@ struct omap_uart_port_info { | |||
77 | void (*enable_wakeup)(struct device *, bool); | 48 | void (*enable_wakeup)(struct device *, bool); |
78 | }; | 49 | }; |
79 | 50 | ||
80 | struct uart_omap_dma { | ||
81 | u8 uart_dma_tx; | ||
82 | u8 uart_dma_rx; | ||
83 | int rx_dma_channel; | ||
84 | int tx_dma_channel; | ||
85 | dma_addr_t rx_buf_dma_phys; | ||
86 | dma_addr_t tx_buf_dma_phys; | ||
87 | unsigned int uart_base; | ||
88 | /* | ||
89 | * Buffer for rx dma.It is not required for tx because the buffer | ||
90 | * comes from port structure. | ||
91 | */ | ||
92 | unsigned char *rx_buf; | ||
93 | unsigned int prev_rx_dma_pos; | ||
94 | int tx_buf_size; | ||
95 | int tx_dma_used; | ||
96 | int rx_dma_used; | ||
97 | spinlock_t tx_lock; | ||
98 | spinlock_t rx_lock; | ||
99 | /* timer to poll activity on rx dma */ | ||
100 | struct timer_list rx_timer; | ||
101 | unsigned int rx_buf_size; | ||
102 | unsigned int rx_poll_rate; | ||
103 | unsigned int rx_timeout; | ||
104 | }; | ||
105 | |||
106 | #endif /* __OMAP_SERIAL_H__ */ | 51 | #endif /* __OMAP_SERIAL_H__ */ |
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index b538e2e4ae5..23f797eb7a2 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c | |||
@@ -44,6 +44,8 @@ | |||
44 | 44 | ||
45 | #include <plat/omap-serial.h> | 45 | #include <plat/omap-serial.h> |
46 | 46 | ||
47 | #define OMAP_MAX_HSUART_PORTS 6 | ||
48 | |||
47 | #define UART_BUILD_REVISION(x, y) (((x) << 8) | (y)) | 49 | #define UART_BUILD_REVISION(x, y) (((x) << 8) | (y)) |
48 | 50 | ||
49 | #define OMAP_UART_REV_42 0x0402 | 51 | #define OMAP_UART_REV_42 0x0402 |
@@ -51,10 +53,14 @@ | |||
51 | #define OMAP_UART_REV_52 0x0502 | 53 | #define OMAP_UART_REV_52 0x0502 |
52 | #define OMAP_UART_REV_63 0x0603 | 54 | #define OMAP_UART_REV_63 0x0603 |
53 | 55 | ||
56 | #define UART_ERRATA_i202_MDR1_ACCESS BIT(0) | ||
57 | #define UART_ERRATA_i291_DMA_FORCEIDLE BIT(1) | ||
58 | |||
54 | #define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/ | 59 | #define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/ |
55 | 60 | ||
56 | /* SCR register bitmasks */ | 61 | /* SCR register bitmasks */ |
57 | #define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7) | 62 | #define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7) |
63 | #define OMAP_UART_SCR_TX_EMPTY (1 << 3) | ||
58 | 64 | ||
59 | /* FCR register bitmasks */ | 65 | /* FCR register bitmasks */ |
60 | #define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6) | 66 | #define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6) |
@@ -71,6 +77,52 @@ | |||
71 | #define OMAP_UART_MVR_MAJ_SHIFT 8 | 77 | #define OMAP_UART_MVR_MAJ_SHIFT 8 |
72 | #define OMAP_UART_MVR_MIN_MASK 0x3f | 78 | #define OMAP_UART_MVR_MIN_MASK 0x3f |
73 | 79 | ||
80 | #define OMAP_UART_DMA_CH_FREE -1 | ||
81 | |||
82 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA | ||
83 | #define OMAP_MODE13X_SPEED 230400 | ||
84 | |||
85 | /* WER = 0x7F | ||
86 | * Enable module level wakeup in WER reg | ||
87 | */ | ||
88 | #define OMAP_UART_WER_MOD_WKUP 0X7F | ||
89 | |||
90 | /* Enable XON/XOFF flow control on output */ | ||
91 | #define OMAP_UART_SW_TX 0x08 | ||
92 | |||
93 | /* Enable XON/XOFF flow control on input */ | ||
94 | #define OMAP_UART_SW_RX 0x02 | ||
95 | |||
96 | #define OMAP_UART_SW_CLR 0xF0 | ||
97 | |||
98 | #define OMAP_UART_TCR_TRIG 0x0F | ||
99 | |||
100 | struct uart_omap_dma { | ||
101 | u8 uart_dma_tx; | ||
102 | u8 uart_dma_rx; | ||
103 | int rx_dma_channel; | ||
104 | int tx_dma_channel; | ||
105 | dma_addr_t rx_buf_dma_phys; | ||
106 | dma_addr_t tx_buf_dma_phys; | ||
107 | unsigned int uart_base; | ||
108 | /* | ||
109 | * Buffer for rx dma.It is not required for tx because the buffer | ||
110 | * comes from port structure. | ||
111 | */ | ||
112 | unsigned char *rx_buf; | ||
113 | unsigned int prev_rx_dma_pos; | ||
114 | int tx_buf_size; | ||
115 | int tx_dma_used; | ||
116 | int rx_dma_used; | ||
117 | spinlock_t tx_lock; | ||
118 | spinlock_t rx_lock; | ||
119 | /* timer to poll activity on rx dma */ | ||
120 | struct timer_list rx_timer; | ||
121 | unsigned int rx_buf_size; | ||
122 | unsigned int rx_poll_rate; | ||
123 | unsigned int rx_timeout; | ||
124 | }; | ||
125 | |||
74 | struct uart_omap_port { | 126 | struct uart_omap_port { |
75 | struct uart_port port; | 127 | struct uart_port port; |
76 | struct uart_omap_dma uart_dma; | 128 | struct uart_omap_dma uart_dma; |
@@ -99,7 +151,6 @@ struct uart_omap_port { | |||
99 | int context_loss_cnt; | 151 | int context_loss_cnt; |
100 | u32 errata; | 152 | u32 errata; |
101 | u8 wakeups_enabled; | 153 | u8 wakeups_enabled; |
102 | unsigned int irq_pending:1; | ||
103 | 154 | ||
104 | int DTR_gpio; | 155 | int DTR_gpio; |
105 | int DTR_inverted; | 156 | int DTR_inverted; |
@@ -303,6 +354,34 @@ static void serial_omap_start_tx(struct uart_port *port) | |||
303 | pm_runtime_put_autosuspend(up->dev); | 354 | pm_runtime_put_autosuspend(up->dev); |
304 | } | 355 | } |
305 | 356 | ||
357 | static void serial_omap_throttle(struct uart_port *port) | ||
358 | { | ||
359 | struct uart_omap_port *up = to_uart_omap_port(port); | ||
360 | unsigned long flags; | ||
361 | |||
362 | pm_runtime_get_sync(up->dev); | ||
363 | spin_lock_irqsave(&up->port.lock, flags); | ||
364 | up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); | ||
365 | serial_out(up, UART_IER, up->ier); | ||
366 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
367 | pm_runtime_mark_last_busy(up->dev); | ||
368 | pm_runtime_put_autosuspend(up->dev); | ||
369 | } | ||
370 | |||
371 | static void serial_omap_unthrottle(struct uart_port *port) | ||
372 | { | ||
373 | struct uart_omap_port *up = to_uart_omap_port(port); | ||
374 | unsigned long flags; | ||
375 | |||
376 | pm_runtime_get_sync(up->dev); | ||
377 | spin_lock_irqsave(&up->port.lock, flags); | ||
378 | up->ier |= UART_IER_RLSI | UART_IER_RDI; | ||
379 | serial_out(up, UART_IER, up->ier); | ||
380 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
381 | pm_runtime_mark_last_busy(up->dev); | ||
382 | pm_runtime_put_autosuspend(up->dev); | ||
383 | } | ||
384 | |||
306 | static unsigned int check_modem_status(struct uart_omap_port *up) | 385 | static unsigned int check_modem_status(struct uart_omap_port *up) |
307 | { | 386 | { |
308 | unsigned int status; | 387 | unsigned int status; |
@@ -504,7 +583,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port) | |||
504 | static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) | 583 | static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) |
505 | { | 584 | { |
506 | struct uart_omap_port *up = to_uart_omap_port(port); | 585 | struct uart_omap_port *up = to_uart_omap_port(port); |
507 | unsigned char mcr = 0; | 586 | unsigned char mcr = 0, old_mcr; |
508 | 587 | ||
509 | dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line); | 588 | dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line); |
510 | if (mctrl & TIOCM_RTS) | 589 | if (mctrl & TIOCM_RTS) |
@@ -519,8 +598,10 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
519 | mcr |= UART_MCR_LOOP; | 598 | mcr |= UART_MCR_LOOP; |
520 | 599 | ||
521 | pm_runtime_get_sync(up->dev); | 600 | pm_runtime_get_sync(up->dev); |
522 | up->mcr = serial_in(up, UART_MCR); | 601 | old_mcr = serial_in(up, UART_MCR); |
523 | up->mcr |= mcr; | 602 | old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 | |
603 | UART_MCR_DTR | UART_MCR_RTS); | ||
604 | up->mcr = old_mcr | mcr; | ||
524 | serial_out(up, UART_MCR, up->mcr); | 605 | serial_out(up, UART_MCR, up->mcr); |
525 | pm_runtime_mark_last_busy(up->dev); | 606 | pm_runtime_mark_last_busy(up->dev); |
526 | pm_runtime_put_autosuspend(up->dev); | 607 | pm_runtime_put_autosuspend(up->dev); |
@@ -654,61 +735,6 @@ static void serial_omap_shutdown(struct uart_port *port) | |||
654 | free_irq(up->port.irq, up); | 735 | free_irq(up->port.irq, up); |
655 | } | 736 | } |
656 | 737 | ||
657 | static inline void | ||
658 | serial_omap_configure_xonxoff | ||
659 | (struct uart_omap_port *up, struct ktermios *termios) | ||
660 | { | ||
661 | up->lcr = serial_in(up, UART_LCR); | ||
662 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | ||
663 | up->efr = serial_in(up, UART_EFR); | ||
664 | serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB); | ||
665 | |||
666 | serial_out(up, UART_XON1, termios->c_cc[VSTART]); | ||
667 | serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]); | ||
668 | |||
669 | /* clear SW control mode bits */ | ||
670 | up->efr &= OMAP_UART_SW_CLR; | ||
671 | |||
672 | /* | ||
673 | * IXON Flag: | ||
674 | * Enable XON/XOFF flow control on output. | ||
675 | * Transmit XON1, XOFF1 | ||
676 | */ | ||
677 | if (termios->c_iflag & IXON) | ||
678 | up->efr |= OMAP_UART_SW_TX; | ||
679 | |||
680 | /* | ||
681 | * IXOFF Flag: | ||
682 | * Enable XON/XOFF flow control on input. | ||
683 | * Receiver compares XON1, XOFF1. | ||
684 | */ | ||
685 | if (termios->c_iflag & IXOFF) | ||
686 | up->efr |= OMAP_UART_SW_RX; | ||
687 | |||
688 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); | ||
689 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | ||
690 | |||
691 | up->mcr = serial_in(up, UART_MCR); | ||
692 | |||
693 | /* | ||
694 | * IXANY Flag: | ||
695 | * Enable any character to restart output. | ||
696 | * Operation resumes after receiving any | ||
697 | * character after recognition of the XOFF character | ||
698 | */ | ||
699 | if (termios->c_iflag & IXANY) | ||
700 | up->mcr |= UART_MCR_XONANY; | ||
701 | |||
702 | serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); | ||
703 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | ||
704 | serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG); | ||
705 | |||
706 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | ||
707 | |||
708 | serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR); | ||
709 | serial_out(up, UART_LCR, up->lcr); | ||
710 | } | ||
711 | |||
712 | static void serial_omap_uart_qos_work(struct work_struct *work) | 738 | static void serial_omap_uart_qos_work(struct work_struct *work) |
713 | { | 739 | { |
714 | struct uart_omap_port *up = container_of(work, struct uart_omap_port, | 740 | struct uart_omap_port *up = container_of(work, struct uart_omap_port, |
@@ -726,7 +752,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
726 | { | 752 | { |
727 | struct uart_omap_port *up = to_uart_omap_port(port); | 753 | struct uart_omap_port *up = to_uart_omap_port(port); |
728 | unsigned char cval = 0; | 754 | unsigned char cval = 0; |
729 | unsigned char efr = 0; | ||
730 | unsigned long flags = 0; | 755 | unsigned long flags = 0; |
731 | unsigned int baud, quot; | 756 | unsigned int baud, quot; |
732 | 757 | ||
@@ -836,11 +861,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
836 | 861 | ||
837 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 862 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
838 | 863 | ||
839 | up->efr = serial_in(up, UART_EFR); | 864 | up->efr = serial_in(up, UART_EFR) & ~UART_EFR_ECB; |
865 | up->efr &= ~UART_EFR_SCD; | ||
840 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); | 866 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); |
841 | 867 | ||
842 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | 868 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); |
843 | up->mcr = serial_in(up, UART_MCR); | 869 | up->mcr = serial_in(up, UART_MCR) & ~UART_MCR_TCRTLR; |
844 | serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); | 870 | serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); |
845 | /* FIFO ENABLE, DMA MODE */ | 871 | /* FIFO ENABLE, DMA MODE */ |
846 | 872 | ||
@@ -859,9 +885,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
859 | 885 | ||
860 | serial_out(up, UART_OMAP_SCR, up->scr); | 886 | serial_out(up, UART_OMAP_SCR, up->scr); |
861 | 887 | ||
862 | serial_out(up, UART_EFR, up->efr); | 888 | /* Reset UART_MCR_TCRTLR: this must be done with the EFR_ECB bit set */ |
863 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | 889 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); |
864 | serial_out(up, UART_MCR, up->mcr); | 890 | serial_out(up, UART_MCR, up->mcr); |
891 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | ||
892 | serial_out(up, UART_EFR, up->efr); | ||
893 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | ||
865 | 894 | ||
866 | /* Protocol, Baud Rate, and Interrupt Settings */ | 895 | /* Protocol, Baud Rate, and Interrupt Settings */ |
867 | 896 | ||
@@ -871,8 +900,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
871 | serial_out(up, UART_OMAP_MDR1, up->mdr1); | 900 | serial_out(up, UART_OMAP_MDR1, up->mdr1); |
872 | 901 | ||
873 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 902 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
874 | |||
875 | up->efr = serial_in(up, UART_EFR); | ||
876 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); | 903 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); |
877 | 904 | ||
878 | serial_out(up, UART_LCR, 0); | 905 | serial_out(up, UART_LCR, 0); |
@@ -899,29 +926,68 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
899 | else | 926 | else |
900 | serial_out(up, UART_OMAP_MDR1, up->mdr1); | 927 | serial_out(up, UART_OMAP_MDR1, up->mdr1); |
901 | 928 | ||
902 | /* Hardware Flow Control Configuration */ | 929 | /* Configure flow control */ |
930 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | ||
931 | |||
932 | /* XON1/XOFF1 accessible mode B, TCRTLR=0, ECB=0 */ | ||
933 | serial_out(up, UART_XON1, termios->c_cc[VSTART]); | ||
934 | serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]); | ||
935 | |||
936 | /* Enable access to TCR/TLR */ | ||
937 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); | ||
938 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | ||
939 | serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); | ||
940 | |||
941 | serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG); | ||
942 | |||
943 | if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { | ||
944 | /* Enable AUTORTS and AUTOCTS */ | ||
945 | up->efr |= UART_EFR_CTS | UART_EFR_RTS; | ||
946 | |||
947 | /* Ensure MCR RTS is asserted */ | ||
948 | up->mcr |= UART_MCR_RTS; | ||
949 | } else { | ||
950 | /* Disable AUTORTS and AUTOCTS */ | ||
951 | up->efr &= ~(UART_EFR_CTS | UART_EFR_RTS); | ||
952 | } | ||
903 | 953 | ||
904 | if (termios->c_cflag & CRTSCTS) { | 954 | if (up->port.flags & UPF_SOFT_FLOW) { |
905 | efr |= (UART_EFR_CTS | UART_EFR_RTS); | 955 | /* clear SW control mode bits */ |
906 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | 956 | up->efr &= OMAP_UART_SW_CLR; |
907 | 957 | ||
908 | up->mcr = serial_in(up, UART_MCR); | 958 | /* |
909 | serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); | 959 | * IXON Flag: |
960 | * Enable XON/XOFF flow control on input. | ||
961 | * Receiver compares XON1, XOFF1. | ||
962 | */ | ||
963 | if (termios->c_iflag & IXON) | ||
964 | up->efr |= OMAP_UART_SW_RX; | ||
910 | 965 | ||
911 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 966 | /* |
912 | up->efr = serial_in(up, UART_EFR); | 967 | * IXOFF Flag: |
913 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); | 968 | * Enable XON/XOFF flow control on output. |
969 | * Transmit XON1, XOFF1 | ||
970 | */ | ||
971 | if (termios->c_iflag & IXOFF) | ||
972 | up->efr |= OMAP_UART_SW_TX; | ||
914 | 973 | ||
915 | serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG); | 974 | /* |
916 | serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */ | 975 | * IXANY Flag: |
917 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | 976 | * Enable any character to restart output. |
918 | serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS); | 977 | * Operation resumes after receiving any |
919 | serial_out(up, UART_LCR, cval); | 978 | * character after recognition of the XOFF character |
979 | */ | ||
980 | if (termios->c_iflag & IXANY) | ||
981 | up->mcr |= UART_MCR_XONANY; | ||
982 | else | ||
983 | up->mcr &= ~UART_MCR_XONANY; | ||
920 | } | 984 | } |
985 | serial_out(up, UART_MCR, up->mcr); | ||
986 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | ||
987 | serial_out(up, UART_EFR, up->efr); | ||
988 | serial_out(up, UART_LCR, up->lcr); | ||
921 | 989 | ||
922 | serial_omap_set_mctrl(&up->port, up->port.mctrl); | 990 | serial_omap_set_mctrl(&up->port, up->port.mctrl); |
923 | /* Software Flow Control Configuration */ | ||
924 | serial_omap_configure_xonxoff(up, termios); | ||
925 | 991 | ||
926 | spin_unlock_irqrestore(&up->port.lock, flags); | 992 | spin_unlock_irqrestore(&up->port.lock, flags); |
927 | pm_runtime_mark_last_busy(up->dev); | 993 | pm_runtime_mark_last_busy(up->dev); |
@@ -987,6 +1053,7 @@ static void serial_omap_config_port(struct uart_port *port, int flags) | |||
987 | dev_dbg(up->port.dev, "serial_omap_config_port+%d\n", | 1053 | dev_dbg(up->port.dev, "serial_omap_config_port+%d\n", |
988 | up->port.line); | 1054 | up->port.line); |
989 | up->port.type = PORT_OMAP; | 1055 | up->port.type = PORT_OMAP; |
1056 | up->port.flags |= UPF_SOFT_FLOW | UPF_HARD_FLOW; | ||
990 | } | 1057 | } |
991 | 1058 | ||
992 | static int | 1059 | static int |
@@ -1190,6 +1257,8 @@ static struct uart_ops serial_omap_pops = { | |||
1190 | .get_mctrl = serial_omap_get_mctrl, | 1257 | .get_mctrl = serial_omap_get_mctrl, |
1191 | .stop_tx = serial_omap_stop_tx, | 1258 | .stop_tx = serial_omap_stop_tx, |
1192 | .start_tx = serial_omap_start_tx, | 1259 | .start_tx = serial_omap_start_tx, |
1260 | .throttle = serial_omap_throttle, | ||
1261 | .unthrottle = serial_omap_unthrottle, | ||
1193 | .stop_rx = serial_omap_stop_rx, | 1262 | .stop_rx = serial_omap_stop_rx, |
1194 | .enable_ms = serial_omap_enable_ms, | 1263 | .enable_ms = serial_omap_enable_ms, |
1195 | .break_ctl = serial_omap_break_ctl, | 1264 | .break_ctl = serial_omap_break_ctl, |
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index fb5aa42fde7..2c7230aaefd 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -610,27 +610,50 @@ static void uart_send_xchar(struct tty_struct *tty, char ch) | |||
610 | static void uart_throttle(struct tty_struct *tty) | 610 | static void uart_throttle(struct tty_struct *tty) |
611 | { | 611 | { |
612 | struct uart_state *state = tty->driver_data; | 612 | struct uart_state *state = tty->driver_data; |
613 | struct uart_port *port = state->uart_port; | ||
614 | uint32_t mask = 0; | ||
613 | 615 | ||
614 | if (I_IXOFF(tty)) | 616 | if (I_IXOFF(tty)) |
617 | mask |= UPF_SOFT_FLOW; | ||
618 | if (tty->termios.c_cflag & CRTSCTS) | ||
619 | mask |= UPF_HARD_FLOW; | ||
620 | |||
621 | if (port->flags & mask) { | ||
622 | port->ops->throttle(port); | ||
623 | mask &= ~port->flags; | ||
624 | } | ||
625 | |||
626 | if (mask & UPF_SOFT_FLOW) | ||
615 | uart_send_xchar(tty, STOP_CHAR(tty)); | 627 | uart_send_xchar(tty, STOP_CHAR(tty)); |
616 | 628 | ||
617 | if (tty->termios.c_cflag & CRTSCTS) | 629 | if (mask & UPF_HARD_FLOW) |
618 | uart_clear_mctrl(state->uart_port, TIOCM_RTS); | 630 | uart_clear_mctrl(port, TIOCM_RTS); |
619 | } | 631 | } |
620 | 632 | ||
621 | static void uart_unthrottle(struct tty_struct *tty) | 633 | static void uart_unthrottle(struct tty_struct *tty) |
622 | { | 634 | { |
623 | struct uart_state *state = tty->driver_data; | 635 | struct uart_state *state = tty->driver_data; |
624 | struct uart_port *port = state->uart_port; | 636 | struct uart_port *port = state->uart_port; |
637 | uint32_t mask = 0; | ||
625 | 638 | ||
626 | if (I_IXOFF(tty)) { | 639 | if (I_IXOFF(tty)) |
640 | mask |= UPF_SOFT_FLOW; | ||
641 | if (tty->termios.c_cflag & CRTSCTS) | ||
642 | mask |= UPF_HARD_FLOW; | ||
643 | |||
644 | if (port->flags & mask) { | ||
645 | port->ops->unthrottle(port); | ||
646 | mask &= ~port->flags; | ||
647 | } | ||
648 | |||
649 | if (mask & UPF_SOFT_FLOW) { | ||
627 | if (port->x_char) | 650 | if (port->x_char) |
628 | port->x_char = 0; | 651 | port->x_char = 0; |
629 | else | 652 | else |
630 | uart_send_xchar(tty, START_CHAR(tty)); | 653 | uart_send_xchar(tty, START_CHAR(tty)); |
631 | } | 654 | } |
632 | 655 | ||
633 | if (tty->termios.c_cflag & CRTSCTS) | 656 | if (mask & UPF_HARD_FLOW) |
634 | uart_set_mctrl(port, TIOCM_RTS); | 657 | uart_set_mctrl(port, TIOCM_RTS); |
635 | } | 658 | } |
636 | 659 | ||
@@ -1214,9 +1237,22 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1214 | struct ktermios *old_termios) | 1237 | struct ktermios *old_termios) |
1215 | { | 1238 | { |
1216 | struct uart_state *state = tty->driver_data; | 1239 | struct uart_state *state = tty->driver_data; |
1240 | struct uart_port *uport = state->uart_port; | ||
1217 | unsigned long flags; | 1241 | unsigned long flags; |
1218 | unsigned int cflag = tty->termios.c_cflag; | 1242 | unsigned int cflag = tty->termios.c_cflag; |
1243 | unsigned int iflag_mask = IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK; | ||
1244 | bool sw_changed = false; | ||
1219 | 1245 | ||
1246 | /* | ||
1247 | * Drivers doing software flow control also need to know | ||
1248 | * about changes to these input settings. | ||
1249 | */ | ||
1250 | if (uport->flags & UPF_SOFT_FLOW) { | ||
1251 | iflag_mask |= IXANY|IXON|IXOFF; | ||
1252 | sw_changed = | ||
1253 | tty->termios.c_cc[VSTART] != old_termios->c_cc[VSTART] || | ||
1254 | tty->termios.c_cc[VSTOP] != old_termios->c_cc[VSTOP]; | ||
1255 | } | ||
1220 | 1256 | ||
1221 | /* | 1257 | /* |
1222 | * These are the bits that are used to setup various | 1258 | * These are the bits that are used to setup various |
@@ -1224,11 +1260,11 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1224 | * bits in c_cflag; c_[io]speed will always be set | 1260 | * bits in c_cflag; c_[io]speed will always be set |
1225 | * appropriately by set_termios() in tty_ioctl.c | 1261 | * appropriately by set_termios() in tty_ioctl.c |
1226 | */ | 1262 | */ |
1227 | #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
1228 | if ((cflag ^ old_termios->c_cflag) == 0 && | 1263 | if ((cflag ^ old_termios->c_cflag) == 0 && |
1229 | tty->termios.c_ospeed == old_termios->c_ospeed && | 1264 | tty->termios.c_ospeed == old_termios->c_ospeed && |
1230 | tty->termios.c_ispeed == old_termios->c_ispeed && | 1265 | tty->termios.c_ispeed == old_termios->c_ispeed && |
1231 | RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0) { | 1266 | ((tty->termios.c_iflag ^ old_termios->c_iflag) & iflag_mask) == 0 && |
1267 | !sw_changed) { | ||
1232 | return; | 1268 | return; |
1233 | } | 1269 | } |
1234 | 1270 | ||
@@ -1236,31 +1272,38 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1236 | 1272 | ||
1237 | /* Handle transition to B0 status */ | 1273 | /* Handle transition to B0 status */ |
1238 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) | 1274 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) |
1239 | uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR); | 1275 | uart_clear_mctrl(uport, TIOCM_RTS | TIOCM_DTR); |
1240 | /* Handle transition away from B0 status */ | 1276 | /* Handle transition away from B0 status */ |
1241 | else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { | 1277 | else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { |
1242 | unsigned int mask = TIOCM_DTR; | 1278 | unsigned int mask = TIOCM_DTR; |
1243 | if (!(cflag & CRTSCTS) || | 1279 | if (!(cflag & CRTSCTS) || |
1244 | !test_bit(TTY_THROTTLED, &tty->flags)) | 1280 | !test_bit(TTY_THROTTLED, &tty->flags)) |
1245 | mask |= TIOCM_RTS; | 1281 | mask |= TIOCM_RTS; |
1246 | uart_set_mctrl(state->uart_port, mask); | 1282 | uart_set_mctrl(uport, mask); |
1247 | } | 1283 | } |
1248 | 1284 | ||
1285 | /* | ||
1286 | * If the port is doing h/w assisted flow control, do nothing. | ||
1287 | * We assume that tty->hw_stopped has never been set. | ||
1288 | */ | ||
1289 | if (uport->flags & UPF_HARD_FLOW) | ||
1290 | return; | ||
1291 | |||
1249 | /* Handle turning off CRTSCTS */ | 1292 | /* Handle turning off CRTSCTS */ |
1250 | if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) { | 1293 | if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) { |
1251 | spin_lock_irqsave(&state->uart_port->lock, flags); | 1294 | spin_lock_irqsave(&uport->lock, flags); |
1252 | tty->hw_stopped = 0; | 1295 | tty->hw_stopped = 0; |
1253 | __uart_start(tty); | 1296 | __uart_start(tty); |
1254 | spin_unlock_irqrestore(&state->uart_port->lock, flags); | 1297 | spin_unlock_irqrestore(&uport->lock, flags); |
1255 | } | 1298 | } |
1256 | /* Handle turning on CRTSCTS */ | 1299 | /* Handle turning on CRTSCTS */ |
1257 | else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { | 1300 | else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { |
1258 | spin_lock_irqsave(&state->uart_port->lock, flags); | 1301 | spin_lock_irqsave(&uport->lock, flags); |
1259 | if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) { | 1302 | if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) { |
1260 | tty->hw_stopped = 1; | 1303 | tty->hw_stopped = 1; |
1261 | state->uart_port->ops->stop_tx(state->uart_port); | 1304 | uport->ops->stop_tx(uport); |
1262 | } | 1305 | } |
1263 | spin_unlock_irqrestore(&state->uart_port->lock, flags); | 1306 | spin_unlock_irqrestore(&uport->lock, flags); |
1264 | } | 1307 | } |
1265 | } | 1308 | } |
1266 | 1309 | ||
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 3c430228d23..c6690a2a27f 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -46,6 +46,8 @@ struct uart_ops { | |||
46 | unsigned int (*get_mctrl)(struct uart_port *); | 46 | unsigned int (*get_mctrl)(struct uart_port *); |
47 | void (*stop_tx)(struct uart_port *); | 47 | void (*stop_tx)(struct uart_port *); |
48 | void (*start_tx)(struct uart_port *); | 48 | void (*start_tx)(struct uart_port *); |
49 | void (*throttle)(struct uart_port *); | ||
50 | void (*unthrottle)(struct uart_port *); | ||
49 | void (*send_xchar)(struct uart_port *, char ch); | 51 | void (*send_xchar)(struct uart_port *, char ch); |
50 | void (*stop_rx)(struct uart_port *); | 52 | void (*stop_rx)(struct uart_port *); |
51 | void (*enable_ms)(struct uart_port *); | 53 | void (*enable_ms)(struct uart_port *); |
@@ -163,6 +165,10 @@ struct uart_port { | |||
163 | #define UPF_BUGGY_UART ((__force upf_t) (1 << 14)) | 165 | #define UPF_BUGGY_UART ((__force upf_t) (1 << 14)) |
164 | #define UPF_NO_TXEN_TEST ((__force upf_t) (1 << 15)) | 166 | #define UPF_NO_TXEN_TEST ((__force upf_t) (1 << 15)) |
165 | #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16)) | 167 | #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16)) |
168 | /* Port has hardware-assisted h/w flow control (iow, auto-RTS *not* auto-CTS) */ | ||
169 | #define UPF_HARD_FLOW ((__force upf_t) (1 << 21)) | ||
170 | /* Port has hardware-assisted s/w flow control */ | ||
171 | #define UPF_SOFT_FLOW ((__force upf_t) (1 << 22)) | ||
166 | #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) | 172 | #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) |
167 | #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) | 173 | #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) |
168 | #define UPF_EXAR_EFR ((__force upf_t) (1 << 25)) | 174 | #define UPF_EXAR_EFR ((__force upf_t) (1 << 25)) |