aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/amba-pl011.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2011-02-24 07:21:36 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-03-10 05:07:24 -0500
commit29772c4e28cbb33ea1f8c6dcd130ebf190b91d85 (patch)
tree17042eda647a9576055f7355fc179595fe429a55 /drivers/tty/serial/amba-pl011.c
parentead76f329f777c7301e0a5456a0a1c7a081570bd (diff)
ARM: 6764/1: pl011: factor out FIFO to TTY code
This piece of code was just slightly different between the DMA and IRQ paths, in DMA mode we surely shouldn't read more than 256 character either, so factor this out in its own function and use for both DMA and PIO mode. Tested on Ux500 and U300. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
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 /*