@@ -185,6 +185,41 @@ static inline void __init omap_uart_reset(struct omap_uart_state *uart)
#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
+/*
+ * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
+ * The access to uart register after MDR1 Access
+ * causes UART to corrupt data.
+ *
+ * Need a delay =
+ * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
+ * give 10 times as much
+ */
+static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
+ u8 fcr_val)
+{
+ struct plat_serial8250_port *p = uart->p;
+ u8 timeout = 255;
+
+ serial_write_reg(p, UART_OMAP_MDR1, mdr1_val);
+ udelay(2);
+ /* Add TX and RX FIFO Clear */
+ serial_write_reg(p, UART_FCR, fcr_val | 0x06);
+ /*
+ * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
+ * TX_FIFO_E bit is 1. So, we check for 0x20 being read.
+ */
+ while (0x20 != (serial_read_reg(p, UART_LSR) & 0x21)) {
+ timeout--;
+ if (!timeout) {
+ /* Should *never* happen. we warn and carry on */
+ dev_crit(&uart->pdev.dev, "Errata i202: timedout %x\n",
+ serial_read_reg(p, UART_LSR));
+ break;
+ }
+ udelay(1);
+ }
+}
+
static void omap_uart_save_context(struct omap_uart_state *uart)
{
u16 lcr = 0;
@@ -222,7 +257,7 @@ static void omap_uart_restore_context(struct omap_uart_state *uart)
uart->context_valid = 0;
- serial_write_reg(p, UART_OMAP_MDR1, 0x7);
+ omap_uart_mdr1_errataset(uart, 0x07, 0xA0);
serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
efr = serial_read_reg(p, UART_EFR);
serial_write_reg(p, UART_EFR, UART_EFR_ECB);
@@ -235,14 +270,13 @@ static void omap_uart_restore_context(struct omap_uart_state *uart)
serial_write_reg(p, UART_IER, uart->ier);
serial_write_reg(p, UART_LCR, 0x80);
serial_write_reg(p, UART_MCR, uart->mcr);
- serial_write_reg(p, UART_FCR, 0xA1);
serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
serial_write_reg(p, UART_EFR, efr);
serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
serial_write_reg(p, UART_OMAP_SCR, uart->scr);
serial_write_reg(p, UART_OMAP_WER, uart->wer);
serial_write_reg(p, UART_OMAP_SYSC, uart->sysc);
- serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
+ omap_uart_mdr1_errataset(uart, 0x00, 0xA1);
}
#else
static inline void omap_uart_save_context(struct omap_uart_state *uart) {}