diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/serial.c | 101 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap-serial.h | 7 |
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 | ||
75 | static LIST_HEAD(uart_list); | 70 | static LIST_HEAD(uart_list); |
76 | static u8 num_uarts; | 71 | static 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 | */ | ||
89 | static 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 | |||
117 | static inline void omap_uart_enable_clocks(struct omap_uart_state *uart) | 73 | static 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 | ||
159 | static 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 | |||
180 | static void omap_uart_block_sleep(struct omap_uart_state *uart) | 115 | static 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 | */ | ||
210 | static 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 | |||
217 | static 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 |
225 | static void omap_uart_set_noidle(struct platform_device *pdev) {} | ||
226 | static void omap_uart_set_forceidle(struct platform_device *pdev) {} | ||
271 | static void omap_uart_block_sleep(struct omap_uart_state *uart) | 227 | static 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 | |||
61 | struct omap_uart_port_info { | 64 | struct 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 | ||
69 | struct uart_omap_dma { | 75 | struct 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__ */ |