aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGovindraj.R <govindraj.raja@ti.com>2011-11-07 08:30:33 -0500
committerKevin Hilman <khilman@ti.com>2011-12-14 19:05:22 -0500
commit94734749af794c080f6af6ac3ce8c1c13ee2dbbd (patch)
treefca071b796416579b42860980cd7324ac128d22e
parentec3bebc6ec64aac23500e6b8ef5c0aaaeda735cf (diff)
ARM: OMAP2+: UART: Move errata handling from serial.c to omap-serial
Move the errata handling mechanism from serial.c to omap-serial file and utilise the same func in driver file. Errata i202, i291 are moved to be handled with omap-serial Moving the errata macro from serial.c file to driver header file as from on errata will be handled in driver file itself. Corrected errata id from chapter reference 2.15 to errata id i291. Removed errata and dma_enabled fields from omap_uart_state struct as they are no more needed with errata handling done within omap-serial. Signed-off-by: Govindraj.R <govindraj.raja@ti.com> Acked-by: Alan Cox <alan@linux.intel.com> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Kevin Hilman <khilman@ti.com>
-rw-r--r--arch/arm/mach-omap2/serial.c101
-rw-r--r--arch/arm/plat-omap/include/plat/omap-serial.h7
-rw-r--r--drivers/tty/serial/omap-serial.c68
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
75static LIST_HEAD(uart_list); 70static LIST_HEAD(uart_list);
76static u8 num_uarts; 71static 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 */
89static 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
117static inline void omap_uart_enable_clocks(struct omap_uart_state *uart) 73static 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
159static 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
180static void omap_uart_block_sleep(struct omap_uart_state *uart) 115static 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 */
210static 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
217static 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
225static void omap_uart_set_noidle(struct platform_device *pdev) {}
226static void omap_uart_set_forceidle(struct platform_device *pdev) {}
271static void omap_uart_block_sleep(struct omap_uart_state *uart) 227static 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
61struct omap_uart_port_info { 64struct 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
69struct uart_omap_dma { 75struct 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];
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;