aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/tty/serial/omap-serial.c68
1 files changed, 64 insertions, 4 deletions
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index ea4c24aa8c87..764ac7795694 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -51,6 +51,7 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
51static void uart_tx_dma_callback(int lch, u16 ch_status, void *data); 51static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
52static void serial_omap_rx_timeout(unsigned long uart_no); 52static void serial_omap_rx_timeout(unsigned long uart_no);
53static int serial_omap_start_rxdma(struct uart_omap_port *up); 53static int serial_omap_start_rxdma(struct uart_omap_port *up);
54static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
54 55
55static inline unsigned int serial_in(struct uart_omap_port *up, int offset) 56static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
56{ 57{
@@ -808,7 +809,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
808 809
809 /* Protocol, Baud Rate, and Interrupt Settings */ 810 /* Protocol, Baud Rate, and Interrupt Settings */
810 811
811 serial_out(up, UART_OMAP_MDR1, up->mdr1); 812 if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
813 serial_omap_mdr1_errataset(up, up->mdr1);
814 else
815 serial_out(up, UART_OMAP_MDR1, up->mdr1);
816
812 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 817 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
813 818
814 up->efr = serial_in(up, UART_EFR); 819 up->efr = serial_in(up, UART_EFR);
@@ -833,7 +838,10 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
833 else 838 else
834 up->mdr1 = UART_OMAP_MDR1_16X_MODE; 839 up->mdr1 = UART_OMAP_MDR1_16X_MODE;
835 840
836 serial_out(up, UART_OMAP_MDR1, up->mdr1); 841 if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
842 serial_omap_mdr1_errataset(up, up->mdr1);
843 else
844 serial_out(up, UART_OMAP_MDR1, up->mdr1);
837 845
838 /* Hardware Flow Control Configuration */ 846 /* Hardware Flow Control Configuration */
839 847
@@ -1362,6 +1370,7 @@ static int serial_omap_probe(struct platform_device *pdev)
1362 up->port.flags = omap_up_info->flags; 1370 up->port.flags = omap_up_info->flags;
1363 up->port.uartclk = omap_up_info->uartclk; 1371 up->port.uartclk = omap_up_info->uartclk;
1364 up->uart_dma.uart_base = mem->start; 1372 up->uart_dma.uart_base = mem->start;
1373 up->errata = omap_up_info->errata;
1365 1374
1366 if (omap_up_info->dma_enabled) { 1375 if (omap_up_info->dma_enabled) {
1367 up->uart_dma.uart_dma_tx = dma_tx->start; 1376 up->uart_dma.uart_dma_tx = dma_tx->start;
@@ -1415,9 +1424,47 @@ static int serial_omap_remove(struct platform_device *dev)
1415 return 0; 1424 return 0;
1416} 1425}
1417 1426
1427/*
1428 * Work Around for Errata i202 (2430, 3430, 3630, 4430 and 4460)
1429 * The access to uart register after MDR1 Access
1430 * causes UART to corrupt data.
1431 *
1432 * Need a delay =
1433 * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
1434 * give 10 times as much
1435 */
1436static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1)
1437{
1438 u8 timeout = 255;
1439
1440 serial_out(up, UART_OMAP_MDR1, mdr1);
1441 udelay(2);
1442 serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT |
1443 UART_FCR_CLEAR_RCVR);
1444 /*
1445 * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
1446 * TX_FIFO_E bit is 1.
1447 */
1448 while (UART_LSR_THRE != (serial_in(up, UART_LSR) &
1449 (UART_LSR_THRE | UART_LSR_DR))) {
1450 timeout--;
1451 if (!timeout) {
1452 /* Should *never* happen. we warn and carry on */
1453 dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n",
1454 serial_in(up, UART_LSR));
1455 break;
1456 }
1457 udelay(1);
1458 }
1459}
1460
1418static void serial_omap_restore_context(struct uart_omap_port *up) 1461static void serial_omap_restore_context(struct uart_omap_port *up)
1419{ 1462{
1420 serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); 1463 if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
1464 serial_omap_mdr1_errataset(up, UART_OMAP_MDR1_DISABLE);
1465 else
1466 serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
1467
1421 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */ 1468 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
1422 serial_out(up, UART_EFR, UART_EFR_ECB); 1469 serial_out(up, UART_EFR, UART_EFR_ECB);
1423 serial_out(up, UART_LCR, 0x0); /* Operational mode */ 1470 serial_out(up, UART_LCR, 0x0); /* Operational mode */
@@ -1434,7 +1481,10 @@ static void serial_omap_restore_context(struct uart_omap_port *up)
1434 serial_out(up, UART_OMAP_SCR, up->scr); 1481 serial_out(up, UART_OMAP_SCR, up->scr);
1435 serial_out(up, UART_EFR, up->efr); 1482 serial_out(up, UART_EFR, up->efr);
1436 serial_out(up, UART_LCR, up->lcr); 1483 serial_out(up, UART_LCR, up->lcr);
1437 serial_out(up, UART_OMAP_MDR1, up->mdr1); 1484 if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
1485 serial_omap_mdr1_errataset(up, up->mdr1);
1486 else
1487 serial_out(up, UART_OMAP_MDR1, up->mdr1);
1438} 1488}
1439 1489
1440#ifdef CONFIG_PM_RUNTIME 1490#ifdef CONFIG_PM_RUNTIME
@@ -1449,6 +1499,11 @@ static int serial_omap_runtime_suspend(struct device *dev)
1449 if (pdata->get_context_loss_count) 1499 if (pdata->get_context_loss_count)
1450 up->context_loss_cnt = pdata->get_context_loss_count(dev); 1500 up->context_loss_cnt = pdata->get_context_loss_count(dev);
1451 1501
1502 /* Errata i291 */
1503 if (up->use_dma && pdata->set_forceidle &&
1504 (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
1505 pdata->set_forceidle(up->pdev);
1506
1452 return 0; 1507 return 0;
1453} 1508}
1454 1509
@@ -1464,6 +1519,11 @@ static int serial_omap_runtime_resume(struct device *dev)
1464 if (up->context_loss_cnt != loss_cnt) 1519 if (up->context_loss_cnt != loss_cnt)
1465 serial_omap_restore_context(up); 1520 serial_omap_restore_context(up);
1466 } 1521 }
1522
1523 /* Errata i291 */
1524 if (up->use_dma && pdata->set_noidle &&
1525 (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
1526 pdata->set_noidle(up->pdev);
1467 } 1527 }
1468 1528
1469 return 0; 1529 return 0;