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/kernel.h>
25 #include <linux/timer.h>
26 #include <linux/clk.h>
27 #include <linux/err.h>
30 #include <mach/clock.h>
31 #include <mach/board.h>
37 #ifdef CONFIG_PM_DEBUG
38 int omap2_pm_debug = 0;
40 static int serial_console_clock_disabled;
41 static int serial_console_uart;
42 static unsigned int serial_console_next_disable;
44 static struct clk *console_iclk, *console_fclk;
46 static void serial_console_kick(void)
48 serial_console_next_disable = omap2_read_32k_sync_counter();
49 /* Keep the clocks on for 4 secs */
50 serial_console_next_disable += 4 * 32768;
53 static void serial_wait_tx(void)
55 static const unsigned long uart_bases[3] = {
56 0x4806a000, 0x4806c000, 0x4806e000
58 unsigned long lsr_reg;
61 /* Wait for TX FIFO and THR to get empty */
62 lsr_reg = IO_ADDRESS(uart_bases[serial_console_uart - 1] + (5 << 2));
63 while ((__raw_readb(lsr_reg) & 0x60) != 0x60)
66 serial_console_kick();
69 u32 omap2_read_32k_sync_counter(void)
71 return omap_readl(OMAP2_32KSYNCT_BASE + 0x0010);
74 void serial_console_fclk_mask(u32 *f1, u32 *f2)
76 switch (serial_console_uart) {
89 void serial_console_sleep(int enable)
91 if (console_iclk == NULL || console_fclk == NULL)
95 BUG_ON(serial_console_clock_disabled);
96 if (clk_get_usecount(console_fclk) == 0)
98 if ((int) serial_console_next_disable - (int) omap2_read_32k_sync_counter() >= 0)
101 clk_disable(console_iclk);
102 clk_disable(console_fclk);
103 serial_console_clock_disabled = 1;
105 int serial_wakeup = 0;
108 switch (serial_console_uart) {
110 l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
111 if (l & OMAP24XX_ST_UART1)
115 l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
116 if (l & OMAP24XX_ST_UART2)
120 l = prm_read_mod_reg(CORE_MOD, OMAP24XX_PM_WKST2);
121 if (l & OMAP24XX_ST_UART3)
126 serial_console_kick();
127 if (!serial_console_clock_disabled)
129 clk_enable(console_iclk);
130 clk_enable(console_fclk);
131 serial_console_clock_disabled = 0;
135 void pm_init_serial_console(void)
137 const struct omap_serial_console_config *conf;
140 conf = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
141 struct omap_serial_console_config);
144 if (conf->console_uart > 3 || conf->console_uart < 1)
146 serial_console_uart = conf->console_uart;
147 sprintf(name, "uart%d_fck", conf->console_uart);
148 console_fclk = clk_get(NULL, name);
149 if (IS_ERR(console_fclk))
152 console_iclk = clk_get(NULL, name);
153 if (IS_ERR(console_fclk))
155 if (console_fclk == NULL || console_iclk == NULL) {
156 serial_console_uart = 0;
159 switch (serial_console_uart) {
161 prm_set_mod_reg_bits(OMAP24XX_ST_UART1, CORE_MOD, PM_WKEN1);
164 prm_set_mod_reg_bits(OMAP24XX_ST_UART2, CORE_MOD, PM_WKEN1);
167 prm_set_mod_reg_bits(OMAP24XX_ST_UART3, CORE_MOD, OMAP24XX_PM_WKEN2);
172 #define DUMP_PRM_MOD_REG(mod, reg) \
173 regs[reg_count].name = #mod "." #reg; \
174 regs[reg_count++].val = prm_read_mod_reg(mod, reg)
175 #define DUMP_CM_MOD_REG(mod, reg) \
176 regs[reg_count].name = #mod "." #reg; \
177 regs[reg_count++].val = cm_read_mod_reg(mod, reg)
178 #define DUMP_PRM_REG(reg) \
179 regs[reg_count].name = #reg; \
180 regs[reg_count++].val = __raw_readl(reg)
181 #define DUMP_CM_REG(reg) \
182 regs[reg_count].name = #reg; \
183 regs[reg_count++].val = __raw_readl(reg)
184 #define DUMP_INTC_REG(reg, off) \
185 regs[reg_count].name = #reg; \
186 regs[reg_count++].val = __raw_readl(IO_ADDRESS(0x480fe000 + (off)))
188 void omap2_pm_dump(int mode, int resume, unsigned int us)
194 int reg_count = 0, i;
195 const char *s1 = NULL, *s2 = NULL;
200 DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
201 DUMP_CM_MOD_REG(MPU_MOD, CM_CLKSTCTRL);
202 DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTCTRL);
203 DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTST);
204 DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
208 DUMP_INTC_REG(INTC_MIR0, 0x0084);
209 DUMP_INTC_REG(INTC_MIR1, 0x00a4);
210 DUMP_INTC_REG(INTC_MIR2, 0x00c4);
213 DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1);
214 if (cpu_is_omap24xx()) {
215 DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2);
216 DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
217 OMAP24XX_PRCM_CLKEMUL_CTRL_OFFSET);
218 DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
219 OMAP24XX_PRCM_CLKSRC_CTRL_OFFSET);
221 DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN);
222 DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1);
223 DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2);
224 DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
225 DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
226 DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
227 DUMP_PRM_MOD_REG(CORE_MOD, PM_PWSTST);
231 if (cpu_is_omap24xx()) {
232 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN);
233 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN);
234 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
235 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
236 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
237 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
238 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTCTRL);
239 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTST);
240 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTCTRL);
241 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTST);
245 DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1);
246 if (cpu_is_omap24xx())
247 DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2);
248 DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST);
249 DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
251 DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
252 DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
253 DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
273 #if defined(CONFIG_NO_IDLE_HZ) || defined(CONFIG_NO_HZ)
274 printk("--- Going to %s %s (next timer after %u ms)\n", s1, s2,
275 jiffies_to_msecs(get_next_timer_interrupt(jiffies) -
278 printk("--- Going to %s %s\n", s1, s2);
281 printk("--- Woke up (slept for %u.%03u ms)\n",
282 us / 1000, us % 1000);
284 for (i = 0; i < reg_count; i++)
285 printk("%-20s: 0x%08x\n", regs[i].name, regs[i].val);