diff options
author | Govindraj.R <govindraj.raja@ti.com> | 2011-10-13 04:41:09 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@ti.com> | 2011-12-14 19:05:23 -0500 |
commit | 62f3ec5fbd5fddce62b7a71adc04723a5eb903da (patch) | |
tree | 682d86d38cf888bd10622479d779e862ebcee6d3 /arch | |
parent | 94734749af794c080f6af6ac3ce8c1c13ee2dbbd (diff) |
ARM: OMAP2+: UART: Add wakeup mechanism for omap-uarts
From the runtime callbacks enable hwmod wakeups for uart which will
internally enable io-pad wakeups for uarts if they have rx-pad pins
set as wakeup capabale.
Use the io-ring wakeup mechanism after uart clock gating and leave
the PM_WKST set for uart to default reset values cleanup the
code in serial.c which was handling PM_WKST reg.
Irq_chaing(PRM_DRIVER) is used to wakeup uart after uart clocks are gated
using pad wakeup mechanism.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de> (for drivers/tty changes)
Signed-off-by: Kevin Hilman <khilman@ti.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap2/serial.c | 96 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap-serial.h | 2 |
2 files changed, 14 insertions, 84 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 77a25cb1dcca..aa6f7f05a1e3 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c | |||
@@ -56,10 +56,6 @@ struct omap_uart_state { | |||
56 | int num; | 56 | int num; |
57 | int can_sleep; | 57 | int can_sleep; |
58 | 58 | ||
59 | void __iomem *wk_st; | ||
60 | void __iomem *wk_en; | ||
61 | u32 wk_mask; | ||
62 | |||
63 | int clocked; | 59 | int clocked; |
64 | 60 | ||
65 | struct list_head node; | 61 | struct list_head node; |
@@ -92,26 +88,6 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart) | |||
92 | omap_device_idle(uart->pdev); | 88 | omap_device_idle(uart->pdev); |
93 | } | 89 | } |
94 | 90 | ||
95 | static void omap_uart_enable_wakeup(struct omap_uart_state *uart) | ||
96 | { | ||
97 | /* Set wake-enable bit */ | ||
98 | if (uart->wk_en && uart->wk_mask) { | ||
99 | u32 v = __raw_readl(uart->wk_en); | ||
100 | v |= uart->wk_mask; | ||
101 | __raw_writel(v, uart->wk_en); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | static void omap_uart_disable_wakeup(struct omap_uart_state *uart) | ||
106 | { | ||
107 | /* Clear wake-enable bit */ | ||
108 | if (uart->wk_en && uart->wk_mask) { | ||
109 | u32 v = __raw_readl(uart->wk_en); | ||
110 | v &= ~uart->wk_mask; | ||
111 | __raw_writel(v, uart->wk_en); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static void omap_uart_block_sleep(struct omap_uart_state *uart) | 91 | static void omap_uart_block_sleep(struct omap_uart_state *uart) |
116 | { | 92 | { |
117 | omap_uart_enable_clocks(uart); | 93 | omap_uart_enable_clocks(uart); |
@@ -141,65 +117,17 @@ int omap_uart_can_sleep(void) | |||
141 | return can_sleep; | 117 | return can_sleep; |
142 | } | 118 | } |
143 | 119 | ||
144 | static void omap_uart_idle_init(struct omap_uart_state *uart) | 120 | static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable) |
145 | { | 121 | { |
146 | int ret; | 122 | struct omap_device *od = to_omap_device(pdev); |
147 | |||
148 | uart->can_sleep = 0; | ||
149 | omap_uart_smart_idle_enable(uart, 0); | ||
150 | 123 | ||
151 | if (cpu_is_omap34xx() && !(cpu_is_ti81xx() || cpu_is_am33xx())) { | 124 | if (!od) |
152 | u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD; | 125 | return; |
153 | u32 wk_mask = 0; | ||
154 | 126 | ||
155 | /* XXX These PRM accesses do not belong here */ | 127 | if (enable) |
156 | uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1); | 128 | omap_hwmod_enable_wakeup(od->hwmods[0]); |
157 | uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1); | 129 | else |
158 | switch (uart->num) { | 130 | omap_hwmod_disable_wakeup(od->hwmods[0]); |
159 | case 0: | ||
160 | wk_mask = OMAP3430_ST_UART1_MASK; | ||
161 | break; | ||
162 | case 1: | ||
163 | wk_mask = OMAP3430_ST_UART2_MASK; | ||
164 | break; | ||
165 | case 2: | ||
166 | wk_mask = OMAP3430_ST_UART3_MASK; | ||
167 | break; | ||
168 | case 3: | ||
169 | wk_mask = OMAP3630_ST_UART4_MASK; | ||
170 | break; | ||
171 | } | ||
172 | uart->wk_mask = wk_mask; | ||
173 | } else if (cpu_is_omap24xx()) { | ||
174 | u32 wk_mask = 0; | ||
175 | u32 wk_en = PM_WKEN1, wk_st = PM_WKST1; | ||
176 | |||
177 | switch (uart->num) { | ||
178 | case 0: | ||
179 | wk_mask = OMAP24XX_ST_UART1_MASK; | ||
180 | break; | ||
181 | case 1: | ||
182 | wk_mask = OMAP24XX_ST_UART2_MASK; | ||
183 | break; | ||
184 | case 2: | ||
185 | wk_en = OMAP24XX_PM_WKEN2; | ||
186 | wk_st = OMAP24XX_PM_WKST2; | ||
187 | wk_mask = OMAP24XX_ST_UART3_MASK; | ||
188 | break; | ||
189 | } | ||
190 | uart->wk_mask = wk_mask; | ||
191 | if (cpu_is_omap2430()) { | ||
192 | uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, wk_en); | ||
193 | uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, wk_st); | ||
194 | } else if (cpu_is_omap2420()) { | ||
195 | uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, wk_en); | ||
196 | uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, wk_st); | ||
197 | } | ||
198 | } else { | ||
199 | uart->wk_en = NULL; | ||
200 | uart->wk_st = NULL; | ||
201 | uart->wk_mask = 0; | ||
202 | } | ||
203 | } | 131 | } |
204 | 132 | ||
205 | /* | 133 | /* |
@@ -222,6 +150,8 @@ static void omap_uart_set_forceidle(struct platform_device *pdev) | |||
222 | } | 150 | } |
223 | 151 | ||
224 | #else | 152 | #else |
153 | static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable) | ||
154 | {} | ||
225 | static void omap_uart_set_noidle(struct platform_device *pdev) {} | 155 | static void omap_uart_set_noidle(struct platform_device *pdev) {} |
226 | static void omap_uart_set_forceidle(struct platform_device *pdev) {} | 156 | static void omap_uart_set_forceidle(struct platform_device *pdev) {} |
227 | static void omap_uart_block_sleep(struct omap_uart_state *uart) | 157 | static void omap_uart_block_sleep(struct omap_uart_state *uart) |
@@ -437,6 +367,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) | |||
437 | omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count; | 367 | omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count; |
438 | omap_up.set_forceidle = omap_uart_set_forceidle; | 368 | omap_up.set_forceidle = omap_uart_set_forceidle; |
439 | omap_up.set_noidle = omap_uart_set_noidle; | 369 | omap_up.set_noidle = omap_uart_set_noidle; |
370 | omap_up.enable_wakeup = omap_uart_enable_wakeup; | ||
440 | 371 | ||
441 | /* Enable the MDR1 Errata i202 for OMAP2430/3xxx/44xx */ | 372 | /* Enable the MDR1 Errata i202 for OMAP2430/3xxx/44xx */ |
442 | if (!cpu_is_omap2420() && !cpu_is_ti816x()) | 373 | if (!cpu_is_omap2420() && !cpu_is_ti816x()) |
@@ -474,15 +405,12 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) | |||
474 | omap_hwmod_idle(uart->oh); | 405 | omap_hwmod_idle(uart->oh); |
475 | 406 | ||
476 | omap_device_enable(uart->pdev); | 407 | omap_device_enable(uart->pdev); |
477 | omap_uart_idle_init(uart); | ||
478 | omap_hwmod_enable_wakeup(uart->oh); | ||
479 | omap_device_idle(uart->pdev); | 408 | omap_device_idle(uart->pdev); |
480 | 409 | ||
481 | omap_uart_block_sleep(uart); | 410 | omap_uart_block_sleep(uart); |
482 | console_unlock(); | 411 | console_unlock(); |
483 | 412 | ||
484 | if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) || | 413 | if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) |
485 | (pdata->wk_en && pdata->wk_mask)) | ||
486 | device_init_wakeup(&pdev->dev, true); | 414 | device_init_wakeup(&pdev->dev, true); |
487 | } | 415 | } |
488 | 416 | ||
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 842b429cfeaa..39709ecfd58f 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h | |||
@@ -70,6 +70,7 @@ struct omap_uart_port_info { | |||
70 | int (*get_context_loss_count)(struct device *); | 70 | int (*get_context_loss_count)(struct device *); |
71 | void (*set_forceidle)(struct platform_device *); | 71 | void (*set_forceidle)(struct platform_device *); |
72 | void (*set_noidle)(struct platform_device *); | 72 | void (*set_noidle)(struct platform_device *); |
73 | void (*enable_wakeup)(struct platform_device *, bool); | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | struct uart_omap_dma { | 76 | struct uart_omap_dma { |
@@ -124,6 +125,7 @@ struct uart_omap_port { | |||
124 | unsigned long port_activity; | 125 | unsigned long port_activity; |
125 | u32 context_loss_cnt; | 126 | u32 context_loss_cnt; |
126 | u32 errata; | 127 | u32 errata; |
128 | u8 wakeups_enabled; | ||
127 | }; | 129 | }; |
128 | 130 | ||
129 | #endif /* __OMAP_SERIAL_H__ */ | 131 | #endif /* __OMAP_SERIAL_H__ */ |