aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/pch_uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/pch_uart.c')
-rw-r--r--drivers/tty/serial/pch_uart.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index c2816f494807..4fdec6a6b758 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -39,6 +39,7 @@ enum {
39 PCH_UART_HANDLED_RX_ERR_INT_SHIFT, 39 PCH_UART_HANDLED_RX_ERR_INT_SHIFT,
40 PCH_UART_HANDLED_RX_TRG_INT_SHIFT, 40 PCH_UART_HANDLED_RX_TRG_INT_SHIFT,
41 PCH_UART_HANDLED_MS_INT_SHIFT, 41 PCH_UART_HANDLED_MS_INT_SHIFT,
42 PCH_UART_HANDLED_LS_INT_SHIFT,
42}; 43};
43 44
44enum { 45enum {
@@ -63,6 +64,8 @@ enum {
63 PCH_UART_HANDLED_RX_TRG_INT_SHIFT)<<1)) 64 PCH_UART_HANDLED_RX_TRG_INT_SHIFT)<<1))
64#define PCH_UART_HANDLED_MS_INT (1<<((PCH_UART_HANDLED_MS_INT_SHIFT)<<1)) 65#define PCH_UART_HANDLED_MS_INT (1<<((PCH_UART_HANDLED_MS_INT_SHIFT)<<1))
65 66
67#define PCH_UART_HANDLED_LS_INT (1<<((PCH_UART_HANDLED_LS_INT_SHIFT)<<1))
68
66#define PCH_UART_RBR 0x00 69#define PCH_UART_RBR 0x00
67#define PCH_UART_THR 0x00 70#define PCH_UART_THR 0x00
68 71
@@ -229,7 +232,6 @@ struct eg20t_port {
229 int start_tx; 232 int start_tx;
230 int start_rx; 233 int start_rx;
231 int tx_empty; 234 int tx_empty;
232 int int_dis_flag;
233 int trigger; 235 int trigger;
234 int trigger_level; 236 int trigger_level;
235 struct pch_uart_buffer rxbuf; 237 struct pch_uart_buffer rxbuf;
@@ -237,7 +239,6 @@ struct eg20t_port {
237 unsigned int fcr; 239 unsigned int fcr;
238 unsigned int mcr; 240 unsigned int mcr;
239 unsigned int use_dma; 241 unsigned int use_dma;
240 unsigned int use_dma_flag;
241 struct dma_async_tx_descriptor *desc_tx; 242 struct dma_async_tx_descriptor *desc_tx;
242 struct dma_async_tx_descriptor *desc_rx; 243 struct dma_async_tx_descriptor *desc_rx;
243 struct pch_dma_slave param_tx; 244 struct pch_dma_slave param_tx;
@@ -560,14 +561,10 @@ static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
560 return i; 561 return i;
561} 562}
562 563
563static unsigned int pch_uart_hal_get_iid(struct eg20t_port *priv) 564static unsigned char pch_uart_hal_get_iid(struct eg20t_port *priv)
564{ 565{
565 unsigned int iir; 566 return ioread8(priv->membase + UART_IIR) &\
566 int ret; 567 (PCH_UART_IIR_IID | PCH_UART_IIR_TOI | PCH_UART_IIR_IP);
567
568 iir = ioread8(priv->membase + UART_IIR);
569 ret = (iir & (PCH_UART_IIR_IID | PCH_UART_IIR_TOI | PCH_UART_IIR_IP));
570 return ret;
571} 568}
572 569
573static u8 pch_uart_hal_get_line_status(struct eg20t_port *priv) 570static u8 pch_uart_hal_get_line_status(struct eg20t_port *priv)
@@ -666,10 +663,13 @@ static void pch_free_dma(struct uart_port *port)
666 dma_release_channel(priv->chan_rx); 663 dma_release_channel(priv->chan_rx);
667 priv->chan_rx = NULL; 664 priv->chan_rx = NULL;
668 } 665 }
669 if (sg_dma_address(&priv->sg_rx)) 666
670 dma_free_coherent(port->dev, port->fifosize, 667 if (priv->rx_buf_dma) {
671 sg_virt(&priv->sg_rx), 668 dma_free_coherent(port->dev, port->fifosize, priv->rx_buf_virt,
672 sg_dma_address(&priv->sg_rx)); 669 priv->rx_buf_dma);
670 priv->rx_buf_virt = NULL;
671 priv->rx_buf_dma = 0;
672 }
673 673
674 return; 674 return;
675} 675}
@@ -1053,12 +1053,17 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
1053 unsigned int handled; 1053 unsigned int handled;
1054 u8 lsr; 1054 u8 lsr;
1055 int ret = 0; 1055 int ret = 0;
1056 unsigned int iid; 1056 unsigned char iid;
1057 unsigned long flags; 1057 unsigned long flags;
1058 int next = 1;
1059 u8 msr;
1058 1060
1059 spin_lock_irqsave(&priv->port.lock, flags); 1061 spin_lock_irqsave(&priv->port.lock, flags);
1060 handled = 0; 1062 handled = 0;
1061 while ((iid = pch_uart_hal_get_iid(priv)) > 1) { 1063 while (next) {
1064 iid = pch_uart_hal_get_iid(priv);
1065 if (iid & PCH_UART_IIR_IP) /* No Interrupt */
1066 break;
1062 switch (iid) { 1067 switch (iid) {
1063 case PCH_UART_IID_RLS: /* Receiver Line Status */ 1068 case PCH_UART_IID_RLS: /* Receiver Line Status */
1064 lsr = pch_uart_hal_get_line_status(priv); 1069 lsr = pch_uart_hal_get_line_status(priv);
@@ -1066,6 +1071,8 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
1066 UART_LSR_PE | UART_LSR_OE)) { 1071 UART_LSR_PE | UART_LSR_OE)) {
1067 pch_uart_err_ir(priv, lsr); 1072 pch_uart_err_ir(priv, lsr);
1068 ret = PCH_UART_HANDLED_RX_ERR_INT; 1073 ret = PCH_UART_HANDLED_RX_ERR_INT;
1074 } else {
1075 ret = PCH_UART_HANDLED_LS_INT;
1069 } 1076 }
1070 break; 1077 break;
1071 case PCH_UART_IID_RDR: /* Received Data Ready */ 1078 case PCH_UART_IID_RDR: /* Received Data Ready */
@@ -1092,20 +1099,22 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
1092 ret = handle_tx(priv); 1099 ret = handle_tx(priv);
1093 break; 1100 break;
1094 case PCH_UART_IID_MS: /* Modem Status */ 1101 case PCH_UART_IID_MS: /* Modem Status */
1095 ret = PCH_UART_HANDLED_MS_INT; 1102 msr = pch_uart_hal_get_modem(priv);
1103 next = 0; /* MS ir prioirty is the lowest. So, MS ir
1104 means final interrupt */
1105 if ((msr & UART_MSR_ANY_DELTA) == 0)
1106 break;
1107 ret |= PCH_UART_HANDLED_MS_INT;
1096 break; 1108 break;
1097 default: /* Never junp to this label */ 1109 default: /* Never junp to this label */
1098 dev_err(priv->port.dev, "%s:iid=%d (%lu)\n", __func__, 1110 dev_err(priv->port.dev, "%s:iid=%02x (%lu)\n", __func__,
1099 iid, jiffies); 1111 iid, jiffies);
1100 ret = -1; 1112 ret = -1;
1113 next = 0;
1101 break; 1114 break;
1102 } 1115 }
1103 handled |= (unsigned int)ret; 1116 handled |= (unsigned int)ret;
1104 } 1117 }
1105 if (handled == 0 && iid <= 1) {
1106 if (priv->int_dis_flag)
1107 priv->int_dis_flag = 0;
1108 }
1109 1118
1110 spin_unlock_irqrestore(&priv->port.lock, flags); 1119 spin_unlock_irqrestore(&priv->port.lock, flags);
1111 return IRQ_RETVAL(handled); 1120 return IRQ_RETVAL(handled);
@@ -1200,7 +1209,6 @@ static void pch_uart_stop_rx(struct uart_port *port)
1200 priv = container_of(port, struct eg20t_port, port); 1209 priv = container_of(port, struct eg20t_port, port);
1201 priv->start_rx = 0; 1210 priv->start_rx = 0;
1202 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT); 1211 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT);
1203 priv->int_dis_flag = 1;
1204} 1212}
1205 1213
1206/* Enable the modem status interrupts. */ 1214/* Enable the modem status interrupts. */
@@ -1447,7 +1455,6 @@ static int pch_uart_verify_port(struct uart_port *port,
1447 __func__); 1455 __func__);
1448 return -EOPNOTSUPP; 1456 return -EOPNOTSUPP;
1449#endif 1457#endif
1450 priv->use_dma_flag = 1;
1451 dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n"); 1458 dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n");
1452 if (!priv->use_dma) 1459 if (!priv->use_dma)
1453 pch_request_dma(port); 1460 pch_request_dma(port);