aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
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 /arch/arm
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>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-omap2/serial.c101
-rw-r--r--arch/arm/plat-omap/include/plat/omap-serial.h7
2 files changed, 38 insertions, 70 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__ */