• 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-davinci/
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};
117
118static int __init davinci_pm_probe(struct platform_device *pdev)
119{
120	pdata = pdev->dev.platform_data;
121	if (!pdata) {
122		dev_err(&pdev->dev, "cannot get platform data\n");
123		return -ENOENT;
124	}
125
126	davinci_sram_suspend = sram_alloc(davinci_cpu_suspend_sz, NULL);
127	if (!davinci_sram_suspend) {
128		dev_err(&pdev->dev, "cannot allocate SRAM memory\n");
129		return -ENOMEM;
130	}
131
132	davinci_sram_push(davinci_sram_suspend, davinci_cpu_suspend,
133						davinci_cpu_suspend_sz);
134
135	suspend_set_ops(&davinci_pm_ops);
136
137	return 0;
138}
139
140static int __exit davinci_pm_remove(struct platform_device *pdev)
141{
142	sram_free(davinci_sram_suspend, davinci_cpu_suspend_sz);
143	return 0;
144}
145
146static struct platform_driver davinci_pm_driver = {
147	.driver = {
148		.name	 = "pm-davinci",
149		.owner	 = THIS_MODULE,
150	},
151	.remove = __exit_p(davinci_pm_remove),
152};
153
154static int __init davinci_pm_init(void)
155{
156	return platform_driver_probe(&davinci_pm_driver, davinci_pm_probe);
157}
158late_initcall(davinci_pm_init);
159