diff options
Diffstat (limited to 'arch/arm/mach-omap2/serial.c')
| -rw-r--r-- | arch/arm/mach-omap2/serial.c | 101 |
1 files changed, 31 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 | /** |
