]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/serial.c
OMAP3: PM: UART: disable clocks when idle
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / serial.c
1 /*
2  * arch/arm/mach-omap2/serial.c
3  *
4  * OMAP2 serial support.
5  *
6  * Copyright (C) 2005-2008 Nokia Corporation
7  * Author: Paul Mundt <paul.mundt@nokia.com>
8  *
9  * Major rework for PM support by Kevin Hilman
10  *
11  * Based off of arch/arm/mach-omap/omap1/serial.c
12  *
13  * This file is subject to the terms and conditions of the GNU General Public
14  * License. See the file "COPYING" in the main directory of this archive
15  * for more details.
16  */
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/serial_8250.h>
20 #include <linux/serial_reg.h>
21 #include <linux/clk.h>
22 #include <linux/io.h>
23
24 #include <mach/common.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 DEFAULT_TIMEOUT (2 * HZ)
34
35 struct omap_uart_state {
36         int num;
37         int can_sleep;
38         struct timer_list timer;
39         u32 timeout;
40
41         void __iomem *wk_st;
42         void __iomem *wk_en;
43         u32 wk_mask;
44         u32 padconf;
45
46         struct clk *ick;
47         struct clk *fck;
48         int clocked;
49
50         struct plat_serial8250_port *p;
51         struct list_head node;
52 };
53
54 static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS];
55 static LIST_HEAD(uart_list);
56
57 static struct plat_serial8250_port serial_platform_data[] = {
58         {
59                 .membase        = IO_ADDRESS(OMAP_UART1_BASE),
60                 .mapbase        = OMAP_UART1_BASE,
61                 .irq            = 72,
62                 .flags          = UPF_BOOT_AUTOCONF,
63                 .iotype         = UPIO_MEM,
64                 .regshift       = 2,
65                 .uartclk        = OMAP24XX_BASE_BAUD * 16,
66         }, {
67                 .membase        = IO_ADDRESS(OMAP_UART2_BASE),
68                 .mapbase        = OMAP_UART2_BASE,
69                 .irq            = 73,
70                 .flags          = UPF_BOOT_AUTOCONF,
71                 .iotype         = UPIO_MEM,
72                 .regshift       = 2,
73                 .uartclk        = OMAP24XX_BASE_BAUD * 16,
74         }, {
75                 .membase        = IO_ADDRESS(OMAP_UART3_BASE),
76                 .mapbase        = OMAP_UART3_BASE,
77                 .irq            = 74,
78                 .flags          = UPF_BOOT_AUTOCONF,
79                 .iotype         = UPIO_MEM,
80                 .regshift       = 2,
81                 .uartclk        = OMAP24XX_BASE_BAUD * 16,
82         }, {
83                 .flags          = 0
84         }
85 };
86
87 static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
88                                            int offset)
89 {
90         offset <<= up->regshift;
91         return (unsigned int)__raw_readb(up->membase + offset);
92 }
93
94 static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
95                                     int value)
96 {
97         offset <<= p->regshift;
98         __raw_writeb(value, p->membase + offset);
99 }
100
101 /*
102  * Internal UARTs need to be initialized for the 8250 autoconfig to work
103  * properly. Note that the TX watermark initialization may not be needed
104  * once the 8250.c watermark handling code is merged.
105  */
106 static inline void __init omap_uart_reset(struct omap_uart_state *uart)
107 {
108         struct plat_serial8250_port *p = uart->p;
109
110         serial_write_reg(p, UART_OMAP_MDR1, 0x07);
111         serial_write_reg(p, UART_OMAP_SCR, 0x08);
112         serial_write_reg(p, UART_OMAP_MDR1, 0x00);
113         serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
114 }
115
116 #ifdef CONFIG_PM
117 static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
118                                           int enable)
119 {
120         struct plat_serial8250_port *p = uart->p;
121         u16 sysc;
122
123         sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
124         if (enable)
125                 sysc |= 0x2 << 3;
126         else
127                 sysc |= 0x1 << 3;
128
129         serial_write_reg(p, UART_OMAP_SYSC, sysc);
130 }
131
132 static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
133 {
134         if (uart->clocked)
135                 return;
136
137         clk_enable(uart->ick);
138         clk_enable(uart->fck);
139         uart->clocked = 1;
140 }
141
142 static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
143 {
144         if (!uart->clocked)
145                 return;
146
147         uart->clocked = 0;
148         clk_disable(uart->ick);
149         clk_disable(uart->fck);
150 }
151
152 static void omap_uart_block_sleep(struct omap_uart_state *uart)
153 {
154         omap_uart_enable_clocks(uart);
155
156         omap_uart_smart_idle_enable(uart, 0);
157         uart->can_sleep = 0;
158         mod_timer(&uart->timer, jiffies + uart->timeout);
159 }
160
161 static void omap_uart_allow_sleep(struct omap_uart_state *uart)
162 {
163         if (!uart->clocked)
164                 return;
165
166         omap_uart_smart_idle_enable(uart, 1);
167         uart->can_sleep = 1;
168         del_timer(&uart->timer);
169 }
170
171 static void omap_uart_idle_timer(unsigned long data)
172 {
173         struct omap_uart_state *uart = (struct omap_uart_state *)data;
174
175         omap_uart_allow_sleep(uart);
176 }
177
178 void omap_uart_prepare_idle(int num)
179 {
180         struct omap_uart_state *uart;
181
182         list_for_each_entry(uart, &uart_list, node) {
183                 if (!clocks_off_while_idle)
184                         continue;
185
186                 if (num == uart->num && uart->can_sleep) {
187                         omap_uart_disable_clocks(uart);
188                         return;
189                 }
190         }
191 }
192
193 void omap_uart_resume_idle(int num)
194 {
195         struct omap_uart_state *uart;
196
197         list_for_each_entry(uart, &uart_list, node) {
198                 if (num == uart->num) {
199                         omap_uart_enable_clocks(uart);
200
201                         /* Check for IO pad wakeup */
202                         if (cpu_is_omap34xx() && uart->padconf) {
203                                 u16 p = omap_ctrl_readw(uart->padconf);
204
205                                 if (p & OMAP3_PADCONF_WAKEUPEVENT0)
206                                         omap_uart_block_sleep(uart);
207                         }
208
209                         /* Check for normal UART wakeup */
210                         if (__raw_readl(uart->wk_st) & uart->wk_mask)
211                                 omap_uart_block_sleep(uart);
212
213                         return;
214                 }
215         }
216 }
217
218 void omap_uart_prepare_suspend(void)
219 {
220         struct omap_uart_state *uart;
221
222         list_for_each_entry(uart, &uart_list, node) {
223                 omap_uart_allow_sleep(uart);
224         }
225 }
226
227 int omap_uart_can_sleep(void)
228 {
229         struct omap_uart_state *uart;
230         int can_sleep = 1;
231
232         list_for_each_entry(uart, &uart_list, node) {
233                 if (!uart->clocked)
234                         continue;
235
236                 if (!uart->can_sleep) {
237                         can_sleep = 0;
238                         continue;
239                 }
240
241                 /* This UART can now safely sleep. */
242                 omap_uart_allow_sleep(uart);
243         }
244
245         return can_sleep;
246 }
247
248 /**
249  * omap_uart_interrupt()
250  *
251  * This handler is used only to detect that *any* UART interrupt has
252  * occurred.  It does _nothing_ to handle the interrupt.  Rather,
253  * any UART interrupt will trigger the inactivity timer so the
254  * UART will not idle or sleep for its timeout period.
255  *
256  **/
257 static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
258 {
259         struct omap_uart_state *uart = dev_id;
260
261         omap_uart_block_sleep(uart);
262
263         return IRQ_NONE;
264 }
265
266 static void omap_uart_idle_init(struct omap_uart_state *uart)
267 {
268         u32 v;
269         struct plat_serial8250_port *p = uart->p;
270         int ret;
271
272         uart->can_sleep = 0;
273         uart->timeout = DEFAULT_TIMEOUT;
274         setup_timer(&uart->timer, omap_uart_idle_timer,
275                     (unsigned long) uart);
276         mod_timer(&uart->timer, jiffies + uart->timeout);
277         omap_uart_smart_idle_enable(uart, 0);
278
279         if (cpu_is_omap34xx()) {
280                 u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
281                 u32 wk_mask = 0;
282                 u32 padconf = 0;
283
284                 uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
285                 uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
286                 switch (uart->num) {
287                 case 0:
288                         wk_mask = OMAP3430_ST_UART1_MASK;
289                         padconf = 0x182;
290                         break;
291                 case 1:
292                         wk_mask = OMAP3430_ST_UART2_MASK;
293                         padconf = 0x17a;
294                         break;
295                 case 2:
296                         wk_mask = OMAP3430_ST_UART3_MASK;
297                         padconf = 0x19e;
298                         break;
299                 }
300                 uart->wk_mask = wk_mask;
301                 uart->padconf = padconf;
302         } else if (cpu_is_omap24xx()) {
303                 u32 wk_mask = 0;
304
305                 if (cpu_is_omap2430()) {
306                         uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
307                         uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
308                 } else if (cpu_is_omap2420()) {
309                         uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
310                         uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
311                 }
312                 switch (uart->num) {
313                 case 0:
314                         wk_mask = OMAP24XX_ST_UART1_MASK;
315                         break;
316                 case 1:
317                         wk_mask = OMAP24XX_ST_UART2_MASK;
318                         break;
319                 case 2:
320                         wk_mask = OMAP24XX_ST_UART3_MASK;
321                         break;
322                 }
323                 uart->wk_mask = wk_mask;
324         } else {
325                 uart->wk_en = 0;
326                 uart->wk_st = 0;
327                 uart->wk_mask = 0;
328                 uart->padconf = 0;
329         }
330
331         /* Set wake-enable bit */
332         if (uart->wk_en && uart->wk_mask) {
333                 v = __raw_readl(uart->wk_en);
334                 v |= uart->wk_mask;
335                 __raw_writel(v, uart->wk_en);
336         }
337
338         /* Ensure IOPAD wake-enables are set */
339         if (cpu_is_omap34xx() && uart->padconf) {
340                 u16 v;
341
342                 v = omap_ctrl_readw(uart->padconf);
343                 v |= OMAP3_PADCONF_WAKEUPENABLE0;
344                 omap_ctrl_writew(v, uart->padconf);
345         }
346
347         p->flags |= UPF_SHARE_IRQ;
348         ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
349                           "serial idle", (void *)uart);
350         WARN_ON(ret);
351 }
352
353 #else
354 static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
355 #endif /* CONFIG_PM */
356
357 void __init omap_serial_init(void)
358 {
359         int i;
360         const struct omap_uart_config *info;
361         char name[16];
362
363         /*
364          * Make sure the serial ports are muxed on at this point.
365          * You have to mux them off in device drivers later on
366          * if not needed.
367          */
368
369         info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
370
371         if (info == NULL)
372                 return;
373
374         for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
375                 struct plat_serial8250_port *p = serial_platform_data + i;
376                 struct omap_uart_state *uart = &omap_uart[i];
377
378                 if (!(info->enabled_uarts & (1 << i))) {
379                         p->membase = NULL;
380                         p->mapbase = 0;
381                         continue;
382                 }
383
384                 sprintf(name, "uart%d_ick", i+1);
385                 uart->ick = clk_get(NULL, name);
386                 if (IS_ERR(uart->ick)) {
387                         printk(KERN_ERR "Could not get uart%d_ick\n", i+1);
388                         uart->ick = NULL;
389                 }
390
391                 sprintf(name, "uart%d_fck", i+1);
392                 uart->fck = clk_get(NULL, name);
393                 if (IS_ERR(uart->fck)) {
394                         printk(KERN_ERR "Could not get uart%d_fck\n", i+1);
395                         uart->fck = NULL;
396                 }
397
398                 if (!uart->ick || !uart->fck)
399                         continue;
400
401                 uart->num = i;
402                 p->private_data = uart;
403                 uart->p = p;
404                 list_add(&uart->node, &uart_list);
405
406                 omap_uart_enable_clocks(uart);
407                 omap_uart_reset(uart);
408                 omap_uart_idle_init(uart);
409         }
410 }
411
412 static struct platform_device serial_device = {
413         .name                   = "serial8250",
414         .id                     = PLAT8250_DEV_PLATFORM,
415         .dev                    = {
416                 .platform_data  = serial_platform_data,
417         },
418 };
419
420 static int __init omap_init(void)
421 {
422         return platform_device_register(&serial_device);
423 }
424 arch_initcall(omap_init);