aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/amba-pl011.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/amba-pl011.c')
-rw-r--r--drivers/tty/serial/amba-pl011.c157
1 files changed, 66 insertions, 91 deletions
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index cb45136f6867..faa16ee6b022 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -144,6 +144,62 @@ struct uart_amba_port {
144}; 144};
145 145
146/* 146/*
147 * Reads up to 256 characters from the FIFO or until it's empty and
148 * inserts them into the TTY layer. Returns the number of characters
149 * read from the FIFO.
150 */
151static int pl011_fifo_to_tty(struct uart_amba_port *uap)
152{
153 u16 status, ch;
154 unsigned int flag, max_count = 256;
155 int fifotaken = 0;
156
157 while (max_count--) {
158 status = readw(uap->port.membase + UART01x_FR);
159 if (status & UART01x_FR_RXFE)
160 break;
161
162 /* Take chars from the FIFO and update status */
163 ch = readw(uap->port.membase + UART01x_DR) |
164 UART_DUMMY_DR_RX;
165 flag = TTY_NORMAL;
166 uap->port.icount.rx++;
167 fifotaken++;
168
169 if (unlikely(ch & UART_DR_ERROR)) {
170 if (ch & UART011_DR_BE) {
171 ch &= ~(UART011_DR_FE | UART011_DR_PE);
172 uap->port.icount.brk++;
173 if (uart_handle_break(&uap->port))
174 continue;
175 } else if (ch & UART011_DR_PE)
176 uap->port.icount.parity++;
177 else if (ch & UART011_DR_FE)
178 uap->port.icount.frame++;
179 if (ch & UART011_DR_OE)
180 uap->port.icount.overrun++;
181
182 ch &= uap->port.read_status_mask;
183
184 if (ch & UART011_DR_BE)
185 flag = TTY_BREAK;
186 else if (ch & UART011_DR_PE)
187 flag = TTY_PARITY;
188 else if (ch & UART011_DR_FE)
189 flag = TTY_FRAME;
190 }
191
192 if (uart_handle_sysrq_char(&uap->port, ch & 255))
193 continue;
194
195 uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
196 }
197
198 return fifotaken;
199}
200
201
202/*
147 * All the DMA operation mode stuff goes inside this ifdef. 203 * All the DMA operation mode stuff goes inside this ifdef.
148 * This assumes that you have a generic DMA device interface, 204 * This assumes that you have a generic DMA device interface,
149 * no custom DMA interfaces are supported. 205 * no custom DMA interfaces are supported.
@@ -634,7 +690,6 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
634 struct pl011_sgbuf *sgbuf = use_buf_b ? 690 struct pl011_sgbuf *sgbuf = use_buf_b ?
635 &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a; 691 &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
636 struct device *dev = uap->dmarx.chan->device->dev; 692 struct device *dev = uap->dmarx.chan->device->dev;
637 unsigned int status, ch, flag;
638 int dma_count = 0; 693 int dma_count = 0;
639 u32 fifotaken = 0; /* only used for vdbg() */ 694 u32 fifotaken = 0; /* only used for vdbg() */
640 695
@@ -671,56 +726,16 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
671 726
672 /* 727 /*
673 * If we read all the DMA'd characters, and we had an 728 * If we read all the DMA'd characters, and we had an
674 * incomplete buffer, that could be due to an rx error, 729 * incomplete buffer, that could be due to an rx error, or
675 * or maybe we just timed out. Read any pending chars 730 * maybe we just timed out. Read any pending chars and check
676 * and check the error status. 731 * the error status.
732 *
733 * Error conditions will only occur in the FIFO, these will
734 * trigger an immediate interrupt and stop the DMA job, so we
735 * will always find the error in the FIFO, never in the DMA
736 * buffer.
677 */ 737 */
678 while (1) { 738 fifotaken = pl011_fifo_to_tty(uap);
679 status = readw(uap->port.membase + UART01x_FR);
680 if (status & UART01x_FR_RXFE)
681 break;
682
683 /* Take chars from the FIFO and update status */
684 ch = readw(uap->port.membase + UART01x_DR) |
685 UART_DUMMY_DR_RX;
686 flag = TTY_NORMAL;
687 uap->port.icount.rx++;
688 fifotaken++;
689
690 /*
691 * Error conditions will only occur in the FIFO,
692 * these will trigger an immediate interrupt and
693 * stop the DMA job, so we will always find the
694 * error in the FIFO, never in the DMA buffer.
695 */
696 if (unlikely(ch & UART_DR_ERROR)) {
697 if (ch & UART011_DR_BE) {
698 ch &= ~(UART011_DR_FE | UART011_DR_PE);
699 uap->port.icount.brk++;
700 if (uart_handle_break(&uap->port))
701 continue;
702 } else if (ch & UART011_DR_PE)
703 uap->port.icount.parity++;
704 else if (ch & UART011_DR_FE)
705 uap->port.icount.frame++;
706 if (ch & UART011_DR_OE)
707 uap->port.icount.overrun++;
708
709 ch &= uap->port.read_status_mask;
710
711 if (ch & UART011_DR_BE)
712 flag = TTY_BREAK;
713 else if (ch & UART011_DR_PE)
714 flag = TTY_PARITY;
715 else if (ch & UART011_DR_FE)
716 flag = TTY_FRAME;
717 }
718
719 if (uart_handle_sysrq_char(&uap->port, ch & 255))
720 continue;
721
722 uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
723 }
724 } 739 }
725 740
726 spin_unlock(&uap->port.lock); 741 spin_unlock(&uap->port.lock);
@@ -1036,49 +1051,9 @@ static void pl011_enable_ms(struct uart_port *port)
1036static void pl011_rx_chars(struct uart_amba_port *uap) 1051static void pl011_rx_chars(struct uart_amba_port *uap)
1037{ 1052{
1038 struct tty_struct *tty = uap->port.state->port.tty; 1053 struct tty_struct *tty = uap->port.state->port.tty;
1039 unsigned int status, ch, flag, max_count = 256;
1040 1054
1041 status = readw(uap->port.membase + UART01x_FR); 1055 pl011_fifo_to_tty(uap);
1042 while ((status & UART01x_FR_RXFE) == 0 && max_count--) {
1043 ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX;
1044 flag = TTY_NORMAL;
1045 uap->port.icount.rx++;
1046 1056
1047 /*
1048 * Note that the error handling code is
1049 * out of the main execution path
1050 */
1051 if (unlikely(ch & UART_DR_ERROR)) {
1052 if (ch & UART011_DR_BE) {
1053 ch &= ~(UART011_DR_FE | UART011_DR_PE);
1054 uap->port.icount.brk++;
1055 if (uart_handle_break(&uap->port))
1056 goto ignore_char;
1057 } else if (ch & UART011_DR_PE)
1058 uap->port.icount.parity++;
1059 else if (ch & UART011_DR_FE)
1060 uap->port.icount.frame++;
1061 if (ch & UART011_DR_OE)
1062 uap->port.icount.overrun++;
1063
1064 ch &= uap->port.read_status_mask;
1065
1066 if (ch & UART011_DR_BE)
1067 flag = TTY_BREAK;
1068 else if (ch & UART011_DR_PE)
1069 flag = TTY_PARITY;
1070 else if (ch & UART011_DR_FE)
1071 flag = TTY_FRAME;
1072 }
1073
1074 if (uart_handle_sysrq_char(&uap->port, ch & 255))
1075 goto ignore_char;
1076
1077 uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
1078
1079 ignore_char:
1080 status = readw(uap->port.membase + UART01x_FR);
1081 }
1082 spin_unlock(&uap->port.lock); 1057 spin_unlock(&uap->port.lock);
1083 tty_flip_buffer_push(tty); 1058 tty_flip_buffer_push(tty);
1084 /* 1059 /*