diff options
-rw-r--r-- | arch/arm/mach-omap2/pm24xx.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-omap2/serial.c | 390 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/mach/common.h | 2 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/mach/serial.h | 9 |
5 files changed, 405 insertions, 27 deletions
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index d38f3121dde9..db1025562fb0 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c | |||
@@ -71,6 +71,11 @@ static int omap2_fclks_active(void) | |||
71 | 71 | ||
72 | f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); | 72 | f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); |
73 | f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2); | 73 | f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2); |
74 | |||
75 | /* Ignore UART clocks. These are handled by UART core (serial.c) */ | ||
76 | f1 &= ~(OMAP24XX_EN_UART1 | OMAP24XX_EN_UART2); | ||
77 | f2 &= ~OMAP24XX_EN_UART3; | ||
78 | |||
74 | if (f1 | f2) | 79 | if (f1 | f2) |
75 | return 1; | 80 | return 1; |
76 | return 0; | 81 | return 0; |
@@ -117,12 +122,20 @@ static void omap2_enter_full_retention(void) | |||
117 | if (omap_irq_pending()) | 122 | if (omap_irq_pending()) |
118 | goto no_sleep; | 123 | goto no_sleep; |
119 | 124 | ||
125 | omap_uart_prepare_idle(0); | ||
126 | omap_uart_prepare_idle(1); | ||
127 | omap_uart_prepare_idle(2); | ||
128 | |||
120 | /* Jump to SRAM suspend code */ | 129 | /* Jump to SRAM suspend code */ |
121 | omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL), | 130 | omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL), |
122 | OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL), | 131 | OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL), |
123 | OMAP_SDRC_REGADDR(SDRC_POWER)); | 132 | OMAP_SDRC_REGADDR(SDRC_POWER)); |
124 | no_sleep: | ||
125 | 133 | ||
134 | omap_uart_resume_idle(2); | ||
135 | omap_uart_resume_idle(1); | ||
136 | omap_uart_resume_idle(0); | ||
137 | |||
138 | no_sleep: | ||
126 | if (omap2_pm_debug) { | 139 | if (omap2_pm_debug) { |
127 | unsigned long long tmp; | 140 | unsigned long long tmp; |
128 | 141 | ||
@@ -283,6 +296,7 @@ static int omap2_pm_suspend(void) | |||
283 | mir1 = omap_readl(0x480fe0a4); | 296 | mir1 = omap_readl(0x480fe0a4); |
284 | omap_writel(1 << 5, 0x480fe0ac); | 297 | omap_writel(1 << 5, 0x480fe0ac); |
285 | 298 | ||
299 | omap_uart_prepare_suspend(); | ||
286 | omap2_enter_full_retention(); | 300 | omap2_enter_full_retention(); |
287 | 301 | ||
288 | omap_writel(mir1, 0x480fe0a4); | 302 | omap_writel(mir1, 0x480fe0a4); |
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index b2a8730771e9..54876aca2d45 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <mach/clockdomain.h> | 27 | #include <mach/clockdomain.h> |
28 | #include <mach/powerdomain.h> | 28 | #include <mach/powerdomain.h> |
29 | #include <mach/control.h> | 29 | #include <mach/control.h> |
30 | #include <mach/serial.h> | ||
30 | 31 | ||
31 | #include "cm.h" | 32 | #include "cm.h" |
32 | #include "cm-regbits-34xx.h" | 33 | #include "cm-regbits-34xx.h" |
@@ -168,10 +169,16 @@ static void omap_sram_idle(void) | |||
168 | return; | 169 | return; |
169 | } | 170 | } |
170 | omap2_gpio_prepare_for_retention(); | 171 | omap2_gpio_prepare_for_retention(); |
172 | omap_uart_prepare_idle(0); | ||
173 | omap_uart_prepare_idle(1); | ||
174 | omap_uart_prepare_idle(2); | ||
171 | 175 | ||
172 | _omap_sram_idle(NULL, save_state); | 176 | _omap_sram_idle(NULL, save_state); |
173 | cpu_init(); | 177 | cpu_init(); |
174 | 178 | ||
179 | omap_uart_resume_idle(2); | ||
180 | omap_uart_resume_idle(1); | ||
181 | omap_uart_resume_idle(0); | ||
175 | omap2_gpio_resume_after_retention(); | 182 | omap2_gpio_resume_after_retention(); |
176 | } | 183 | } |
177 | 184 | ||
@@ -204,6 +211,11 @@ static int omap3_fclks_active(void) | |||
204 | CM_FCLKEN); | 211 | CM_FCLKEN); |
205 | fck_per = cm_read_mod_reg(OMAP3430_PER_MOD, | 212 | fck_per = cm_read_mod_reg(OMAP3430_PER_MOD, |
206 | CM_FCLKEN); | 213 | CM_FCLKEN); |
214 | |||
215 | /* Ignore UART clocks. These are handled by UART core (serial.c) */ | ||
216 | fck_core1 &= ~(OMAP3430_EN_UART1 | OMAP3430_EN_UART2); | ||
217 | fck_per &= ~OMAP3430_EN_UART3; | ||
218 | |||
207 | if (fck_core1 | fck_core3 | fck_sgx | fck_dss | | 219 | if (fck_core1 | fck_core3 | fck_sgx | fck_dss | |
208 | fck_cam | fck_per | fck_usbhost) | 220 | fck_cam | fck_per | fck_usbhost) |
209 | return 1; | 221 | return 1; |
@@ -212,6 +224,8 @@ static int omap3_fclks_active(void) | |||
212 | 224 | ||
213 | static int omap3_can_sleep(void) | 225 | static int omap3_can_sleep(void) |
214 | { | 226 | { |
227 | if (!omap_uart_can_sleep()) | ||
228 | return 0; | ||
215 | if (omap3_fclks_active()) | 229 | if (omap3_fclks_active()) |
216 | return 0; | 230 | return 0; |
217 | return 1; | 231 | return 1; |
@@ -301,6 +315,7 @@ static int omap3_pm_suspend(void) | |||
301 | goto restore; | 315 | goto restore; |
302 | } | 316 | } |
303 | 317 | ||
318 | omap_uart_prepare_suspend(); | ||
304 | omap_sram_idle(); | 319 | omap_sram_idle(); |
305 | 320 | ||
306 | restore: | 321 | restore: |
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 4dcf39c285b9..53cbe0620286 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * Copyright (C) 2005-2008 Nokia Corporation | 6 | * Copyright (C) 2005-2008 Nokia Corporation |
7 | * Author: Paul Mundt <paul.mundt@nokia.com> | 7 | * Author: Paul Mundt <paul.mundt@nokia.com> |
8 | * | 8 | * |
9 | * Major rework for PM support by Kevin Hilman | ||
10 | * | ||
9 | * Based off of arch/arm/mach-omap/omap1/serial.c | 11 | * Based off of arch/arm/mach-omap/omap1/serial.c |
10 | * | 12 | * |
11 | * This file is subject to the terms and conditions of the GNU General Public | 13 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -21,9 +23,50 @@ | |||
21 | 23 | ||
22 | #include <mach/common.h> | 24 | #include <mach/common.h> |
23 | #include <mach/board.h> | 25 | #include <mach/board.h> |
26 | #include <mach/clock.h> | ||
27 | #include <mach/control.h> | ||
28 | |||
29 | #include "prm.h" | ||
30 | #include "pm.h" | ||
31 | #include "prm-regbits-34xx.h" | ||
32 | |||
33 | #define UART_OMAP_WER 0x17 /* Wake-up enable register */ | ||
34 | |||
35 | #define DEFAULT_TIMEOUT (2 * HZ) | ||
36 | |||
37 | struct omap_uart_state { | ||
38 | int num; | ||
39 | int can_sleep; | ||
40 | struct timer_list timer; | ||
41 | u32 timeout; | ||
42 | |||
43 | void __iomem *wk_st; | ||
44 | void __iomem *wk_en; | ||
45 | u32 wk_mask; | ||
46 | u32 padconf; | ||
47 | |||
48 | struct clk *ick; | ||
49 | struct clk *fck; | ||
50 | int clocked; | ||
51 | |||
52 | struct plat_serial8250_port *p; | ||
53 | struct list_head node; | ||
24 | 54 | ||
25 | static struct clk *uart_ick[OMAP_MAX_NR_PORTS]; | 55 | #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) |
26 | static struct clk *uart_fck[OMAP_MAX_NR_PORTS]; | 56 | int context_valid; |
57 | |||
58 | /* Registers to be saved/restored for OFF-mode */ | ||
59 | u16 dll; | ||
60 | u16 dlh; | ||
61 | u16 ier; | ||
62 | u16 sysc; | ||
63 | u16 scr; | ||
64 | u16 wer; | ||
65 | #endif | ||
66 | }; | ||
67 | |||
68 | static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS]; | ||
69 | static LIST_HEAD(uart_list); | ||
27 | 70 | ||
28 | static struct plat_serial8250_port serial_platform_data[] = { | 71 | static struct plat_serial8250_port serial_platform_data[] = { |
29 | { | 72 | { |
@@ -74,30 +117,320 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, | |||
74 | * properly. Note that the TX watermark initialization may not be needed | 117 | * properly. Note that the TX watermark initialization may not be needed |
75 | * once the 8250.c watermark handling code is merged. | 118 | * once the 8250.c watermark handling code is merged. |
76 | */ | 119 | */ |
77 | static inline void __init omap_serial_reset(struct plat_serial8250_port *p) | 120 | static inline void __init omap_uart_reset(struct omap_uart_state *uart) |
78 | { | 121 | { |
122 | struct plat_serial8250_port *p = uart->p; | ||
123 | |||
79 | serial_write_reg(p, UART_OMAP_MDR1, 0x07); | 124 | serial_write_reg(p, UART_OMAP_MDR1, 0x07); |
80 | serial_write_reg(p, UART_OMAP_SCR, 0x08); | 125 | serial_write_reg(p, UART_OMAP_SCR, 0x08); |
81 | serial_write_reg(p, UART_OMAP_MDR1, 0x00); | 126 | serial_write_reg(p, UART_OMAP_MDR1, 0x00); |
82 | serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0)); | 127 | serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0)); |
83 | } | 128 | } |
84 | 129 | ||
85 | void omap_serial_enable_clocks(int enable) | 130 | #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) |
131 | |||
132 | static int enable_off_mode; /* to be removed by full off-mode patches */ | ||
133 | |||
134 | static void omap_uart_save_context(struct omap_uart_state *uart) | ||
86 | { | 135 | { |
87 | int i; | 136 | u16 lcr = 0; |
88 | for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { | 137 | struct plat_serial8250_port *p = uart->p; |
89 | if (uart_ick[i] && uart_fck[i]) { | 138 | |
90 | if (enable) { | 139 | if (!enable_off_mode) |
91 | clk_enable(uart_ick[i]); | 140 | return; |
92 | clk_enable(uart_fck[i]); | 141 | |
93 | } else { | 142 | lcr = serial_read_reg(p, UART_LCR); |
94 | clk_disable(uart_ick[i]); | 143 | serial_write_reg(p, UART_LCR, 0xBF); |
95 | clk_disable(uart_fck[i]); | 144 | uart->dll = serial_read_reg(p, UART_DLL); |
145 | uart->dlh = serial_read_reg(p, UART_DLM); | ||
146 | serial_write_reg(p, UART_LCR, lcr); | ||
147 | uart->ier = serial_read_reg(p, UART_IER); | ||
148 | uart->sysc = serial_read_reg(p, UART_OMAP_SYSC); | ||
149 | uart->scr = serial_read_reg(p, UART_OMAP_SCR); | ||
150 | uart->wer = serial_read_reg(p, UART_OMAP_WER); | ||
151 | |||
152 | uart->context_valid = 1; | ||
153 | } | ||
154 | |||
155 | static void omap_uart_restore_context(struct omap_uart_state *uart) | ||
156 | { | ||
157 | u16 efr = 0; | ||
158 | struct plat_serial8250_port *p = uart->p; | ||
159 | |||
160 | if (!enable_off_mode) | ||
161 | return; | ||
162 | |||
163 | if (!uart->context_valid) | ||
164 | return; | ||
165 | |||
166 | uart->context_valid = 0; | ||
167 | |||
168 | serial_write_reg(p, UART_OMAP_MDR1, 0x7); | ||
169 | serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ | ||
170 | efr = serial_read_reg(p, UART_EFR); | ||
171 | serial_write_reg(p, UART_EFR, UART_EFR_ECB); | ||
172 | serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ | ||
173 | serial_write_reg(p, UART_IER, 0x0); | ||
174 | serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ | ||
175 | serial_write_reg(p, UART_DLL, uart->dll); | ||
176 | serial_write_reg(p, UART_DLM, uart->dlh); | ||
177 | serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ | ||
178 | serial_write_reg(p, UART_IER, uart->ier); | ||
179 | serial_write_reg(p, UART_FCR, 0xA1); | ||
180 | serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ | ||
181 | serial_write_reg(p, UART_EFR, efr); | ||
182 | serial_write_reg(p, UART_LCR, UART_LCR_WLEN8); | ||
183 | serial_write_reg(p, UART_OMAP_SCR, uart->scr); | ||
184 | serial_write_reg(p, UART_OMAP_WER, uart->wer); | ||
185 | serial_write_reg(p, UART_OMAP_SYSC, uart->sysc); | ||
186 | serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */ | ||
187 | } | ||
188 | #else | ||
189 | static inline void omap_uart_save_context(struct omap_uart_state *uart) {} | ||
190 | static inline void omap_uart_restore_context(struct omap_uart_state *uart) {} | ||
191 | #endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */ | ||
192 | |||
193 | static inline void omap_uart_enable_clocks(struct omap_uart_state *uart) | ||
194 | { | ||
195 | if (uart->clocked) | ||
196 | return; | ||
197 | |||
198 | clk_enable(uart->ick); | ||
199 | clk_enable(uart->fck); | ||
200 | uart->clocked = 1; | ||
201 | omap_uart_restore_context(uart); | ||
202 | } | ||
203 | |||
204 | #ifdef CONFIG_PM | ||
205 | |||
206 | static inline void omap_uart_disable_clocks(struct omap_uart_state *uart) | ||
207 | { | ||
208 | if (!uart->clocked) | ||
209 | return; | ||
210 | |||
211 | omap_uart_save_context(uart); | ||
212 | uart->clocked = 0; | ||
213 | clk_disable(uart->ick); | ||
214 | clk_disable(uart->fck); | ||
215 | } | ||
216 | |||
217 | static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, | ||
218 | int enable) | ||
219 | { | ||
220 | struct plat_serial8250_port *p = uart->p; | ||
221 | u16 sysc; | ||
222 | |||
223 | sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7; | ||
224 | if (enable) | ||
225 | sysc |= 0x2 << 3; | ||
226 | else | ||
227 | sysc |= 0x1 << 3; | ||
228 | |||
229 | serial_write_reg(p, UART_OMAP_SYSC, sysc); | ||
230 | } | ||
231 | |||
232 | static void omap_uart_block_sleep(struct omap_uart_state *uart) | ||
233 | { | ||
234 | omap_uart_enable_clocks(uart); | ||
235 | |||
236 | omap_uart_smart_idle_enable(uart, 0); | ||
237 | uart->can_sleep = 0; | ||
238 | mod_timer(&uart->timer, jiffies + uart->timeout); | ||
239 | } | ||
240 | |||
241 | static void omap_uart_allow_sleep(struct omap_uart_state *uart) | ||
242 | { | ||
243 | if (!uart->clocked) | ||
244 | return; | ||
245 | |||
246 | omap_uart_smart_idle_enable(uart, 1); | ||
247 | uart->can_sleep = 1; | ||
248 | del_timer(&uart->timer); | ||
249 | } | ||
250 | |||
251 | static void omap_uart_idle_timer(unsigned long data) | ||
252 | { | ||
253 | struct omap_uart_state *uart = (struct omap_uart_state *)data; | ||
254 | |||
255 | omap_uart_allow_sleep(uart); | ||
256 | } | ||
257 | |||
258 | void omap_uart_prepare_idle(int num) | ||
259 | { | ||
260 | struct omap_uart_state *uart; | ||
261 | |||
262 | list_for_each_entry(uart, &uart_list, node) { | ||
263 | if (num == uart->num && uart->can_sleep) { | ||
264 | omap_uart_disable_clocks(uart); | ||
265 | return; | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | |||
270 | void omap_uart_resume_idle(int num) | ||
271 | { | ||
272 | struct omap_uart_state *uart; | ||
273 | |||
274 | list_for_each_entry(uart, &uart_list, node) { | ||
275 | if (num == uart->num) { | ||
276 | omap_uart_enable_clocks(uart); | ||
277 | |||
278 | /* Check for IO pad wakeup */ | ||
279 | if (cpu_is_omap34xx() && uart->padconf) { | ||
280 | u16 p = omap_ctrl_readw(uart->padconf); | ||
281 | |||
282 | if (p & OMAP3_PADCONF_WAKEUPEVENT0) | ||
283 | omap_uart_block_sleep(uart); | ||
96 | } | 284 | } |
285 | |||
286 | /* Check for normal UART wakeup */ | ||
287 | if (__raw_readl(uart->wk_st) & uart->wk_mask) | ||
288 | omap_uart_block_sleep(uart); | ||
289 | |||
290 | return; | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | |||
295 | void omap_uart_prepare_suspend(void) | ||
296 | { | ||
297 | struct omap_uart_state *uart; | ||
298 | |||
299 | list_for_each_entry(uart, &uart_list, node) { | ||
300 | omap_uart_allow_sleep(uart); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | int omap_uart_can_sleep(void) | ||
305 | { | ||
306 | struct omap_uart_state *uart; | ||
307 | int can_sleep = 1; | ||
308 | |||
309 | list_for_each_entry(uart, &uart_list, node) { | ||
310 | if (!uart->clocked) | ||
311 | continue; | ||
312 | |||
313 | if (!uart->can_sleep) { | ||
314 | can_sleep = 0; | ||
315 | continue; | ||
97 | } | 316 | } |
317 | |||
318 | /* This UART can now safely sleep. */ | ||
319 | omap_uart_allow_sleep(uart); | ||
98 | } | 320 | } |
321 | |||
322 | return can_sleep; | ||
99 | } | 323 | } |
100 | 324 | ||
325 | /** | ||
326 | * omap_uart_interrupt() | ||
327 | * | ||
328 | * This handler is used only to detect that *any* UART interrupt has | ||
329 | * occurred. It does _nothing_ to handle the interrupt. Rather, | ||
330 | * any UART interrupt will trigger the inactivity timer so the | ||
331 | * UART will not idle or sleep for its timeout period. | ||
332 | * | ||
333 | **/ | ||
334 | static irqreturn_t omap_uart_interrupt(int irq, void *dev_id) | ||
335 | { | ||
336 | struct omap_uart_state *uart = dev_id; | ||
337 | |||
338 | omap_uart_block_sleep(uart); | ||
339 | |||
340 | return IRQ_NONE; | ||
341 | } | ||
342 | |||
343 | static void omap_uart_idle_init(struct omap_uart_state *uart) | ||
344 | { | ||
345 | u32 v; | ||
346 | struct plat_serial8250_port *p = uart->p; | ||
347 | int ret; | ||
348 | |||
349 | uart->can_sleep = 0; | ||
350 | uart->timeout = DEFAULT_TIMEOUT; | ||
351 | setup_timer(&uart->timer, omap_uart_idle_timer, | ||
352 | (unsigned long) uart); | ||
353 | mod_timer(&uart->timer, jiffies + uart->timeout); | ||
354 | omap_uart_smart_idle_enable(uart, 0); | ||
355 | |||
356 | if (cpu_is_omap34xx()) { | ||
357 | u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD; | ||
358 | u32 wk_mask = 0; | ||
359 | u32 padconf = 0; | ||
360 | |||
361 | uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1); | ||
362 | uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1); | ||
363 | switch (uart->num) { | ||
364 | case 0: | ||
365 | wk_mask = OMAP3430_ST_UART1_MASK; | ||
366 | padconf = 0x182; | ||
367 | break; | ||
368 | case 1: | ||
369 | wk_mask = OMAP3430_ST_UART2_MASK; | ||
370 | padconf = 0x17a; | ||
371 | break; | ||
372 | case 2: | ||
373 | wk_mask = OMAP3430_ST_UART3_MASK; | ||
374 | padconf = 0x19e; | ||
375 | break; | ||
376 | } | ||
377 | uart->wk_mask = wk_mask; | ||
378 | uart->padconf = padconf; | ||
379 | } else if (cpu_is_omap24xx()) { | ||
380 | u32 wk_mask = 0; | ||
381 | |||
382 | if (cpu_is_omap2430()) { | ||
383 | uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1); | ||
384 | uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1); | ||
385 | } else if (cpu_is_omap2420()) { | ||
386 | uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1); | ||
387 | uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1); | ||
388 | } | ||
389 | switch (uart->num) { | ||
390 | case 0: | ||
391 | wk_mask = OMAP24XX_ST_UART1_MASK; | ||
392 | break; | ||
393 | case 1: | ||
394 | wk_mask = OMAP24XX_ST_UART2_MASK; | ||
395 | break; | ||
396 | case 2: | ||
397 | wk_mask = OMAP24XX_ST_UART3_MASK; | ||
398 | break; | ||
399 | } | ||
400 | uart->wk_mask = wk_mask; | ||
401 | } else { | ||
402 | uart->wk_en = 0; | ||
403 | uart->wk_st = 0; | ||
404 | uart->wk_mask = 0; | ||
405 | uart->padconf = 0; | ||
406 | } | ||
407 | |||
408 | /* Set wake-enable bit */ | ||
409 | if (uart->wk_en && uart->wk_mask) { | ||
410 | v = __raw_readl(uart->wk_en); | ||
411 | v |= uart->wk_mask; | ||
412 | __raw_writel(v, uart->wk_en); | ||
413 | } | ||
414 | |||
415 | /* Ensure IOPAD wake-enables are set */ | ||
416 | if (cpu_is_omap34xx() && uart->padconf) { | ||
417 | u16 v; | ||
418 | |||
419 | v = omap_ctrl_readw(uart->padconf); | ||
420 | v |= OMAP3_PADCONF_WAKEUPENABLE0; | ||
421 | omap_ctrl_writew(v, uart->padconf); | ||
422 | } | ||
423 | |||
424 | p->flags |= UPF_SHARE_IRQ; | ||
425 | ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED, | ||
426 | "serial idle", (void *)uart); | ||
427 | WARN_ON(ret); | ||
428 | } | ||
429 | |||
430 | #else | ||
431 | static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} | ||
432 | #endif /* CONFIG_PM */ | ||
433 | |||
101 | void __init omap_serial_init(void) | 434 | void __init omap_serial_init(void) |
102 | { | 435 | { |
103 | int i; | 436 | int i; |
@@ -117,6 +450,7 @@ void __init omap_serial_init(void) | |||
117 | 450 | ||
118 | for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { | 451 | for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { |
119 | struct plat_serial8250_port *p = serial_platform_data + i; | 452 | struct plat_serial8250_port *p = serial_platform_data + i; |
453 | struct omap_uart_state *uart = &omap_uart[i]; | ||
120 | 454 | ||
121 | if (!(info->enabled_uarts & (1 << i))) { | 455 | if (!(info->enabled_uarts & (1 << i))) { |
122 | p->membase = NULL; | 456 | p->membase = NULL; |
@@ -125,22 +459,30 @@ void __init omap_serial_init(void) | |||
125 | } | 459 | } |
126 | 460 | ||
127 | sprintf(name, "uart%d_ick", i+1); | 461 | sprintf(name, "uart%d_ick", i+1); |
128 | uart_ick[i] = clk_get(NULL, name); | 462 | uart->ick = clk_get(NULL, name); |
129 | if (IS_ERR(uart_ick[i])) { | 463 | if (IS_ERR(uart->ick)) { |
130 | printk(KERN_ERR "Could not get uart%d_ick\n", i+1); | 464 | printk(KERN_ERR "Could not get uart%d_ick\n", i+1); |
131 | uart_ick[i] = NULL; | 465 | uart->ick = NULL; |
132 | } else | 466 | } |
133 | clk_enable(uart_ick[i]); | ||
134 | 467 | ||
135 | sprintf(name, "uart%d_fck", i+1); | 468 | sprintf(name, "uart%d_fck", i+1); |
136 | uart_fck[i] = clk_get(NULL, name); | 469 | uart->fck = clk_get(NULL, name); |
137 | if (IS_ERR(uart_fck[i])) { | 470 | if (IS_ERR(uart->fck)) { |
138 | printk(KERN_ERR "Could not get uart%d_fck\n", i+1); | 471 | printk(KERN_ERR "Could not get uart%d_fck\n", i+1); |
139 | uart_fck[i] = NULL; | 472 | uart->fck = NULL; |
140 | } else | 473 | } |
141 | clk_enable(uart_fck[i]); | 474 | |
475 | if (!uart->ick || !uart->fck) | ||
476 | continue; | ||
477 | |||
478 | uart->num = i; | ||
479 | p->private_data = uart; | ||
480 | uart->p = p; | ||
481 | list_add(&uart->node, &uart_list); | ||
142 | 482 | ||
143 | omap_serial_reset(p); | 483 | omap_uart_enable_clocks(uart); |
484 | omap_uart_reset(uart); | ||
485 | omap_uart_idle_init(uart); | ||
144 | } | 486 | } |
145 | } | 487 | } |
146 | 488 | ||
diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h index 0ecf36deb17b..834f0b3aad18 100644 --- a/arch/arm/plat-omap/include/mach/common.h +++ b/arch/arm/plat-omap/include/mach/common.h | |||
@@ -33,8 +33,6 @@ struct sys_timer; | |||
33 | 33 | ||
34 | extern void omap_map_common_io(void); | 34 | extern void omap_map_common_io(void); |
35 | extern struct sys_timer omap_timer; | 35 | extern struct sys_timer omap_timer; |
36 | extern void omap_serial_init(void); | ||
37 | extern void omap_serial_enable_clocks(int enable); | ||
38 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) | 36 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) |
39 | extern int omap_register_i2c_bus(int bus_id, u32 clkrate, | 37 | extern int omap_register_i2c_bus(int bus_id, u32 clkrate, |
40 | struct i2c_board_info const *info, | 38 | struct i2c_board_info const *info, |
diff --git a/arch/arm/plat-omap/include/mach/serial.h b/arch/arm/plat-omap/include/mach/serial.h index 8a676a04be48..8e895858b3e3 100644 --- a/arch/arm/plat-omap/include/mach/serial.h +++ b/arch/arm/plat-omap/include/mach/serial.h | |||
@@ -40,4 +40,13 @@ | |||
40 | __ret; \ | 40 | __ret; \ |
41 | }) | 41 | }) |
42 | 42 | ||
43 | #ifndef __ASSEMBLER__ | ||
44 | extern void omap_serial_init(void); | ||
45 | extern int omap_uart_can_sleep(void); | ||
46 | extern void omap_uart_check_wakeup(void); | ||
47 | extern void omap_uart_prepare_suspend(void); | ||
48 | extern void omap_uart_prepare_idle(int num); | ||
49 | extern void omap_uart_resume_idle(int num); | ||
50 | #endif | ||
51 | |||
43 | #endif | 52 | #endif |