• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/arm/mach-omap2/
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
34#include <asm/mach/time.h>
35#include <asm/mach/irq.h>
36#include <asm/mach-types.h>
37
38#include <mach/irqs.h>
39#include <plat/clock.h>
40#include <plat/sram.h>
41#include <plat/control.h>
42#include <plat/dma.h>
43#include <plat/board.h>
44
45#include "prm.h"
46#include "prm-regbits-24xx.h"
47#include "cm.h"
48#include "cm-regbits-24xx.h"
49#include "sdrc.h"
50#include "pm.h"
51
52#include <plat/powerdomain.h>
53#include <plat/clockdomain.h>
54
55static void (*omap2_sram_idle)(void);
56static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
57				  void __iomem *sdrc_power);
58
59static struct powerdomain *mpu_pwrdm, *core_pwrdm;
60static struct clockdomain *dsp_clkdm, *mpu_clkdm, *wkup_clkdm, *gfx_clkdm;
61
62static struct clk *osc_ck, *emul_ck;
63
64static int omap2_fclks_active(void)
65{
66	u32 f1, f2;
67
68	f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
69	f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
70
71	/* Ignore UART clocks.  These are handled by UART core (serial.c) */
72	f1 &= ~(OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_UART2_MASK);
73	f2 &= ~OMAP24XX_EN_UART3_MASK;
74
75	if (f1 | f2)
76		return 1;
77	return 0;
78}
79
80static void omap2_enter_full_retention(void)
81{
82	u32 l;
83	struct timespec ts_preidle, ts_postidle, ts_idle;
84
85	/* There is 1 reference hold for all children of the oscillator
86	 * clock, the following will remove it. If no one else uses the
87	 * oscillator itself it will be disabled if/when we enter retention
88	 * mode.
89	 */
90	clk_disable(osc_ck);
91
92	/* Clear old wake-up events */
93	/* REVISIT: These write to reserved bits? */
94	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
95	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
96	prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
97
98	/*
99	 * Set MPU powerdomain's next power state to RETENTION;
100	 * preserve logic state during retention
101	 */
102	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
103	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
104
105	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
106	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
107
108	omap2_gpio_prepare_for_idle(PWRDM_POWER_RET);
109
110	if (omap2_pm_debug) {
111		omap2_pm_dump(0, 0, 0);
112		getnstimeofday(&ts_preidle);
113	}
114
115	/* One last check for pending IRQs to avoid extra latency due
116	 * to sleeping unnecessarily. */
117	if (omap_irq_pending())
118		goto no_sleep;
119
120	omap_uart_prepare_idle(0);
121	omap_uart_prepare_idle(1);
122	omap_uart_prepare_idle(2);
123
124	/* Jump to SRAM suspend code */
125	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
126			   OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
127			   OMAP_SDRC_REGADDR(SDRC_POWER));
128
129	omap_uart_resume_idle(2);
130	omap_uart_resume_idle(1);
131	omap_uart_resume_idle(0);
132
133no_sleep:
134	if (omap2_pm_debug) {
135		unsigned long long tmp;
136
137		getnstimeofday(&ts_postidle);
138		ts_idle = timespec_sub(ts_postidle, ts_preidle);
139		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
140		omap2_pm_dump(0, 1, tmp);
141	}
142	omap2_gpio_resume_after_idle();
143
144	clk_enable(osc_ck);
145
146	/* clear CORE wake-up events */
147	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
148	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
149
150	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
151	prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
152
153	/* MPU domain wake events */
154	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
155	if (l & 0x01)
156		prm_write_mod_reg(0x01, OCP_MOD,
157				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
158	if (l & 0x20)
159		prm_write_mod_reg(0x20, OCP_MOD,
160				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
161
162	/* Mask future PRCM-to-MPU interrupts */
163	prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
164}
165
166static int omap2_i2c_active(void)
167{
168	u32 l;
169
170	l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
171	return l & (OMAP2420_EN_I2C2_MASK | OMAP2420_EN_I2C1_MASK);
172}
173
174static int sti_console_enabled;
175
176static int omap2_allow_mpu_retention(void)
177{
178	u32 l;
179
180	/* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
181	l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
182	if (l & (OMAP2420_EN_MMC_MASK | OMAP24XX_EN_UART2_MASK |
183		 OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_MCSPI2_MASK |
184		 OMAP24XX_EN_MCSPI1_MASK | OMAP24XX_EN_DSS1_MASK))
185		return 0;
186	/* Check for UART3. */
187	l = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
188	if (l & OMAP24XX_EN_UART3_MASK)
189		return 0;
190	if (sti_console_enabled)
191		return 0;
192
193	return 1;
194}
195
196static void omap2_enter_mpu_retention(void)
197{
198	int only_idle = 0;
199	struct timespec ts_preidle, ts_postidle, ts_idle;
200
201	/* Putting MPU into the WFI state while a transfer is active
202	 * seems to cause the I2C block to timeout. Why? Good question. */
203	if (omap2_i2c_active())
204		return;
205
206	/* The peripherals seem not to be able to wake up the MPU when
207	 * it is in retention mode. */
208	if (omap2_allow_mpu_retention()) {
209		/* REVISIT: These write to reserved bits? */
210		prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
211		prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
212		prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
213
214		/* Try to enter MPU retention */
215		prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
216				  OMAP_LOGICRETSTATE_MASK,
217				  MPU_MOD, OMAP2_PM_PWSTCTRL);
218	} else {
219		/* Block MPU retention */
220
221		prm_write_mod_reg(OMAP_LOGICRETSTATE_MASK, MPU_MOD,
222						 OMAP2_PM_PWSTCTRL);
223		only_idle = 1;
224	}
225
226	if (omap2_pm_debug) {
227		omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
228		getnstimeofday(&ts_preidle);
229	}
230
231	omap2_sram_idle();
232
233	if (omap2_pm_debug) {
234		unsigned long long tmp;
235
236		getnstimeofday(&ts_postidle);
237		ts_idle = timespec_sub(ts_postidle, ts_preidle);
238		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
239		omap2_pm_dump(only_idle ? 2 : 1, 1, tmp);
240	}
241}
242
243static int omap2_can_sleep(void)
244{
245	if (omap2_fclks_active())
246		return 0;
247	if (osc_ck->usecount > 1)
248		return 0;
249	if (omap_dma_running())
250		return 0;
251
252	return 1;
253}
254
255static void omap2_pm_idle(void)
256{
257	local_irq_disable();
258	local_fiq_disable();
259
260	if (!omap2_can_sleep()) {
261		if (omap_irq_pending())
262			goto out;
263		omap2_enter_mpu_retention();
264		goto out;
265	}
266
267	if (omap_irq_pending())
268		goto out;
269
270	omap2_enter_full_retention();
271
272out:
273	local_fiq_enable();
274	local_irq_enable();
275}
276
277static int omap2_pm_prepare(void)
278{
279	/* We cannot sleep in idle until we have resumed */
280	disable_hlt();
281	return 0;
282}
283
284static int omap2_pm_suspend(void)
285{
286	u32 wken_wkup, mir1;
287
288	wken_wkup = prm_read_mod_reg(WKUP_MOD, PM_WKEN);
289	wken_wkup &= ~OMAP24XX_EN_GPT1_MASK;
290	prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
291
292	/* Mask GPT1 */
293	mir1 = omap_readl(0x480fe0a4);
294	omap_writel(1 << 5, 0x480fe0ac);
295
296	omap_uart_prepare_suspend();
297	omap2_enter_full_retention();
298
299	omap_writel(mir1, 0x480fe0a4);
300	prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
301
302	return 0;
303}
304
305static int omap2_pm_enter(suspend_state_t state)
306{
307	int ret = 0;
308
309	switch (state) {
310	case PM_SUSPEND_STANDBY:
311	case PM_SUSPEND_MEM:
312		ret = omap2_pm_suspend();
313		break;
314	default:
315		ret = -EINVAL;
316	}
317
318	return ret;
319}
320
321static void omap2_pm_finish(void)
322{
323	enable_hlt();
324}
325
326static struct platform_suspend_ops omap_pm_ops = {
327	.prepare	= omap2_pm_prepare,
328	.enter		= omap2_pm_enter,
329	.finish		= omap2_pm_finish,
330	.valid		= suspend_valid_only_mem,
331};
332
333static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
334{
335	clkdm_clear_all_wkdeps(clkdm);
336	clkdm_clear_all_sleepdeps(clkdm);
337
338	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
339		omap2_clkdm_allow_idle(clkdm);
340	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
341		 atomic_read(&clkdm->usecount) == 0)
342		omap2_clkdm_sleep(clkdm);
343	return 0;
344}
345
346static void __init prcm_setup_regs(void)
347{
348	int i, num_mem_banks;
349	struct powerdomain *pwrdm;
350
351	/* Enable autoidle */
352	prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
353			  OMAP2_PRCM_SYSCONFIG_OFFSET);
354
355	/*
356	 * Set CORE powerdomain memory banks to retain their contents
357	 * during RETENTION
358	 */
359	num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
360	for (i = 0; i < num_mem_banks; i++)
361		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
362
363	/* Set CORE powerdomain's next power state to RETENTION */
364	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
365
366	/*
367	 * Set MPU powerdomain's next power state to RETENTION;
368	 * preserve logic state during retention
369	 */
370	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
371	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
372
373	/* Force-power down DSP, GFX powerdomains */
374
375	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
376	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
377	omap2_clkdm_sleep(dsp_clkdm);
378
379	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
380	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
381	omap2_clkdm_sleep(gfx_clkdm);
382
383	/*
384	 * Clear clockdomain wakeup dependencies and enable
385	 * hardware-supervised idle for all clkdms
386	 */
387	clkdm_for_each(clkdms_setup, NULL);
388	clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);
389
390	/* Enable clock autoidle for all domains */
391	cm_write_mod_reg(OMAP24XX_AUTO_CAM_MASK |
392			 OMAP24XX_AUTO_MAILBOXES_MASK |
393			 OMAP24XX_AUTO_WDT4_MASK |
394			 OMAP2420_AUTO_WDT3_MASK |
395			 OMAP24XX_AUTO_MSPRO_MASK |
396			 OMAP2420_AUTO_MMC_MASK |
397			 OMAP24XX_AUTO_FAC_MASK |
398			 OMAP2420_AUTO_EAC_MASK |
399			 OMAP24XX_AUTO_HDQ_MASK |
400			 OMAP24XX_AUTO_UART2_MASK |
401			 OMAP24XX_AUTO_UART1_MASK |
402			 OMAP24XX_AUTO_I2C2_MASK |
403			 OMAP24XX_AUTO_I2C1_MASK |
404			 OMAP24XX_AUTO_MCSPI2_MASK |
405			 OMAP24XX_AUTO_MCSPI1_MASK |
406			 OMAP24XX_AUTO_MCBSP2_MASK |
407			 OMAP24XX_AUTO_MCBSP1_MASK |
408			 OMAP24XX_AUTO_GPT12_MASK |
409			 OMAP24XX_AUTO_GPT11_MASK |
410			 OMAP24XX_AUTO_GPT10_MASK |
411			 OMAP24XX_AUTO_GPT9_MASK |
412			 OMAP24XX_AUTO_GPT8_MASK |
413			 OMAP24XX_AUTO_GPT7_MASK |
414			 OMAP24XX_AUTO_GPT6_MASK |
415			 OMAP24XX_AUTO_GPT5_MASK |
416			 OMAP24XX_AUTO_GPT4_MASK |
417			 OMAP24XX_AUTO_GPT3_MASK |
418			 OMAP24XX_AUTO_GPT2_MASK |
419			 OMAP2420_AUTO_VLYNQ_MASK |
420			 OMAP24XX_AUTO_DSS_MASK,
421			 CORE_MOD, CM_AUTOIDLE1);
422	cm_write_mod_reg(OMAP24XX_AUTO_UART3_MASK |
423			 OMAP24XX_AUTO_SSI_MASK |
424			 OMAP24XX_AUTO_USB_MASK,
425			 CORE_MOD, CM_AUTOIDLE2);
426	cm_write_mod_reg(OMAP24XX_AUTO_SDRC_MASK |
427			 OMAP24XX_AUTO_GPMC_MASK |
428			 OMAP24XX_AUTO_SDMA_MASK,
429			 CORE_MOD, CM_AUTOIDLE3);
430	cm_write_mod_reg(OMAP24XX_AUTO_PKA_MASK |
431			 OMAP24XX_AUTO_AES_MASK |
432			 OMAP24XX_AUTO_RNG_MASK |
433			 OMAP24XX_AUTO_SHA_MASK |
434			 OMAP24XX_AUTO_DES_MASK,
435			 CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
436
437	cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD,
438			 CM_AUTOIDLE);
439
440	/* Put DPLL and both APLLs into autoidle mode */
441	cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
442			 (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
443			 (0x03 << OMAP24XX_AUTO_54M_SHIFT),
444			 PLL_MOD, CM_AUTOIDLE);
445
446	cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK |
447			 OMAP24XX_AUTO_WDT1_MASK |
448			 OMAP24XX_AUTO_MPU_WDT_MASK |
449			 OMAP24XX_AUTO_GPIOS_MASK |
450			 OMAP24XX_AUTO_32KSYNC_MASK |
451			 OMAP24XX_AUTO_GPT1_MASK,
452			 WKUP_MOD, CM_AUTOIDLE);
453
454	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
455	 * stabilisation */
456	prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
457			  OMAP2_PRCM_CLKSSETUP_OFFSET);
458
459	/* Configure automatic voltage transition */
460	prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
461			  OMAP2_PRCM_VOLTSETUP_OFFSET);
462	prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK |
463			  (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
464			  OMAP24XX_MEMRETCTRL_MASK |
465			  (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) |
466			  (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT),
467			  OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET);
468
469	/* Enable wake-up events */
470	prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK,
471			  WKUP_MOD, PM_WKEN);
472}
473
474static int __init omap2_pm_init(void)
475{
476	u32 l;
477
478	if (!cpu_is_omap24xx())
479		return -ENODEV;
480
481	printk(KERN_INFO "Power Management for OMAP2 initializing\n");
482	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
483	printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
484
485	/* Look up important powerdomains */
486
487	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
488	if (!mpu_pwrdm)
489		pr_err("PM: mpu_pwrdm not found\n");
490
491	core_pwrdm = pwrdm_lookup("core_pwrdm");
492	if (!core_pwrdm)
493		pr_err("PM: core_pwrdm not found\n");
494
495	/* Look up important clockdomains */
496
497	mpu_clkdm = clkdm_lookup("mpu_clkdm");
498	if (!mpu_clkdm)
499		pr_err("PM: mpu_clkdm not found\n");
500
501	wkup_clkdm = clkdm_lookup("wkup_clkdm");
502	if (!wkup_clkdm)
503		pr_err("PM: wkup_clkdm not found\n");
504
505	dsp_clkdm = clkdm_lookup("dsp_clkdm");
506	if (!dsp_clkdm)
507		pr_err("PM: dsp_clkdm not found\n");
508
509	gfx_clkdm = clkdm_lookup("gfx_clkdm");
510	if (!gfx_clkdm)
511		pr_err("PM: gfx_clkdm not found\n");
512
513
514	osc_ck = clk_get(NULL, "osc_ck");
515	if (IS_ERR(osc_ck)) {
516		printk(KERN_ERR "could not get osc_ck\n");
517		return -ENODEV;
518	}
519
520	if (cpu_is_omap242x()) {
521		emul_ck = clk_get(NULL, "emul_ck");
522		if (IS_ERR(emul_ck)) {
523			printk(KERN_ERR "could not get emul_ck\n");
524			clk_put(osc_ck);
525			return -ENODEV;
526		}
527	}
528
529	prcm_setup_regs();
530
531	/* Hack to prevent MPU retention when STI console is enabled. */
532	{
533		const struct omap_sti_console_config *sti;
534
535		sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
536				      struct omap_sti_console_config);
537		if (sti != NULL && sti->enable)
538			sti_console_enabled = 1;
539	}
540
541	/*
542	 * We copy the assembler sleep/wakeup routines to SRAM.
543	 * These routines need to be in SRAM as that's the only
544	 * memory the MPU can see when it wakes up.
545	 */
546	if (cpu_is_omap24xx()) {
547		omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
548						 omap24xx_idle_loop_suspend_sz);
549
550		omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
551						    omap24xx_cpu_suspend_sz);
552	}
553
554	suspend_set_ops(&omap_pm_ops);
555	pm_idle = omap2_pm_idle;
556
557	return 0;
558}
559
560late_initcall(omap2_pm_init);
561