diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tty/serial/omap-serial.c | 68 |
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]; | |||
51 | static void uart_tx_dma_callback(int lch, u16 ch_status, void *data); | 51 | static void uart_tx_dma_callback(int lch, u16 ch_status, void *data); |
52 | static void serial_omap_rx_timeout(unsigned long uart_no); | 52 | static void serial_omap_rx_timeout(unsigned long uart_no); |
53 | static int serial_omap_start_rxdma(struct uart_omap_port *up); | 53 | static int serial_omap_start_rxdma(struct uart_omap_port *up); |
54 | static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1); | ||
54 | 55 | ||
55 | static inline unsigned int serial_in(struct uart_omap_port *up, int offset) | 56 | static 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 | */ | ||
1436 | static 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 | |||
1418 | static void serial_omap_restore_context(struct uart_omap_port *up) | 1461 | static 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; |