2 * linux/arch/arm/mach-omap2/pm_debug.c
4 * OMAP Power Management debug routines
6 * Copyright (C) 2005 Texas Instruments, Inc.
7 * Copyright (C) 2006-2008 Nokia Corporation
10 * Richard Woodruff <r-woodruff2@ti.com>
13 * Amit Kucheria <amit.kucheria@nokia.com>
14 * Igor Stoppa <igor.stoppa@nokia.com>
17 * Based on pm.c for omap2
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.
24 #include <linux/clk.h>
25 #include <linux/err.h>
28 #include <asm/arch/clock.h>
29 #include <asm/arch/board.h>
34 #ifdef CONFIG_PM_DEBUG
35 int omap2_pm_debug
= 0;
37 static int serial_console_clock_disabled
;
38 static int serial_console_uart
;
39 static unsigned int serial_console_next_disable
;
41 static struct clk
*console_iclk
, *console_fclk
;
43 static void serial_console_kick(void)
45 serial_console_next_disable
= omap2_read_32k_sync_counter();
46 /* Keep the clocks on for 4 secs */
47 serial_console_next_disable
+= 4 * 32768;
50 static void serial_wait_tx(void)
52 static const unsigned long uart_bases
[3] = {
53 0x4806a000, 0x4806c000, 0x4806e000
55 unsigned long lsr_reg
;
58 /* Wait for TX FIFO and THR to get empty */
59 lsr_reg
= IO_ADDRESS(uart_bases
[serial_console_uart
- 1] + (5 << 2));
60 while ((__raw_readb(lsr_reg
) & 0x60) != 0x60)
63 serial_console_kick();
66 u32
omap2_read_32k_sync_counter(void)
68 return omap_readl(OMAP2_32KSYNCT_BASE
+ 0x0010);
71 void serial_console_fclk_mask(u32
*f1
, u32
*f2
)
73 switch (serial_console_uart
) {
86 void serial_console_sleep(int enable
)
88 if (console_iclk
== NULL
|| console_fclk
== NULL
)
92 BUG_ON(serial_console_clock_disabled
);
93 if (clk_get_usecount(console_fclk
) == 0)
95 if ((int) serial_console_next_disable
- (int) omap2_read_32k_sync_counter() >= 0)
98 clk_disable(console_iclk
);
99 clk_disable(console_fclk
);
100 serial_console_clock_disabled
= 1;
102 int serial_wakeup
= 0;
105 switch (serial_console_uart
) {
107 l
= prm_read_mod_reg(CORE_MOD
, PM_WKST1
);
108 if (l
& OMAP24XX_ST_UART1
)
112 l
= prm_read_mod_reg(CORE_MOD
, PM_WKST1
);
113 if (l
& OMAP24XX_ST_UART2
)
117 l
= prm_read_mod_reg(CORE_MOD
, OMAP24XX_PM_WKST2
);
118 if (l
& OMAP24XX_ST_UART3
)
123 serial_console_kick();
124 if (!serial_console_clock_disabled
)
126 clk_enable(console_iclk
);
127 clk_enable(console_fclk
);
128 serial_console_clock_disabled
= 0;
132 void pm_init_serial_console(void)
134 const struct omap_serial_console_config
*conf
;
137 conf
= omap_get_config(OMAP_TAG_SERIAL_CONSOLE
,
138 struct omap_serial_console_config
);
141 if (conf
->console_uart
> 3 || conf
->console_uart
< 1)
143 serial_console_uart
= conf
->console_uart
;
144 sprintf(name
, "uart%d_fck", conf
->console_uart
);
145 console_fclk
= clk_get(NULL
, name
);
146 if (IS_ERR(console_fclk
))
149 console_iclk
= clk_get(NULL
, name
);
150 if (IS_ERR(console_fclk
))
152 if (console_fclk
== NULL
|| console_iclk
== NULL
) {
153 serial_console_uart
= 0;
156 switch (serial_console_uart
) {
158 prm_set_mod_reg_bits(OMAP24XX_ST_UART1
, CORE_MOD
, PM_WKEN1
);
161 prm_set_mod_reg_bits(OMAP24XX_ST_UART2
, CORE_MOD
, PM_WKEN1
);
164 prm_set_mod_reg_bits(OMAP24XX_ST_UART3
, CORE_MOD
, OMAP24XX_PM_WKEN2
);
169 #define DUMP_PRM_MOD_REG(mod, reg) \
170 regs[reg_count].name = #mod "." #reg; \
171 regs[reg_count++].val = prm_read_mod_reg(mod, reg)
172 #define DUMP_CM_MOD_REG(mod, reg) \
173 regs[reg_count].name = #mod "." #reg; \
174 regs[reg_count++].val = cm_read_mod_reg(mod, reg)
175 #define DUMP_PRM_REG(reg) \
176 regs[reg_count].name = #reg; \
177 regs[reg_count++].val = __raw_readl(reg)
178 #define DUMP_CM_REG(reg) \
179 regs[reg_count].name = #reg; \
180 regs[reg_count++].val = __raw_readl(reg)
181 #define DUMP_INTC_REG(reg, off) \
182 regs[reg_count].name = #reg; \
183 regs[reg_count++].val = __raw_readl(IO_ADDRESS(0x480fe000 + (off)))
185 void omap2_pm_dump(int mode
, int resume
, unsigned int us
)
191 int reg_count
= 0, i
;
192 const char *s1
= NULL
, *s2
= NULL
;
197 DUMP_PRM_REG(OMAP24XX_PRCM_IRQENABLE_MPU
);
198 DUMP_CM_MOD_REG(MPU_MOD
, CM_CLKSTCTRL
);
199 DUMP_PRM_MOD_REG(MPU_MOD
, PM_PWSTCTRL
);
200 DUMP_PRM_MOD_REG(MPU_MOD
, PM_PWSTST
);
201 DUMP_PRM_MOD_REG(MPU_MOD
, PM_WKDEP
);
205 DUMP_INTC_REG(INTC_MIR0
, 0x0084);
206 DUMP_INTC_REG(INTC_MIR1
, 0x00a4);
207 DUMP_INTC_REG(INTC_MIR2
, 0x00c4);
210 DUMP_CM_MOD_REG(CORE_MOD
, CM_FCLKEN1
);
211 DUMP_CM_MOD_REG(CORE_MOD
, OMAP24XX_CM_FCLKEN2
);
212 DUMP_CM_MOD_REG(WKUP_MOD
, CM_FCLKEN
);
213 DUMP_CM_MOD_REG(CORE_MOD
, CM_ICLKEN1
);
214 DUMP_CM_MOD_REG(CORE_MOD
, CM_ICLKEN2
);
215 DUMP_CM_MOD_REG(WKUP_MOD
, CM_ICLKEN
);
216 DUMP_CM_MOD_REG(PLL_MOD
, CM_CLKEN
);
217 DUMP_PRM_REG(OMAP24XX_PRCM_CLKEMUL_CTRL
);
218 DUMP_CM_MOD_REG(PLL_MOD
, CM_AUTOIDLE
);
219 DUMP_PRM_MOD_REG(CORE_MOD
, PM_PWSTST
);
220 DUMP_PRM_REG(OMAP24XX_PRCM_CLKSRC_CTRL
);
224 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_FCLKEN
);
225 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_ICLKEN
);
226 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_IDLEST
);
227 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_AUTOIDLE
);
228 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_CLKSEL
);
229 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_CLKSTCTRL
);
230 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD
, RM_RSTCTRL
);
231 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD
, RM_RSTST
);
232 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD
, PM_PWSTCTRL
);
233 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD
, PM_PWSTST
);
236 DUMP_PRM_MOD_REG(CORE_MOD
, PM_WKST1
);
237 DUMP_PRM_MOD_REG(CORE_MOD
, OMAP24XX_PM_WKST2
);
238 DUMP_PRM_MOD_REG(WKUP_MOD
, PM_WKST
);
239 DUMP_PRM_REG(OMAP24XX_PRCM_IRQSTATUS_MPU
);
241 DUMP_INTC_REG(INTC_PENDING_IRQ0
, 0x0098);
242 DUMP_INTC_REG(INTC_PENDING_IRQ1
, 0x00b8);
243 DUMP_INTC_REG(INTC_PENDING_IRQ2
, 0x00d8);
263 #if defined(CONFIG_NO_IDLE_HZ) || defined(CONFIG_NO_HZ)
264 printk("--- Going to %s %s (next timer after %u ms)\n", s1
, s2
,
265 jiffies_to_msecs(get_next_timer_interrupt(jiffies
) -
268 printk("--- Going to %s %s\n", s1
, s2
);
271 printk("--- Woke up (slept for %u.%03u ms)\n", us
/ 1000, us
% 1000);
272 for (i
= 0; i
< reg_count
; i
++)
273 printk("%-20s: 0x%08x\n", regs
[i
].name
, regs
[i
].val
);