Linux Audio

Check our new training course

Loading...
v3.5.6
  1/*
  2 * OMAP2 Power Management Routines
  3 *
  4 * Copyright (C) 2005 Texas Instruments, Inc.
  5 * Copyright (C) 2006-2008 Nokia Corporation
  6 *
  7 * Written by:
  8 * Richard Woodruff <r-woodruff2@ti.com>
  9 * Tony Lindgren
 10 * Juha Yrjola
 11 * Amit Kucheria <amit.kucheria@nokia.com>
 12 * Igor Stoppa <igor.stoppa@nokia.com>
 13 *
 14 * Based on pm.c for omap1
 15 *
 16 * This program is free software; you can redistribute it and/or modify
 17 * it under the terms of the GNU General Public License version 2 as
 18 * published by the Free Software Foundation.
 19 */
 20
 21#include <linux/suspend.h>
 22#include <linux/sched.h>
 23#include <linux/proc_fs.h>
 24#include <linux/interrupt.h>
 25#include <linux/sysfs.h>
 26#include <linux/module.h>
 27#include <linux/delay.h>
 28#include <linux/clk.h>
 
 29#include <linux/irq.h>
 30#include <linux/time.h>
 31#include <linux/gpio.h>
 
 32
 33#include <asm/mach/time.h>
 34#include <asm/mach/irq.h>
 35#include <asm/mach-types.h>
 36#include <asm/system_misc.h>
 37
 
 38#include <plat/clock.h>
 39#include <plat/sram.h>
 40#include <plat/dma.h>
 41#include <plat/board.h>
 42
 43#include <mach/irqs.h>
 44
 45#include "common.h"
 46#include "prm2xxx_3xxx.h"
 47#include "prm-regbits-24xx.h"
 48#include "cm2xxx_3xxx.h"
 49#include "cm-regbits-24xx.h"
 50#include "sdrc.h"
 51#include "pm.h"
 52#include "control.h"
 
 53#include "powerdomain.h"
 54#include "clockdomain.h"
 55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 56static void (*omap2_sram_idle)(void);
 57static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
 58				  void __iomem *sdrc_power);
 59
 60static struct powerdomain *mpu_pwrdm, *core_pwrdm;
 61static struct clockdomain *dsp_clkdm, *mpu_clkdm, *wkup_clkdm, *gfx_clkdm;
 62
 63static struct clk *osc_ck, *emul_ck;
 64
 65static int omap2_fclks_active(void)
 66{
 67	u32 f1, f2;
 68
 69	f1 = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
 70	f2 = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
 71
 72	return (f1 | f2) ? 1 : 0;
 
 
 
 
 
 
 73}
 74
 75static int omap2_enter_full_retention(void)
 76{
 77	u32 l;
 
 78
 79	/* There is 1 reference hold for all children of the oscillator
 80	 * clock, the following will remove it. If no one else uses the
 81	 * oscillator itself it will be disabled if/when we enter retention
 82	 * mode.
 83	 */
 84	clk_disable(osc_ck);
 85
 86	/* Clear old wake-up events */
 87	/* REVISIT: These write to reserved bits? */
 88	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
 89	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
 90	omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
 91
 92	/*
 93	 * Set MPU powerdomain's next power state to RETENTION;
 94	 * preserve logic state during retention
 95	 */
 96	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
 97	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
 98
 99	/* Workaround to kill USB */
100	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
101	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
102
103	omap2_gpio_prepare_for_idle(0);
104
 
 
 
 
105	/* One last check for pending IRQs to avoid extra latency due
106	 * to sleeping unnecessarily. */
107	if (omap_irq_pending())
108		goto no_sleep;
109
 
 
 
 
 
 
 
 
 
110	/* Jump to SRAM suspend code */
111	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
112			   OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
113			   OMAP_SDRC_REGADDR(SDRC_POWER));
114
 
 
 
 
 
 
 
115no_sleep:
 
 
 
 
 
 
 
116	omap2_gpio_resume_after_idle();
117
118	clk_enable(osc_ck);
119
120	/* clear CORE wake-up events */
121	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
122	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
123
124	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
125	omap2_prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
126
127	/* MPU domain wake events */
128	l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
129	if (l & 0x01)
130		omap2_prm_write_mod_reg(0x01, OCP_MOD,
131				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
132	if (l & 0x20)
133		omap2_prm_write_mod_reg(0x20, OCP_MOD,
134				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
135
136	/* Mask future PRCM-to-MPU interrupts */
137	omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
138
139	return 0;
140}
141
142static int omap2_i2c_active(void)
143{
144	u32 l;
145
146	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
147	return l & (OMAP2420_EN_I2C2_MASK | OMAP2420_EN_I2C1_MASK);
148}
149
150static int sti_console_enabled;
151
152static int omap2_allow_mpu_retention(void)
153{
154	u32 l;
155
156	/* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
157	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
158	if (l & (OMAP2420_EN_MMC_MASK | OMAP24XX_EN_UART2_MASK |
159		 OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_MCSPI2_MASK |
160		 OMAP24XX_EN_MCSPI1_MASK | OMAP24XX_EN_DSS1_MASK))
161		return 0;
162	/* Check for UART3. */
163	l = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
164	if (l & OMAP24XX_EN_UART3_MASK)
165		return 0;
166	if (sti_console_enabled)
167		return 0;
168
169	return 1;
170}
171
172static void omap2_enter_mpu_retention(void)
173{
 
 
 
174	/* Putting MPU into the WFI state while a transfer is active
175	 * seems to cause the I2C block to timeout. Why? Good question. */
176	if (omap2_i2c_active())
177		return;
178
179	/* The peripherals seem not to be able to wake up the MPU when
180	 * it is in retention mode. */
181	if (omap2_allow_mpu_retention()) {
182		/* REVISIT: These write to reserved bits? */
183		omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
184		omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
185		omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
186
187		/* Try to enter MPU retention */
188		omap2_prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
189				  OMAP_LOGICRETSTATE_MASK,
190				  MPU_MOD, OMAP2_PM_PWSTCTRL);
191	} else {
192		/* Block MPU retention */
193
194		omap2_prm_write_mod_reg(OMAP_LOGICRETSTATE_MASK, MPU_MOD,
195						 OMAP2_PM_PWSTCTRL);
 
 
 
 
 
196	}
197
198	omap2_sram_idle();
 
 
 
 
 
 
 
 
199}
200
201static int omap2_can_sleep(void)
202{
203	if (omap2_fclks_active())
204		return 0;
 
 
205	if (osc_ck->usecount > 1)
206		return 0;
207	if (omap_dma_running())
208		return 0;
209
210	return 1;
211}
212
213static void omap2_pm_idle(void)
214{
 
215	local_fiq_disable();
216
217	if (!omap2_can_sleep()) {
218		if (omap_irq_pending())
219			goto out;
220		omap2_enter_mpu_retention();
221		goto out;
222	}
223
224	if (omap_irq_pending())
225		goto out;
226
227	omap2_enter_full_retention();
228
229out:
230	local_fiq_enable();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231}
232
233static void __init prcm_setup_regs(void)
234{
235	int i, num_mem_banks;
236	struct powerdomain *pwrdm;
237
238	/*
239	 * Enable autoidle
240	 * XXX This should be handled by hwmod code or PRCM init code
241	 */
242	omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
243			  OMAP2_PRCM_SYSCONFIG_OFFSET);
244
245	/*
246	 * Set CORE powerdomain memory banks to retain their contents
247	 * during RETENTION
248	 */
249	num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
250	for (i = 0; i < num_mem_banks; i++)
251		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
252
253	/* Set CORE powerdomain's next power state to RETENTION */
254	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
255
256	/*
257	 * Set MPU powerdomain's next power state to RETENTION;
258	 * preserve logic state during retention
259	 */
260	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
261	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
262
263	/* Force-power down DSP, GFX powerdomains */
264
265	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
266	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
267	clkdm_sleep(dsp_clkdm);
268
269	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
270	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
271	clkdm_sleep(gfx_clkdm);
272
273	/* Enable hardware-supervised idle for all clkdms */
274	clkdm_for_each(omap_pm_clkdms_setup, NULL);
275	clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);
276
277#ifdef CONFIG_SUSPEND
278	omap_pm_suspend = omap2_enter_full_retention;
279#endif
280
281	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
282	 * stabilisation */
283	omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
284				OMAP2_PRCM_CLKSSETUP_OFFSET);
285
286	/* Configure automatic voltage transition */
287	omap2_prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
288				OMAP2_PRCM_VOLTSETUP_OFFSET);
289	omap2_prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK |
290				(0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
291				OMAP24XX_MEMRETCTRL_MASK |
292				(0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) |
293				(0x0 << OMAP24XX_VOLT_LEVEL_SHIFT),
294				OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET);
295
296	/* Enable wake-up events */
297	omap2_prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK,
298				WKUP_MOD, PM_WKEN);
299}
300
301int __init omap2_pm_init(void)
302{
303	u32 l;
304
 
 
 
305	printk(KERN_INFO "Power Management for OMAP2 initializing\n");
306	l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
307	printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
308
309	/* Look up important powerdomains */
310
311	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
312	if (!mpu_pwrdm)
313		pr_err("PM: mpu_pwrdm not found\n");
314
315	core_pwrdm = pwrdm_lookup("core_pwrdm");
316	if (!core_pwrdm)
317		pr_err("PM: core_pwrdm not found\n");
318
319	/* Look up important clockdomains */
320
321	mpu_clkdm = clkdm_lookup("mpu_clkdm");
322	if (!mpu_clkdm)
323		pr_err("PM: mpu_clkdm not found\n");
324
325	wkup_clkdm = clkdm_lookup("wkup_clkdm");
326	if (!wkup_clkdm)
327		pr_err("PM: wkup_clkdm not found\n");
328
329	dsp_clkdm = clkdm_lookup("dsp_clkdm");
330	if (!dsp_clkdm)
331		pr_err("PM: dsp_clkdm not found\n");
332
333	gfx_clkdm = clkdm_lookup("gfx_clkdm");
334	if (!gfx_clkdm)
335		pr_err("PM: gfx_clkdm not found\n");
336
337
338	osc_ck = clk_get(NULL, "osc_ck");
339	if (IS_ERR(osc_ck)) {
340		printk(KERN_ERR "could not get osc_ck\n");
341		return -ENODEV;
342	}
343
344	if (cpu_is_omap242x()) {
345		emul_ck = clk_get(NULL, "emul_ck");
346		if (IS_ERR(emul_ck)) {
347			printk(KERN_ERR "could not get emul_ck\n");
348			clk_put(osc_ck);
349			return -ENODEV;
350		}
351	}
352
353	prcm_setup_regs();
354
355	/* Hack to prevent MPU retention when STI console is enabled. */
356	{
357		const struct omap_sti_console_config *sti;
358
359		sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
360				      struct omap_sti_console_config);
361		if (sti != NULL && sti->enable)
362			sti_console_enabled = 1;
363	}
364
365	/*
366	 * We copy the assembler sleep/wakeup routines to SRAM.
367	 * These routines need to be in SRAM as that's the only
368	 * memory the MPU can see when it wakes up.
369	 */
370	omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
371					 omap24xx_idle_loop_suspend_sz);
 
372
373	omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
374					    omap24xx_cpu_suspend_sz);
 
375
376	arm_pm_idle = omap2_pm_idle;
 
377
378	return 0;
379}
v3.1
  1/*
  2 * OMAP2 Power Management Routines
  3 *
  4 * Copyright (C) 2005 Texas Instruments, Inc.
  5 * Copyright (C) 2006-2008 Nokia Corporation
  6 *
  7 * Written by:
  8 * Richard Woodruff <r-woodruff2@ti.com>
  9 * Tony Lindgren
 10 * Juha Yrjola
 11 * Amit Kucheria <amit.kucheria@nokia.com>
 12 * Igor Stoppa <igor.stoppa@nokia.com>
 13 *
 14 * Based on pm.c for omap1
 15 *
 16 * This program is free software; you can redistribute it and/or modify
 17 * it under the terms of the GNU General Public License version 2 as
 18 * published by the Free Software Foundation.
 19 */
 20
 21#include <linux/suspend.h>
 22#include <linux/sched.h>
 23#include <linux/proc_fs.h>
 24#include <linux/interrupt.h>
 25#include <linux/sysfs.h>
 26#include <linux/module.h>
 27#include <linux/delay.h>
 28#include <linux/clk.h>
 29#include <linux/io.h>
 30#include <linux/irq.h>
 31#include <linux/time.h>
 32#include <linux/gpio.h>
 33#include <linux/console.h>
 34
 35#include <asm/mach/time.h>
 36#include <asm/mach/irq.h>
 37#include <asm/mach-types.h>
 
 38
 39#include <mach/irqs.h>
 40#include <plat/clock.h>
 41#include <plat/sram.h>
 42#include <plat/dma.h>
 43#include <plat/board.h>
 44
 
 
 
 45#include "prm2xxx_3xxx.h"
 46#include "prm-regbits-24xx.h"
 47#include "cm2xxx_3xxx.h"
 48#include "cm-regbits-24xx.h"
 49#include "sdrc.h"
 50#include "pm.h"
 51#include "control.h"
 52
 53#include "powerdomain.h"
 54#include "clockdomain.h"
 55
 56static int omap2_pm_debug;
 57
 58#ifdef CONFIG_SUSPEND
 59static suspend_state_t suspend_state = PM_SUSPEND_ON;
 60static inline bool is_suspending(void)
 61{
 62	return (suspend_state != PM_SUSPEND_ON);
 63}
 64#else
 65static inline bool is_suspending(void)
 66{
 67	return false;
 68}
 69#endif
 70
 71static void (*omap2_sram_idle)(void);
 72static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
 73				  void __iomem *sdrc_power);
 74
 75static struct powerdomain *mpu_pwrdm, *core_pwrdm;
 76static struct clockdomain *dsp_clkdm, *mpu_clkdm, *wkup_clkdm, *gfx_clkdm;
 77
 78static struct clk *osc_ck, *emul_ck;
 79
 80static int omap2_fclks_active(void)
 81{
 82	u32 f1, f2;
 83
 84	f1 = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
 85	f2 = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
 86
 87	/* Ignore UART clocks.  These are handled by UART core (serial.c) */
 88	f1 &= ~(OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_UART2_MASK);
 89	f2 &= ~OMAP24XX_EN_UART3_MASK;
 90
 91	if (f1 | f2)
 92		return 1;
 93	return 0;
 94}
 95
 96static void omap2_enter_full_retention(void)
 97{
 98	u32 l;
 99	struct timespec ts_preidle, ts_postidle, ts_idle;
100
101	/* There is 1 reference hold for all children of the oscillator
102	 * clock, the following will remove it. If no one else uses the
103	 * oscillator itself it will be disabled if/when we enter retention
104	 * mode.
105	 */
106	clk_disable(osc_ck);
107
108	/* Clear old wake-up events */
109	/* REVISIT: These write to reserved bits? */
110	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
111	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
112	omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
113
114	/*
115	 * Set MPU powerdomain's next power state to RETENTION;
116	 * preserve logic state during retention
117	 */
118	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
119	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
120
121	/* Workaround to kill USB */
122	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
123	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
124
125	omap2_gpio_prepare_for_idle(0);
126
127	if (omap2_pm_debug) {
128		getnstimeofday(&ts_preidle);
129	}
130
131	/* One last check for pending IRQs to avoid extra latency due
132	 * to sleeping unnecessarily. */
133	if (omap_irq_pending())
134		goto no_sleep;
135
136	/* Block console output in case it is on one of the OMAP UARTs */
137	if (!is_suspending())
138		if (!console_trylock())
139			goto no_sleep;
140
141	omap_uart_prepare_idle(0);
142	omap_uart_prepare_idle(1);
143	omap_uart_prepare_idle(2);
144
145	/* Jump to SRAM suspend code */
146	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
147			   OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
148			   OMAP_SDRC_REGADDR(SDRC_POWER));
149
150	omap_uart_resume_idle(2);
151	omap_uart_resume_idle(1);
152	omap_uart_resume_idle(0);
153
154	if (!is_suspending())
155		console_unlock();
156
157no_sleep:
158	if (omap2_pm_debug) {
159		unsigned long long tmp;
160
161		getnstimeofday(&ts_postidle);
162		ts_idle = timespec_sub(ts_postidle, ts_preidle);
163		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
164	}
165	omap2_gpio_resume_after_idle();
166
167	clk_enable(osc_ck);
168
169	/* clear CORE wake-up events */
170	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
171	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
172
173	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
174	omap2_prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
175
176	/* MPU domain wake events */
177	l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
178	if (l & 0x01)
179		omap2_prm_write_mod_reg(0x01, OCP_MOD,
180				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
181	if (l & 0x20)
182		omap2_prm_write_mod_reg(0x20, OCP_MOD,
183				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
184
185	/* Mask future PRCM-to-MPU interrupts */
186	omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
 
 
187}
188
189static int omap2_i2c_active(void)
190{
191	u32 l;
192
193	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
194	return l & (OMAP2420_EN_I2C2_MASK | OMAP2420_EN_I2C1_MASK);
195}
196
197static int sti_console_enabled;
198
199static int omap2_allow_mpu_retention(void)
200{
201	u32 l;
202
203	/* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
204	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
205	if (l & (OMAP2420_EN_MMC_MASK | OMAP24XX_EN_UART2_MASK |
206		 OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_MCSPI2_MASK |
207		 OMAP24XX_EN_MCSPI1_MASK | OMAP24XX_EN_DSS1_MASK))
208		return 0;
209	/* Check for UART3. */
210	l = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
211	if (l & OMAP24XX_EN_UART3_MASK)
212		return 0;
213	if (sti_console_enabled)
214		return 0;
215
216	return 1;
217}
218
219static void omap2_enter_mpu_retention(void)
220{
221	int only_idle = 0;
222	struct timespec ts_preidle, ts_postidle, ts_idle;
223
224	/* Putting MPU into the WFI state while a transfer is active
225	 * seems to cause the I2C block to timeout. Why? Good question. */
226	if (omap2_i2c_active())
227		return;
228
229	/* The peripherals seem not to be able to wake up the MPU when
230	 * it is in retention mode. */
231	if (omap2_allow_mpu_retention()) {
232		/* REVISIT: These write to reserved bits? */
233		omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
234		omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
235		omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
236
237		/* Try to enter MPU retention */
238		omap2_prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
239				  OMAP_LOGICRETSTATE_MASK,
240				  MPU_MOD, OMAP2_PM_PWSTCTRL);
241	} else {
242		/* Block MPU retention */
243
244		omap2_prm_write_mod_reg(OMAP_LOGICRETSTATE_MASK, MPU_MOD,
245						 OMAP2_PM_PWSTCTRL);
246		only_idle = 1;
247	}
248
249	if (omap2_pm_debug) {
250		getnstimeofday(&ts_preidle);
251	}
252
253	omap2_sram_idle();
254
255	if (omap2_pm_debug) {
256		unsigned long long tmp;
257
258		getnstimeofday(&ts_postidle);
259		ts_idle = timespec_sub(ts_postidle, ts_preidle);
260		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
261	}
262}
263
264static int omap2_can_sleep(void)
265{
266	if (omap2_fclks_active())
267		return 0;
268	if (!omap_uart_can_sleep())
269		return 0;
270	if (osc_ck->usecount > 1)
271		return 0;
272	if (omap_dma_running())
273		return 0;
274
275	return 1;
276}
277
278static void omap2_pm_idle(void)
279{
280	local_irq_disable();
281	local_fiq_disable();
282
283	if (!omap2_can_sleep()) {
284		if (omap_irq_pending())
285			goto out;
286		omap2_enter_mpu_retention();
287		goto out;
288	}
289
290	if (omap_irq_pending())
291		goto out;
292
293	omap2_enter_full_retention();
294
295out:
296	local_fiq_enable();
297	local_irq_enable();
298}
299
300#ifdef CONFIG_SUSPEND
301static int omap2_pm_begin(suspend_state_t state)
302{
303	disable_hlt();
304	suspend_state = state;
305	return 0;
306}
307
308static int omap2_pm_suspend(void)
309{
310	u32 wken_wkup, mir1;
311
312	wken_wkup = omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
313	wken_wkup &= ~OMAP24XX_EN_GPT1_MASK;
314	omap2_prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
315
316	/* Mask GPT1 */
317	mir1 = omap_readl(0x480fe0a4);
318	omap_writel(1 << 5, 0x480fe0ac);
319
320	omap_uart_prepare_suspend();
321	omap2_enter_full_retention();
322
323	omap_writel(mir1, 0x480fe0a4);
324	omap2_prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
325
326	return 0;
327}
328
329static int omap2_pm_enter(suspend_state_t state)
330{
331	int ret = 0;
332
333	switch (state) {
334	case PM_SUSPEND_STANDBY:
335	case PM_SUSPEND_MEM:
336		ret = omap2_pm_suspend();
337		break;
338	default:
339		ret = -EINVAL;
340	}
341
342	return ret;
343}
344
345static void omap2_pm_end(void)
346{
347	suspend_state = PM_SUSPEND_ON;
348	enable_hlt();
349}
350
351static const struct platform_suspend_ops omap_pm_ops = {
352	.begin		= omap2_pm_begin,
353	.enter		= omap2_pm_enter,
354	.end		= omap2_pm_end,
355	.valid		= suspend_valid_only_mem,
356};
357#else
358static const struct platform_suspend_ops __initdata omap_pm_ops;
359#endif /* CONFIG_SUSPEND */
360
361/* XXX This function should be shareable between OMAP2xxx and OMAP3 */
362static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
363{
364	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
365		clkdm_allow_idle(clkdm);
366	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
367		 atomic_read(&clkdm->usecount) == 0)
368		clkdm_sleep(clkdm);
369	return 0;
370}
371
372static void __init prcm_setup_regs(void)
373{
374	int i, num_mem_banks;
375	struct powerdomain *pwrdm;
376
377	/*
378	 * Enable autoidle
379	 * XXX This should be handled by hwmod code or PRCM init code
380	 */
381	omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
382			  OMAP2_PRCM_SYSCONFIG_OFFSET);
383
384	/*
385	 * Set CORE powerdomain memory banks to retain their contents
386	 * during RETENTION
387	 */
388	num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
389	for (i = 0; i < num_mem_banks; i++)
390		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
391
392	/* Set CORE powerdomain's next power state to RETENTION */
393	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
394
395	/*
396	 * Set MPU powerdomain's next power state to RETENTION;
397	 * preserve logic state during retention
398	 */
399	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
400	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
401
402	/* Force-power down DSP, GFX powerdomains */
403
404	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
405	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
406	clkdm_sleep(dsp_clkdm);
407
408	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
409	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
410	clkdm_sleep(gfx_clkdm);
411
412	/* Enable hardware-supervised idle for all clkdms */
413	clkdm_for_each(clkdms_setup, NULL);
414	clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);
415
 
 
 
 
416	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
417	 * stabilisation */
418	omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
419				OMAP2_PRCM_CLKSSETUP_OFFSET);
420
421	/* Configure automatic voltage transition */
422	omap2_prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
423				OMAP2_PRCM_VOLTSETUP_OFFSET);
424	omap2_prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK |
425				(0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
426				OMAP24XX_MEMRETCTRL_MASK |
427				(0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) |
428				(0x0 << OMAP24XX_VOLT_LEVEL_SHIFT),
429				OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET);
430
431	/* Enable wake-up events */
432	omap2_prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK,
433				WKUP_MOD, PM_WKEN);
434}
435
436static int __init omap2_pm_init(void)
437{
438	u32 l;
439
440	if (!cpu_is_omap24xx())
441		return -ENODEV;
442
443	printk(KERN_INFO "Power Management for OMAP2 initializing\n");
444	l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
445	printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
446
447	/* Look up important powerdomains */
448
449	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
450	if (!mpu_pwrdm)
451		pr_err("PM: mpu_pwrdm not found\n");
452
453	core_pwrdm = pwrdm_lookup("core_pwrdm");
454	if (!core_pwrdm)
455		pr_err("PM: core_pwrdm not found\n");
456
457	/* Look up important clockdomains */
458
459	mpu_clkdm = clkdm_lookup("mpu_clkdm");
460	if (!mpu_clkdm)
461		pr_err("PM: mpu_clkdm not found\n");
462
463	wkup_clkdm = clkdm_lookup("wkup_clkdm");
464	if (!wkup_clkdm)
465		pr_err("PM: wkup_clkdm not found\n");
466
467	dsp_clkdm = clkdm_lookup("dsp_clkdm");
468	if (!dsp_clkdm)
469		pr_err("PM: dsp_clkdm not found\n");
470
471	gfx_clkdm = clkdm_lookup("gfx_clkdm");
472	if (!gfx_clkdm)
473		pr_err("PM: gfx_clkdm not found\n");
474
475
476	osc_ck = clk_get(NULL, "osc_ck");
477	if (IS_ERR(osc_ck)) {
478		printk(KERN_ERR "could not get osc_ck\n");
479		return -ENODEV;
480	}
481
482	if (cpu_is_omap242x()) {
483		emul_ck = clk_get(NULL, "emul_ck");
484		if (IS_ERR(emul_ck)) {
485			printk(KERN_ERR "could not get emul_ck\n");
486			clk_put(osc_ck);
487			return -ENODEV;
488		}
489	}
490
491	prcm_setup_regs();
492
493	/* Hack to prevent MPU retention when STI console is enabled. */
494	{
495		const struct omap_sti_console_config *sti;
496
497		sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
498				      struct omap_sti_console_config);
499		if (sti != NULL && sti->enable)
500			sti_console_enabled = 1;
501	}
502
503	/*
504	 * We copy the assembler sleep/wakeup routines to SRAM.
505	 * These routines need to be in SRAM as that's the only
506	 * memory the MPU can see when it wakes up.
507	 */
508	if (cpu_is_omap24xx()) {
509		omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
510						 omap24xx_idle_loop_suspend_sz);
511
512		omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
513						    omap24xx_cpu_suspend_sz);
514	}
515
516	suspend_set_ops(&omap_pm_ops);
517	pm_idle = omap2_pm_idle;
518
519	return 0;
520}
521
522late_initcall(omap2_pm_init);