PRCM: OMAP3: Fix to wrongly modified omap2_clk_wait_ready
[linux-ginger.git] / arch / arm / mach-omap2 / pm-debug.c
blob8a9f3c4f09f8b8b2f22b61c6096568a4f1cce35c
1 /*
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
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
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>
26 #include <linux/io.h>
28 #include <asm/arch/clock.h>
29 #include <asm/arch/board.h>
31 #include "prm.h"
32 #include "pm.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;
56 int looped = 0;
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)
61 looped = 1;
62 if (looped)
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) {
74 case 1:
75 *f1 &= ~(1 << 21);
76 break;
77 case 2:
78 *f1 &= ~(1 << 22);
79 break;
80 case 3:
81 *f2 &= ~(1 << 2);
82 break;
86 void serial_console_sleep(int enable)
88 if (console_iclk == NULL || console_fclk == NULL)
89 return;
91 if (enable) {
92 BUG_ON(serial_console_clock_disabled);
93 if (clk_get_usecount(console_fclk) == 0)
94 return;
95 if ((int) serial_console_next_disable - (int) omap2_read_32k_sync_counter() >= 0)
96 return;
97 serial_wait_tx();
98 clk_disable(console_iclk);
99 clk_disable(console_fclk);
100 serial_console_clock_disabled = 1;
101 } else {
102 int serial_wakeup = 0;
103 u32 l;
105 switch (serial_console_uart) {
106 case 1:
107 l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
108 if (l & OMAP24XX_ST_UART1)
109 serial_wakeup = 1;
110 break;
111 case 2:
112 l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
113 if (l & OMAP24XX_ST_UART2)
114 serial_wakeup = 1;
115 break;
116 case 3:
117 l = prm_read_mod_reg(CORE_MOD, OMAP24XX_PM_WKST2);
118 if (l & OMAP24XX_ST_UART3)
119 serial_wakeup = 1;
120 break;
122 if (serial_wakeup)
123 serial_console_kick();
124 if (!serial_console_clock_disabled)
125 return;
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;
135 char name[16];
137 conf = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
138 struct omap_serial_console_config);
139 if (conf == NULL)
140 return;
141 if (conf->console_uart > 3 || conf->console_uart < 1)
142 return;
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))
147 console_fclk = NULL;
148 name[6] = 'i';
149 console_iclk = clk_get(NULL, name);
150 if (IS_ERR(console_fclk))
151 console_iclk = NULL;
152 if (console_fclk == NULL || console_iclk == NULL) {
153 serial_console_uart = 0;
154 return;
156 switch (serial_console_uart) {
157 case 1:
158 prm_set_mod_reg_bits(OMAP24XX_ST_UART1, CORE_MOD, PM_WKEN1);
159 break;
160 case 2:
161 prm_set_mod_reg_bits(OMAP24XX_ST_UART2, CORE_MOD, PM_WKEN1);
162 break;
163 case 3:
164 prm_set_mod_reg_bits(OMAP24XX_ST_UART3, CORE_MOD, OMAP24XX_PM_WKEN2);
165 break;
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)
187 struct reg {
188 const char *name;
189 u32 val;
190 } regs[32];
191 int reg_count = 0, i;
192 const char *s1 = NULL, *s2 = NULL;
194 if (!resume) {
195 #if 0
196 /* MPU */
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);
202 #endif
203 #if 0
204 /* INTC */
205 DUMP_INTC_REG(INTC_MIR0, 0x0084);
206 DUMP_INTC_REG(INTC_MIR1, 0x00a4);
207 DUMP_INTC_REG(INTC_MIR2, 0x00c4);
208 #endif
209 #if 0
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);
221 #endif
222 #if 0
223 /* DSP */
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);
234 #endif
235 } else {
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);
240 #if 1
241 DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
242 DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
243 DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
244 #endif
247 switch (mode) {
248 case 0:
249 s1 = "full";
250 s2 = "retention";
251 break;
252 case 1:
253 s1 = "MPU";
254 s2 = "retention";
255 break;
256 case 2:
257 s1 = "MPU";
258 s2 = "idle";
259 break;
262 if (!resume)
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) -
266 jiffies));
267 #else
268 printk("--- Going to %s %s\n", s1, s2);
269 #endif
270 else
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);
276 #endif