diff options
-rw-r--r-- | arch/arm/mach-omap2/serial.c | 101 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap-serial.h | 7 | ||||
-rw-r--r-- | drivers/tty/serial/omap-serial.c | 68 |
3 files changed, 102 insertions, 74 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 78ca7e8fc10b..77a25cb1dcca 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c | |||
@@ -42,8 +42,6 @@ | |||
42 | #include "control.h" | 42 | #include "control.h" |
43 | #include "mux.h" | 43 | #include "mux.h" |
44 | 44 | ||
45 | #define UART_ERRATA_i202_MDR1_ACCESS (0x1 << 1) | ||
46 | |||
47 | /* | 45 | /* |
48 | * NOTE: By default the serial timeout is disabled as it causes lost characters | 46 | * NOTE: By default the serial timeout is disabled as it causes lost characters |
49 | * over the serial ports. This means that the UART clocks will stay on until | 47 | * over the serial ports. This means that the UART clocks will stay on until |
@@ -61,59 +59,17 @@ struct omap_uart_state { | |||
61 | void __iomem *wk_st; | 59 | void __iomem *wk_st; |
62 | void __iomem *wk_en; | 60 | void __iomem *wk_en; |
63 | u32 wk_mask; | 61 | u32 wk_mask; |
64 | u32 dma_enabled; | ||
65 | 62 | ||
66 | int clocked; | 63 | int clocked; |
67 | 64 | ||
68 | struct list_head node; | 65 | struct list_head node; |
69 | struct omap_hwmod *oh; | 66 | struct omap_hwmod *oh; |
70 | struct platform_device *pdev; | 67 | struct platform_device *pdev; |
71 | |||
72 | u32 errata; | ||
73 | }; | 68 | }; |
74 | 69 | ||
75 | static LIST_HEAD(uart_list); | 70 | static LIST_HEAD(uart_list); |
76 | static u8 num_uarts; | 71 | static u8 num_uarts; |
77 | 72 | ||
78 | #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) | ||
79 | |||
80 | /* | ||
81 | * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6) | ||
82 | * The access to uart register after MDR1 Access | ||
83 | * causes UART to corrupt data. | ||
84 | * | ||
85 | * Need a delay = | ||
86 | * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS) | ||
87 | * give 10 times as much | ||
88 | */ | ||
89 | static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val, | ||
90 | u8 fcr_val) | ||
91 | { | ||
92 | u8 timeout = 255; | ||
93 | |||
94 | serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val); | ||
95 | udelay(2); | ||
96 | serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT | | ||
97 | UART_FCR_CLEAR_RCVR); | ||
98 | /* | ||
99 | * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and | ||
100 | * TX_FIFO_E bit is 1. | ||
101 | */ | ||
102 | while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) & | ||
103 | (UART_LSR_THRE | UART_LSR_DR))) { | ||
104 | timeout--; | ||
105 | if (!timeout) { | ||
106 | /* Should *never* happen. we warn and carry on */ | ||
107 | dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n", | ||
108 | serial_read_reg(uart, UART_LSR)); | ||
109 | break; | ||
110 | } | ||
111 | udelay(1); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | #endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */ | ||
116 | |||
117 | static inline void omap_uart_enable_clocks(struct omap_uart_state *uart) | 73 | static inline void omap_uart_enable_clocks(struct omap_uart_state *uart) |
118 | { | 74 | { |
119 | if (uart->clocked) | 75 | if (uart->clocked) |
@@ -156,27 +112,6 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart) | |||
156 | } | 112 | } |
157 | } | 113 | } |
158 | 114 | ||
159 | static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, | ||
160 | int enable) | ||
161 | { | ||
162 | u8 idlemode; | ||
163 | |||
164 | if (enable) { | ||
165 | /** | ||
166 | * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests | ||
167 | * in Smartidle Mode When Configured for DMA Operations. | ||
168 | */ | ||
169 | if (uart->dma_enabled) | ||
170 | idlemode = HWMOD_IDLEMODE_FORCE; | ||
171 | else | ||
172 | idlemode = HWMOD_IDLEMODE_SMART; | ||
173 | } else { | ||
174 | idlemode = HWMOD_IDLEMODE_NO; | ||
175 | } | ||
176 | |||
177 | omap_hwmod_set_slave_idlemode(uart->oh, idlemode); | ||
178 | } | ||
179 | |||
180 | static void omap_uart_block_sleep(struct omap_uart_state *uart) | 115 | static void omap_uart_block_sleep(struct omap_uart_state *uart) |
181 | { | 116 | { |
182 | omap_uart_enable_clocks(uart); | 117 | omap_uart_enable_clocks(uart); |
@@ -267,7 +202,28 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) | |||
267 | } | 202 | } |
268 | } | 203 | } |
269 | 204 | ||
205 | /* | ||
206 | * Errata i291: [UART]:Cannot Acknowledge Idle Requests | ||
207 | * in Smartidle Mode When Configured for DMA Operations. | ||
208 | * WA: configure uart in force idle mode. | ||
209 | */ | ||
210 | static void omap_uart_set_noidle(struct platform_device *pdev) | ||
211 | { | ||
212 | struct omap_device *od = to_omap_device(pdev); | ||
213 | |||
214 | omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO); | ||
215 | } | ||
216 | |||
217 | static void omap_uart_set_forceidle(struct platform_device *pdev) | ||
218 | { | ||
219 | struct omap_device *od = to_omap_device(pdev); | ||
220 | |||
221 | omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_FORCE); | ||
222 | } | ||
223 | |||
270 | #else | 224 | #else |
225 | static void omap_uart_set_noidle(struct platform_device *pdev) {} | ||
226 | static void omap_uart_set_forceidle(struct platform_device *pdev) {} | ||
271 | static void omap_uart_block_sleep(struct omap_uart_state *uart) | 227 | static void omap_uart_block_sleep(struct omap_uart_state *uart) |
272 | { | 228 | { |
273 | /* Needed to enable UART clocks when built without CONFIG_PM */ | 229 | /* Needed to enable UART clocks when built without CONFIG_PM */ |
@@ -473,13 +429,22 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) | |||
473 | break; | 429 | break; |
474 | 430 | ||
475 | oh = uart->oh; | 431 | oh = uart->oh; |
476 | uart->dma_enabled = 0; | ||
477 | name = DRIVER_NAME; | 432 | name = DRIVER_NAME; |
478 | 433 | ||
479 | omap_up.dma_enabled = uart->dma_enabled; | 434 | omap_up.dma_enabled = uart->dma_enabled; |
480 | omap_up.uartclk = OMAP24XX_BASE_BAUD * 16; | 435 | omap_up.uartclk = OMAP24XX_BASE_BAUD * 16; |
481 | omap_up.flags = UPF_BOOT_AUTOCONF; | 436 | omap_up.flags = UPF_BOOT_AUTOCONF; |
482 | omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count; | 437 | omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count; |
438 | omap_up.set_forceidle = omap_uart_set_forceidle; | ||
439 | omap_up.set_noidle = omap_uart_set_noidle; | ||
440 | |||
441 | /* Enable the MDR1 Errata i202 for OMAP2430/3xxx/44xx */ | ||
442 | if (!cpu_is_omap2420() && !cpu_is_ti816x()) | ||
443 | omap_up.errata |= UART_ERRATA_i202_MDR1_ACCESS; | ||
444 | |||
445 | /* Enable DMA Mode Force Idle Errata i291 for omap34xx/3630 */ | ||
446 | if (cpu_is_omap34xx() || cpu_is_omap3630()) | ||
447 | omap_up.errata |= UART_ERRATA_i291_DMA_FORCEIDLE; | ||
483 | 448 | ||
484 | pdata = &omap_up; | 449 | pdata = &omap_up; |
485 | pdata_size = sizeof(struct omap_uart_port_info); | 450 | pdata_size = sizeof(struct omap_uart_port_info); |
@@ -519,10 +484,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) | |||
519 | if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) || | 484 | if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) || |
520 | (pdata->wk_en && pdata->wk_mask)) | 485 | (pdata->wk_en && pdata->wk_mask)) |
521 | device_init_wakeup(&pdev->dev, true); | 486 | device_init_wakeup(&pdev->dev, true); |
522 | |||
523 | /* Enable the MDR1 errata for OMAP3 */ | ||
524 | if (cpu_is_omap34xx() && !(cpu_is_ti81xx() || cpu_is_am33xx())) | ||
525 | uart->errata |= UART_ERRATA_i202_MDR1_ACCESS; | ||
526 | } | 487 | } |
527 | 488 | ||
528 | /** | 489 | /** |
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 348c9ead6edb..842b429cfeaa 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h | |||
@@ -58,12 +58,18 @@ | |||
58 | 58 | ||
59 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA | 59 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA |
60 | 60 | ||
61 | #define UART_ERRATA_i202_MDR1_ACCESS BIT(0) | ||
62 | #define UART_ERRATA_i291_DMA_FORCEIDLE BIT(1) | ||
63 | |||
61 | struct omap_uart_port_info { | 64 | struct omap_uart_port_info { |
62 | bool dma_enabled; /* To specify DMA Mode */ | 65 | bool dma_enabled; /* To specify DMA Mode */ |
63 | unsigned int uartclk; /* UART clock rate */ | 66 | unsigned int uartclk; /* UART clock rate */ |
64 | upf_t flags; /* UPF_* flags */ | 67 | upf_t flags; /* UPF_* flags */ |
68 | u32 errata; | ||
65 | 69 | ||
66 | int (*get_context_loss_count)(struct device *); | 70 | int (*get_context_loss_count)(struct device *); |
71 | void (*set_forceidle)(struct platform_device *); | ||
72 | void (*set_noidle)(struct platform_device *); | ||
67 | }; | 73 | }; |
68 | 74 | ||
69 | struct uart_omap_dma { | 75 | struct uart_omap_dma { |
@@ -117,6 +123,7 @@ struct uart_omap_port { | |||
117 | char name[20]; | 123 | char name[20]; |
118 | unsigned long port_activity; | 124 | unsigned long port_activity; |
119 | u32 context_loss_cnt; | 125 | u32 context_loss_cnt; |
126 | u32 errata; | ||
120 | }; | 127 | }; |
121 | 128 | ||
122 | #endif /* __OMAP_SERIAL_H__ */ | 129 | #endif /* __OMAP_SERIAL_H__ */ |
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; |