]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/pm-debug.c
24XX: PM: Move debugging related code to pm-debug.c
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / pm-debug.c
1 /*
2  * linux/arch/arm/mach-omap2/pm_debug.c
3  *
4  * OMAP Power Management debug routines
5  *
6  * Copyright (C) 2005 Texas Instruments, Inc.
7  * Copyright (C) 2006-2008 Nokia Corporation
8  *
9  * Written by:
10  * Richard Woodruff <r-woodruff2@ti.com>
11  * Tony Lindgren
12  * Juha Yrjola
13  * Amit Kucheria <amit.kucheria@nokia.com>
14  * Igor Stoppa <igor.stoppa@nokia.com>
15  * Jouni Hogander
16  *
17  * Based on pm.c for omap2
18  *
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License version 2 as
21  * published by the Free Software Foundation.
22  */
23
24 #include <linux/clk.h>
25 #include <linux/err.h>
26
27 #include <asm/arch/clock.h>
28 #include <asm/arch/board.h>
29
30 #include "prm.h"
31 #include "pm.h"
32
33 #ifdef CONFIG_PM_DEBUG
34 int omap2_pm_debug = 0;
35
36 static int serial_console_clock_disabled;
37 static int serial_console_uart;
38 static unsigned int serial_console_next_disable;
39
40 static struct clk *console_iclk, *console_fclk;
41
42 static void serial_console_kick(void)
43 {
44         serial_console_next_disable = omap2_read_32k_sync_counter();
45         /* Keep the clocks on for 4 secs */
46         serial_console_next_disable += 4 * 32768;
47 }
48
49 static void serial_wait_tx(void)
50 {
51         static const unsigned long uart_bases[3] = {
52                 0x4806a000, 0x4806c000, 0x4806e000
53         };
54         unsigned long lsr_reg;
55         int looped = 0;
56
57         /* Wait for TX FIFO and THR to get empty */
58         lsr_reg = IO_ADDRESS(uart_bases[serial_console_uart - 1] + (5 << 2));
59         while ((__raw_readb(lsr_reg) & 0x60) != 0x60)
60                 looped = 1;
61         if (looped)
62                 serial_console_kick();
63 }
64
65 u32 omap2_read_32k_sync_counter(void)
66 {
67         return omap_readl(OMAP2_32KSYNCT_BASE + 0x0010);
68 }
69
70 void serial_console_fclk_mask(u32 *f1, u32 *f2)
71 {
72         switch (serial_console_uart)  {
73         case 1:
74                 *f1 &= ~(1 << 21);
75                 break;
76         case 2:
77                 *f1 &= ~(1 << 22);
78                 break;
79         case 3:
80                 *f2 &= ~(1 << 2);
81                 break;
82         }
83 }
84
85 void serial_console_sleep(int enable)
86 {
87         if (console_iclk == NULL || console_fclk == NULL)
88                 return;
89
90         if (enable) {
91                 BUG_ON(serial_console_clock_disabled);
92                 if (clk_get_usecount(console_fclk) == 0)
93                         return;
94                 if ((int) serial_console_next_disable - (int) omap2_read_32k_sync_counter() >= 0)
95                         return;
96                 serial_wait_tx();
97                 clk_disable(console_iclk);
98                 clk_disable(console_fclk);
99                 serial_console_clock_disabled = 1;
100         } else {
101                 int serial_wakeup = 0;
102                 u32 l;
103
104                 switch (serial_console_uart)  {
105                 case 1:
106                         l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
107                         if (l & OMAP24XX_ST_UART1)
108                                 serial_wakeup = 1;
109                         break;
110                 case 2:
111                         l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
112                         if (l & OMAP24XX_ST_UART2)
113                                 serial_wakeup = 1;
114                         break;
115                 case 3:
116                         l = prm_read_mod_reg(CORE_MOD, OMAP24XX_PM_WKST2);
117                         if (l & OMAP24XX_ST_UART3)
118                                 serial_wakeup = 1;
119                         break;
120                 }
121                 if (serial_wakeup)
122                         serial_console_kick();
123                 if (!serial_console_clock_disabled)
124                         return;
125                 clk_enable(console_iclk);
126                 clk_enable(console_fclk);
127                 serial_console_clock_disabled = 0;
128         }
129 }
130
131 void pm_init_serial_console(void)
132 {
133         const struct omap_serial_console_config *conf;
134         char name[16];
135
136         conf = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
137                                struct omap_serial_console_config);
138         if (conf == NULL)
139                 return;
140         if (conf->console_uart > 3 || conf->console_uart < 1)
141                 return;
142         serial_console_uart = conf->console_uart;
143         sprintf(name, "uart%d_fck", conf->console_uart);
144         console_fclk = clk_get(NULL, name);
145         if (IS_ERR(console_fclk))
146                 console_fclk = NULL;
147         name[6] = 'i';
148         console_iclk = clk_get(NULL, name);
149         if (IS_ERR(console_fclk))
150                 console_iclk = NULL;
151         if (console_fclk == NULL || console_iclk == NULL) {
152                 serial_console_uart = 0;
153                 return;
154         }
155         switch (serial_console_uart) {
156         case 1:
157                 prm_set_mod_reg_bits(OMAP24XX_ST_UART1, CORE_MOD, PM_WKEN1);
158                 break;
159         case 2:
160                 prm_set_mod_reg_bits(OMAP24XX_ST_UART2, CORE_MOD, PM_WKEN1);
161                 break;
162         case 3:
163                 prm_set_mod_reg_bits(OMAP24XX_ST_UART3, CORE_MOD, OMAP24XX_PM_WKEN2);
164                 break;
165         }
166 }
167
168 #define DUMP_PRM_MOD_REG(mod, reg)    \
169         regs[reg_count].name = #mod "." #reg; \
170         regs[reg_count++].val = prm_read_mod_reg(mod, reg)
171 #define DUMP_CM_MOD_REG(mod, reg)     \
172         regs[reg_count].name = #mod "." #reg; \
173         regs[reg_count++].val = cm_read_mod_reg(mod, reg)
174 #define DUMP_PRM_REG(reg) \
175         regs[reg_count].name = #reg; \
176         regs[reg_count++].val = __raw_readl(reg)
177 #define DUMP_CM_REG(reg) \
178         regs[reg_count].name = #reg; \
179         regs[reg_count++].val = __raw_readl(reg)
180 #define DUMP_INTC_REG(reg, off) \
181         regs[reg_count].name = #reg; \
182         regs[reg_count++].val = __raw_readl(IO_ADDRESS(0x480fe000 + (off)))
183
184 void omap2_pm_dump(int mode, int resume, unsigned int us)
185 {
186         struct reg {
187                 const char *name;
188                 u32 val;
189         } regs[32];
190         int reg_count = 0, i;
191         const char *s1 = NULL, *s2 = NULL;
192
193         if (!resume) {
194 #if 0
195                 /* MPU */
196                 DUMP_PRM_REG(OMAP24XX_PRCM_IRQENABLE_MPU);
197                 DUMP_CM_MOD_REG(MPU_MOD, CM_CLKSTCTRL);
198                 DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTCTRL);
199                 DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTST);
200                 DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
201 #endif
202 #if 0
203                 /* INTC */
204                 DUMP_INTC_REG(INTC_MIR0, 0x0084);
205                 DUMP_INTC_REG(INTC_MIR1, 0x00a4);
206                 DUMP_INTC_REG(INTC_MIR2, 0x00c4);
207 #endif
208 #if 0
209                 DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1);
210                 DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2);
211                 DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN);
212                 DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1);
213                 DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2);
214                 DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
215                 DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
216                 DUMP_PRM_REG(OMAP24XX_PRCM_CLKEMUL_CTRL);
217                 DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
218                 DUMP_PRM_MOD_REG(CORE_MOD, PM_PWSTST);
219                 DUMP_PRM_REG(OMAP24XX_PRCM_CLKSRC_CTRL);
220 #endif
221 #if 0
222                 /* DSP */
223                 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN);
224                 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN);
225                 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
226                 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
227                 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
228                 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
229                 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTCTRL);
230                 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTST);
231                 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTCTRL);
232                 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTST);
233 #endif
234         } else {
235                 DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1);
236                 DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2);
237                 DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST);
238                 DUMP_PRM_REG(OMAP24XX_PRCM_IRQSTATUS_MPU);
239 #if 1
240                 DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
241                 DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
242                 DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
243 #endif
244         }
245
246         switch (mode) {
247         case 0:
248                 s1 = "full";
249                 s2 = "retention";
250                 break;
251         case 1:
252                 s1 = "MPU";
253                 s2 = "retention";
254                 break;
255         case 2:
256                 s1 = "MPU";
257                 s2 = "idle";
258                 break;
259         }
260
261         if (!resume)
262 #if defined(CONFIG_NO_IDLE_HZ) || defined(CONFIG_NO_HZ)
263                 printk("--- Going to %s %s (next timer after %u ms)\n", s1, s2,
264                        jiffies_to_msecs(get_next_timer_interrupt(jiffies) -
265                                         jiffies));
266 #else
267                 printk("--- Going to %s %s\n", s1, s2);
268 #endif
269         else
270                 printk("--- Woke up (slept for %u.%03u ms)\n", us / 1000, us % 1000);
271         for (i = 0; i < reg_count; i++)
272                 printk("%-20s: 0x%08x\n", regs[i].name, regs[i].val);
273 }
274
275 #endif