aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/serial.c
diff options
context:
space:
mode:
authorDeepak K <deepak.k@ti.com>2010-08-02 06:18:12 -0400
committerTony Lindgren <tony@atomide.com>2010-08-02 06:18:12 -0400
commit0003450964357ec85eeeeda2e4bb8b06a6f82ad3 (patch)
tree69e8e5fab5bba66712681c0022fda2b6594c0ce3 /arch/arm/mach-omap2/serial.c
parent5a927b36f56c2a937e67f0947f233f723660f690 (diff)
omap2/3/4: serial: errata i202: fix for MDR1 access
Errata i202 (OMAP3430 - 1.12, OMAP3630 - 1.6): UART module MDR1 register access can cause a dummy underrun condition which could result in a freeze in the case of IrDA communication or if used as UART, corrupted data. Workaround is as follows for everytime MDR1 register is changed: * setup all required UART registers * setup MDR1.MODE_SELECT bit field * Wait 5 L4 clk cycles + 5 UART functional clock cycles * Clear the Tx and RX fifo using FCR register Note: The following step is not done as I am assuming it is not needed due to reconfiguration being done and there is no halted operation perse. * Read if required, the RESUME register to resume halted operation Based on an earlier patch at: http://git.omapzoom.org/?p=kernel/omap.git;a=commitdiff;h=42d4a342c009bd9727c100abc8a4bc3063c22f0c Signed-off-by: Deepak K <deepak.k@ti.com> Signed-off-by: Nishanth Menon <nm@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap2/serial.c')
-rw-r--r--arch/arm/mach-omap2/serial.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 009b63fc79f0..566e991ede81 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -38,6 +38,7 @@
38#define UART_OMAP_WER 0x17 /* Wake-up enable register */ 38#define UART_OMAP_WER 0x17 /* Wake-up enable register */
39 39
40#define UART_ERRATA_FIFO_FULL_ABORT (0x1 << 0) 40#define UART_ERRATA_FIFO_FULL_ABORT (0x1 << 0)
41#define UART_ERRATA_i202_MDR1_ACCESS (0x1 << 1)
41 42
42/* 43/*
43 * NOTE: By default the serial timeout is disabled as it causes lost characters 44 * NOTE: By default the serial timeout is disabled as it causes lost characters
@@ -184,6 +185,42 @@ static inline void __init omap_uart_reset(struct omap_uart_state *uart)
184 185
185#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) 186#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
186 187
188/*
189 * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
190 * The access to uart register after MDR1 Access
191 * causes UART to corrupt data.
192 *
193 * Need a delay =
194 * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
195 * give 10 times as much
196 */
197static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
198 u8 fcr_val)
199{
200 struct plat_serial8250_port *p = uart->p;
201 u8 timeout = 255;
202
203 serial_write_reg(p, UART_OMAP_MDR1, mdr1_val);
204 udelay(2);
205 serial_write_reg(p, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
206 UART_FCR_CLEAR_RCVR);
207 /*
208 * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
209 * TX_FIFO_E bit is 1.
210 */
211 while (UART_LSR_THRE != (serial_read_reg(p, UART_LSR) &
212 (UART_LSR_THRE | UART_LSR_DR))) {
213 timeout--;
214 if (!timeout) {
215 /* Should *never* happen. we warn and carry on */
216 dev_crit(&uart->pdev.dev, "Errata i202: timedout %x\n",
217 serial_read_reg(p, UART_LSR));
218 break;
219 }
220 udelay(1);
221 }
222}
223
187static void omap_uart_save_context(struct omap_uart_state *uart) 224static void omap_uart_save_context(struct omap_uart_state *uart)
188{ 225{
189 u16 lcr = 0; 226 u16 lcr = 0;
@@ -221,7 +258,10 @@ static void omap_uart_restore_context(struct omap_uart_state *uart)
221 258
222 uart->context_valid = 0; 259 uart->context_valid = 0;
223 260
224 serial_write_reg(p, UART_OMAP_MDR1, 0x7); 261 if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
262 omap_uart_mdr1_errataset(uart, 0x07, 0xA0);
263 else
264 serial_write_reg(p, UART_OMAP_MDR1, 0x7);
225 serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ 265 serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
226 efr = serial_read_reg(p, UART_EFR); 266 efr = serial_read_reg(p, UART_EFR);
227 serial_write_reg(p, UART_EFR, UART_EFR_ECB); 267 serial_write_reg(p, UART_EFR, UART_EFR_ECB);
@@ -234,14 +274,16 @@ static void omap_uart_restore_context(struct omap_uart_state *uart)
234 serial_write_reg(p, UART_IER, uart->ier); 274 serial_write_reg(p, UART_IER, uart->ier);
235 serial_write_reg(p, UART_LCR, 0x80); 275 serial_write_reg(p, UART_LCR, 0x80);
236 serial_write_reg(p, UART_MCR, uart->mcr); 276 serial_write_reg(p, UART_MCR, uart->mcr);
237 serial_write_reg(p, UART_FCR, 0xA1);
238 serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ 277 serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
239 serial_write_reg(p, UART_EFR, efr); 278 serial_write_reg(p, UART_EFR, efr);
240 serial_write_reg(p, UART_LCR, UART_LCR_WLEN8); 279 serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
241 serial_write_reg(p, UART_OMAP_SCR, uart->scr); 280 serial_write_reg(p, UART_OMAP_SCR, uart->scr);
242 serial_write_reg(p, UART_OMAP_WER, uart->wer); 281 serial_write_reg(p, UART_OMAP_WER, uart->wer);
243 serial_write_reg(p, UART_OMAP_SYSC, uart->sysc); 282 serial_write_reg(p, UART_OMAP_SYSC, uart->sysc);
244 serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */ 283 if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
284 omap_uart_mdr1_errataset(uart, 0x00, 0xA1);
285 else
286 serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
245} 287}
246#else 288#else
247static inline void omap_uart_save_context(struct omap_uart_state *uart) {} 289static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
@@ -769,6 +811,10 @@ void __init omap_serial_init_port(int port)
769 uart->p->serial_in = serial_in_override; 811 uart->p->serial_in = serial_in_override;
770 uart->p->serial_out = serial_out_override; 812 uart->p->serial_out = serial_out_override;
771 } 813 }
814
815 /* Enable the MDR1 errata for OMAP3 */
816 if (cpu_is_omap34xx())
817 uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
772} 818}
773 819
774/** 820/**