aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-davinci/Makefile1
-rw-r--r--arch/arm/mach-davinci/include/mach/memory.h1
-rw-r--r--arch/arm/mach-davinci/include/mach/pm.h54
-rw-r--r--arch/arm/mach-davinci/pm.c158
-rw-r--r--arch/arm/mach-davinci/sleep.S224
5 files changed, 438 insertions, 0 deletions
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index eeb9230d8844..d0fed3a67100 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o
34# Power Management 34# Power Management
35obj-$(CONFIG_CPU_FREQ) += cpufreq.o 35obj-$(CONFIG_CPU_FREQ) += cpufreq.o
36obj-$(CONFIG_CPU_IDLE) += cpuidle.o 36obj-$(CONFIG_CPU_IDLE) += cpuidle.o
37obj-$(CONFIG_SUSPEND) += pm.o sleep.o
diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h
index 7aeaf46cade0..a91edfb8beea 100644
--- a/arch/arm/mach-davinci/include/mach/memory.h
+++ b/arch/arm/mach-davinci/include/mach/memory.h
@@ -33,6 +33,7 @@
33 33
34#define DDR2_SDRCR_OFFSET 0xc 34#define DDR2_SDRCR_OFFSET 0xc
35#define DDR2_SRPD_BIT BIT(23) 35#define DDR2_SRPD_BIT BIT(23)
36#define DDR2_MCLKSTOPEN_BIT BIT(30)
36#define DDR2_LPMODEN_BIT BIT(31) 37#define DDR2_LPMODEN_BIT BIT(31)
37 38
38/* 39/*
diff --git a/arch/arm/mach-davinci/include/mach/pm.h b/arch/arm/mach-davinci/include/mach/pm.h
new file mode 100644
index 000000000000..37b19bf35a85
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/pm.h
@@ -0,0 +1,54 @@
1/*
2 * TI DaVinci platform support for power management.
3 *
4 * Copyright (C) 2009 Texas Instruments, Inc. http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11 * kind, whether express or implied; without even the implied warranty
12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15#ifndef _MACH_DAVINCI_PM_H
16#define _MACH_DAVINCI_PM_H
17
18/*
19 * Caution: Assembly code in sleep.S makes assumtion on the order
20 * of the members of this structure.
21 */
22struct davinci_pm_config {
23 void __iomem *ddr2_ctlr_base;
24 void __iomem *ddrpsc_reg_base;
25 int ddrpsc_num;
26 void __iomem *ddrpll_reg_base;
27 void __iomem *deepsleep_reg;
28 void __iomem *cpupll_reg_base;
29 /*
30 * Note on SLEEPCOUNT:
31 * The SLEEPCOUNT feature is mainly intended for cases in which
32 * the internal oscillator is used. The internal oscillator is
33 * fully disabled in deep sleep mode. When you exist deep sleep
34 * mode, the oscillator will be turned on and will generate very
35 * small oscillations which will not be detected by the deep sleep
36 * counter. Eventually those oscillations will grow to an amplitude
37 * large enough to start incrementing the deep sleep counter.
38 * In this case recommendation from hardware engineers is that the
39 * SLEEPCOUNT be set to 4096. This means that 4096 valid clock cycles
40 * must be detected before the clock is passed to the rest of the
41 * system.
42 * In the case that the internal oscillator is not used and the
43 * clock is generated externally, the SLEEPCOUNT value can be very
44 * small since the clock input is assumed to be stable before SoC
45 * is taken out of deepsleep mode. A value of 128 would be more than
46 * adequate.
47 */
48 int sleepcount;
49};
50
51extern unsigned int davinci_cpu_suspend_sz;
52extern void davinci_cpu_suspend(struct davinci_pm_config *);
53
54#endif
diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c
new file mode 100644
index 000000000000..fab953b43dea
--- /dev/null
+++ b/arch/arm/mach-davinci/pm.c
@@ -0,0 +1,158 @@
1/*
2 * DaVinci Power Management Routines
3 *
4 * Copyright (C) 2009 Texas Instruments, Inc. http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/pm.h>
12#include <linux/suspend.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/clk.h>
16#include <linux/spinlock.h>
17
18#include <asm/cacheflush.h>
19#include <asm/delay.h>
20
21#include <mach/da8xx.h>
22#include <mach/sram.h>
23#include <mach/pm.h>
24
25#include "clock.h"
26
27#define DEEPSLEEP_SLEEPCOUNT_MASK 0xFFFF
28
29static void (*davinci_sram_suspend) (struct davinci_pm_config *);
30static struct davinci_pm_config *pdata;
31
32static void davinci_sram_push(void *dest, void *src, unsigned int size)
33{
34 memcpy(dest, src, size);
35 flush_icache_range((unsigned long)dest, (unsigned long)(dest + size));
36}
37
38static void davinci_pm_suspend(void)
39{
40 unsigned val;
41
42 if (pdata->cpupll_reg_base != pdata->ddrpll_reg_base) {
43
44 /* Switch CPU PLL to bypass mode */
45 val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
46 val &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
47 __raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
48
49 udelay(PLL_BYPASS_TIME);
50
51 /* Powerdown CPU PLL */
52 val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
53 val |= PLLCTL_PLLPWRDN;
54 __raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
55 }
56
57 /* Configure sleep count in deep sleep register */
58 val = __raw_readl(pdata->deepsleep_reg);
59 val &= ~DEEPSLEEP_SLEEPCOUNT_MASK,
60 val |= pdata->sleepcount;
61 __raw_writel(val, pdata->deepsleep_reg);
62
63 /* System goes to sleep in this call */
64 davinci_sram_suspend(pdata);
65
66 if (pdata->cpupll_reg_base != pdata->ddrpll_reg_base) {
67
68 /* put CPU PLL in reset */
69 val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
70 val &= ~PLLCTL_PLLRST;
71 __raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
72
73 /* put CPU PLL in power down */
74 val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
75 val &= ~PLLCTL_PLLPWRDN;
76 __raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
77
78 /* wait for CPU PLL reset */
79 udelay(PLL_RESET_TIME);
80
81 /* bring CPU PLL out of reset */
82 val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
83 val |= PLLCTL_PLLRST;
84 __raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
85
86 /* Wait for CPU PLL to lock */
87 udelay(PLL_LOCK_TIME);
88
89 /* Remove CPU PLL from bypass mode */
90 val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
91 val &= ~PLLCTL_PLLENSRC;
92 val |= PLLCTL_PLLEN;
93 __raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
94 }
95}
96
97static int davinci_pm_enter(suspend_state_t state)
98{
99 int ret = 0;
100
101 switch (state) {
102 case PM_SUSPEND_STANDBY:
103 case PM_SUSPEND_MEM:
104 davinci_pm_suspend();
105 break;
106 default:
107 ret = -EINVAL;
108 }
109
110 return ret;
111}
112
113static struct platform_suspend_ops davinci_pm_ops = {
114 .enter = davinci_pm_enter,
115 .valid = suspend_valid_only_mem,
116};