diff options
Diffstat (limited to 'arch/arm/mach-omap2/serial.c')
-rw-r--r-- | arch/arm/mach-omap2/serial.c | 80 |
1 files changed, 69 insertions, 11 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 3771254dfa81..566e991ede81 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c | |||
@@ -37,6 +37,9 @@ | |||
37 | #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 | 37 | #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 |
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) | ||
41 | #define UART_ERRATA_i202_MDR1_ACCESS (0x1 << 1) | ||
42 | |||
40 | /* | 43 | /* |
41 | * 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 |
42 | * over the serial ports. This means that the UART clocks will stay on until | 45 | * over the serial ports. This means that the UART clocks will stay on until |
@@ -64,6 +67,7 @@ struct omap_uart_state { | |||
64 | struct list_head node; | 67 | struct list_head node; |
65 | struct platform_device pdev; | 68 | struct platform_device pdev; |
66 | 69 | ||
70 | u32 errata; | ||
67 | #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) | 71 | #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) |
68 | int context_valid; | 72 | int context_valid; |
69 | 73 | ||
@@ -74,6 +78,7 @@ struct omap_uart_state { | |||
74 | u16 sysc; | 78 | u16 sysc; |
75 | u16 scr; | 79 | u16 scr; |
76 | u16 wer; | 80 | u16 wer; |
81 | u16 mcr; | ||
77 | #endif | 82 | #endif |
78 | }; | 83 | }; |
79 | 84 | ||
@@ -180,6 +185,42 @@ static inline void __init omap_uart_reset(struct omap_uart_state *uart) | |||
180 | 185 | ||
181 | #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) | 186 | #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) |
182 | 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 | */ | ||
197 | static 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 | |||
183 | static void omap_uart_save_context(struct omap_uart_state *uart) | 224 | static void omap_uart_save_context(struct omap_uart_state *uart) |
184 | { | 225 | { |
185 | u16 lcr = 0; | 226 | u16 lcr = 0; |
@@ -197,6 +238,9 @@ static void omap_uart_save_context(struct omap_uart_state *uart) | |||
197 | uart->sysc = serial_read_reg(p, UART_OMAP_SYSC); | 238 | uart->sysc = serial_read_reg(p, UART_OMAP_SYSC); |
198 | uart->scr = serial_read_reg(p, UART_OMAP_SCR); | 239 | uart->scr = serial_read_reg(p, UART_OMAP_SCR); |
199 | uart->wer = serial_read_reg(p, UART_OMAP_WER); | 240 | uart->wer = serial_read_reg(p, UART_OMAP_WER); |
241 | serial_write_reg(p, UART_LCR, 0x80); | ||
242 | uart->mcr = serial_read_reg(p, UART_MCR); | ||
243 | serial_write_reg(p, UART_LCR, lcr); | ||
200 | 244 | ||
201 | uart->context_valid = 1; | 245 | uart->context_valid = 1; |
202 | } | 246 | } |
@@ -214,7 +258,10 @@ static void omap_uart_restore_context(struct omap_uart_state *uart) | |||
214 | 258 | ||
215 | uart->context_valid = 0; | 259 | uart->context_valid = 0; |
216 | 260 | ||
217 | 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); | ||
218 | serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ | 265 | serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ |
219 | efr = serial_read_reg(p, UART_EFR); | 266 | efr = serial_read_reg(p, UART_EFR); |
220 | serial_write_reg(p, UART_EFR, UART_EFR_ECB); | 267 | serial_write_reg(p, UART_EFR, UART_EFR_ECB); |
@@ -225,14 +272,18 @@ static void omap_uart_restore_context(struct omap_uart_state *uart) | |||
225 | serial_write_reg(p, UART_DLM, uart->dlh); | 272 | serial_write_reg(p, UART_DLM, uart->dlh); |
226 | serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ | 273 | serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ |
227 | serial_write_reg(p, UART_IER, uart->ier); | 274 | serial_write_reg(p, UART_IER, uart->ier); |
228 | serial_write_reg(p, UART_FCR, 0xA1); | 275 | serial_write_reg(p, UART_LCR, 0x80); |
276 | serial_write_reg(p, UART_MCR, uart->mcr); | ||
229 | serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ | 277 | serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ |
230 | serial_write_reg(p, UART_EFR, efr); | 278 | serial_write_reg(p, UART_EFR, efr); |
231 | serial_write_reg(p, UART_LCR, UART_LCR_WLEN8); | 279 | serial_write_reg(p, UART_LCR, UART_LCR_WLEN8); |
232 | serial_write_reg(p, UART_OMAP_SCR, uart->scr); | 280 | serial_write_reg(p, UART_OMAP_SCR, uart->scr); |
233 | serial_write_reg(p, UART_OMAP_WER, uart->wer); | 281 | serial_write_reg(p, UART_OMAP_WER, uart->wer); |
234 | serial_write_reg(p, UART_OMAP_SYSC, uart->sysc); | 282 | serial_write_reg(p, UART_OMAP_SYSC, uart->sysc); |
235 | 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 */ | ||
236 | } | 287 | } |
237 | #else | 288 | #else |
238 | static inline void omap_uart_save_context(struct omap_uart_state *uart) {} | 289 | static inline void omap_uart_save_context(struct omap_uart_state *uart) {} |
@@ -489,8 +540,8 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) | |||
489 | } | 540 | } |
490 | uart->wk_mask = wk_mask; | 541 | uart->wk_mask = wk_mask; |
491 | } else { | 542 | } else { |
492 | uart->wk_en = 0; | 543 | uart->wk_en = NULL; |
493 | uart->wk_st = 0; | 544 | uart->wk_st = NULL; |
494 | uart->wk_mask = 0; | 545 | uart->wk_mask = 0; |
495 | uart->padconf = 0; | 546 | uart->padconf = 0; |
496 | } | 547 | } |
@@ -552,7 +603,8 @@ static ssize_t sleep_timeout_store(struct device *dev, | |||
552 | return n; | 603 | return n; |
553 | } | 604 | } |
554 | 605 | ||
555 | DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store); | 606 | static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, |
607 | sleep_timeout_store); | ||
556 | #define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr)) | 608 | #define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr)) |
557 | #else | 609 | #else |
558 | static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} | 610 | static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} |
@@ -749,14 +801,20 @@ void __init omap_serial_init_port(int port) | |||
749 | * omap3xxx: Never read empty UART fifo on UARTs | 801 | * omap3xxx: Never read empty UART fifo on UARTs |
750 | * with IP rev >=0x52 | 802 | * with IP rev >=0x52 |
751 | */ | 803 | */ |
752 | if (cpu_is_omap44xx()) { | 804 | if (cpu_is_omap44xx()) |
753 | uart->p->serial_in = serial_in_override; | 805 | uart->errata |= UART_ERRATA_FIFO_FULL_ABORT; |
754 | uart->p->serial_out = serial_out_override; | 806 | else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF) |
755 | } else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF) | 807 | >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) |
756 | >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) { | 808 | uart->errata |= UART_ERRATA_FIFO_FULL_ABORT; |
809 | |||
810 | if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) { | ||
757 | uart->p->serial_in = serial_in_override; | 811 | uart->p->serial_in = serial_in_override; |
758 | uart->p->serial_out = serial_out_override; | 812 | uart->p->serial_out = serial_out_override; |
759 | } | 813 | } |
814 | |||
815 | /* Enable the MDR1 errata for OMAP3 */ | ||
816 | if (cpu_is_omap34xx()) | ||
817 | uart->errata |= UART_ERRATA_i202_MDR1_ACCESS; | ||
760 | } | 818 | } |
761 | 819 | ||
762 | /** | 820 | /** |