Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-davinci/pm.c
10699 views
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
29
static void (*davinci_sram_suspend) (struct davinci_pm_config *);
30
static struct davinci_pm_config *pdata;
31
32
static 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
38
static 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
97
static 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
113
static const struct platform_suspend_ops davinci_pm_ops = {
114
.enter = davinci_pm_enter,
115
.valid = suspend_valid_only_mem,
116
};
117
118
static 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
140
static 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
146
static 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
154
static int __init davinci_pm_init(void)
155
{
156
return platform_driver_probe(&davinci_pm_driver, davinci_pm_probe);
157
}
158
late_initcall(davinci_pm_init);
159
160