Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
arm
mach-s5p64x0
pm.c
Go to the documentation of this file.
1
/* linux/arch/arm/mach-s5p64x0/pm.c
2
*
3
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
4
* http://www.samsung.com
5
*
6
* S5P64X0 Power Management Support
7
*
8
* Based on arch/arm/mach-s3c64xx/pm.c by Ben Dooks
9
*
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License version 2 as
12
* published by the Free Software Foundation.
13
*/
14
15
#include <
linux/suspend.h
>
16
#include <
linux/syscore_ops.h
>
17
#include <
linux/io.h
>
18
19
#include <plat/cpu.h>
20
#include <
plat/pm.h
>
21
#include <
plat/regs-timer.h
>
22
#include <
plat/wakeup-mask.h
>
23
24
#include <mach/regs-clock.h>
25
#include <mach/regs-gpio.h>
26
27
static
struct
sleep_save
s5p64x0_core_save[] = {
28
SAVE_ITEM
(
S5P64X0_APLL_CON
),
29
SAVE_ITEM
(
S5P64X0_MPLL_CON
),
30
SAVE_ITEM
(
S5P64X0_EPLL_CON
),
31
SAVE_ITEM
(
S5P64X0_EPLL_CON_K
),
32
SAVE_ITEM
(
S5P64X0_CLK_SRC0
),
33
SAVE_ITEM
(
S5P64X0_CLK_SRC1
),
34
SAVE_ITEM
(
S5P64X0_CLK_DIV0
),
35
SAVE_ITEM
(
S5P64X0_CLK_DIV1
),
36
SAVE_ITEM
(
S5P64X0_CLK_DIV2
),
37
SAVE_ITEM
(
S5P64X0_CLK_DIV3
),
38
SAVE_ITEM
(
S5P64X0_CLK_GATE_MEM0
),
39
SAVE_ITEM
(
S5P64X0_CLK_GATE_HCLK1
),
40
SAVE_ITEM
(
S5P64X0_CLK_GATE_SCLK1
),
41
};
42
43
static
struct
sleep_save
s5p64x0_misc_save[] = {
44
SAVE_ITEM
(
S5P64X0_AHB_CON0
),
45
SAVE_ITEM
(
S5P64X0_SPCON0
),
46
SAVE_ITEM
(
S5P64X0_SPCON1
),
47
SAVE_ITEM
(
S5P64X0_MEM0CONSLP0
),
48
SAVE_ITEM
(
S5P64X0_MEM0CONSLP1
),
49
SAVE_ITEM
(
S5P64X0_MEM0DRVCON
),
50
SAVE_ITEM
(
S5P64X0_MEM1DRVCON
),
51
52
SAVE_ITEM
(
S3C64XX_TINT_CSTAT
),
53
};
54
55
/* DPLL is present only in S5P6450 */
56
static
struct
sleep_save
s5p6450_core_save[] = {
57
SAVE_ITEM
(
S5P6450_DPLL_CON
),
58
SAVE_ITEM
(
S5P6450_DPLL_CON_K
),
59
};
60
61
void
s3c_pm_configure_extint
(
void
)
62
{
63
__raw_writel
(
s3c_irqwake_eintmask
,
S5P64X0_EINT_WAKEUP_MASK
);
64
}
65
66
void
s3c_pm_restore_core
(
void
)
67
{
68
__raw_writel
(0,
S5P64X0_EINT_WAKEUP_MASK
);
69
70
s3c_pm_do_restore_core
(s5p64x0_core_save,
71
ARRAY_SIZE
(s5p64x0_core_save));
72
73
if
(
soc_is_s5p6450
())
74
s3c_pm_do_restore_core
(s5p6450_core_save,
75
ARRAY_SIZE
(s5p6450_core_save));
76
77
s3c_pm_do_restore
(s5p64x0_misc_save,
ARRAY_SIZE
(s5p64x0_misc_save));
78
}
79
80
void
s3c_pm_save_core
(
void
)
81
{
82
s3c_pm_do_save
(s5p64x0_misc_save,
ARRAY_SIZE
(s5p64x0_misc_save));
83
84
if
(
soc_is_s5p6450
())
85
s3c_pm_do_save
(s5p6450_core_save,
86
ARRAY_SIZE
(s5p6450_core_save));
87
88
s3c_pm_do_save
(s5p64x0_core_save,
ARRAY_SIZE
(s5p64x0_core_save));
89
}
90
91
static
int
s5p64x0_cpu_suspend(
unsigned
long
arg
)
92
{
93
unsigned
long
tmp
= 0;
94
95
/*
96
* Issue the standby signal into the pm unit. Note, we
97
* issue a write-buffer drain just in case.
98
*/
99
asm
(
"b 1f\n\t"
100
".align 5\n\t"
101
"1:\n\t"
102
"mcr p15, 0, %0, c7, c10, 5\n\t"
103
"mcr p15, 0, %0, c7, c10, 4\n\t"
104
"mcr p15, 0, %0, c7, c0, 4"
: :
"r"
(
tmp
));
105
106
/* we should never get past here */
107
panic
(
"sleep resumed to originator?"
);
108
}
109
110
/* mapping of interrupts to parts of the wakeup mask */
111
static
struct
samsung_wakeup_mask
s5p64x0_wake_irqs[] = {
112
{ .irq =
IRQ_RTC_ALARM
, .bit =
S5P64X0_PWR_CFG_RTC_ALRM_DISABLE
, },
113
{ .irq =
IRQ_RTC_TIC
, .bit =
S5P64X0_PWR_CFG_RTC_TICK_DISABLE
, },
114
{ .irq =
IRQ_HSMMC0
, .bit =
S5P64X0_PWR_CFG_MMC0_DISABLE
, },
115
{ .irq =
IRQ_HSMMC1
, .bit =
S5P64X0_PWR_CFG_MMC1_DISABLE
, },
116
};
117
118
static
void
s5p64x0_pm_prepare(
void
)
119
{
120
u32
tmp
;
121
122
samsung_sync_wakemask
(
S5P64X0_PWR_CFG
,
123
s5p64x0_wake_irqs,
ARRAY_SIZE
(s5p64x0_wake_irqs));
124
125
/* store the resume address in INFORM0 register */
126
__raw_writel
(
virt_to_phys
(
s3c_cpu_resume
),
S5P64X0_INFORM0
);
127
128
/* setup clock gating for FIMGVG block */
129
__raw_writel
((
__raw_readl
(
S5P64X0_CLK_GATE_HCLK1
) | \
130
(
S5P64X0_CLK_GATE_HCLK1_FIMGVG
)),
S5P64X0_CLK_GATE_HCLK1
);
131
__raw_writel
((
__raw_readl
(
S5P64X0_CLK_GATE_SCLK1
) | \
132
(
S5P64X0_CLK_GATE_SCLK1_FIMGVG
)),
S5P64X0_CLK_GATE_SCLK1
);
133
134
/* Configure the stabilization counter with wait time required */
135
__raw_writel
(
S5P64X0_PWR_STABLE_PWR_CNT_VAL4
,
S5P64X0_PWR_STABLE
);
136
137
/* set WFI to SLEEP mode configuration */
138
tmp =
__raw_readl
(
S5P64X0_SLEEP_CFG
);
139
tmp &= ~(
S5P64X0_SLEEP_CFG_OSC_EN
);
140
__raw_writel
(tmp,
S5P64X0_SLEEP_CFG
);
141
142
tmp =
__raw_readl
(
S5P64X0_PWR_CFG
);
143
tmp &= ~(
S5P64X0_PWR_CFG_WFI_MASK
);
144
tmp |=
S5P64X0_PWR_CFG_WFI_SLEEP
;
145
__raw_writel
(tmp,
S5P64X0_PWR_CFG
);
146
147
/*
148
* set OTHERS register to disable interrupt before going to
149
* sleep. This bit is present only in S5P6450, it is reserved
150
* in S5P6440.
151
*/
152
if
(
soc_is_s5p6450
()) {
153
tmp =
__raw_readl
(
S5P64X0_OTHERS
);
154
tmp |=
S5P6450_OTHERS_DISABLE_INT
;
155
__raw_writel
(tmp,
S5P64X0_OTHERS
);
156
}
157
158
/* ensure previous wakeup state is cleared before sleeping */
159
__raw_writel
(
__raw_readl
(
S5P64X0_WAKEUP_STAT
),
S5P64X0_WAKEUP_STAT
);
160
161
}
162
163
static
int
s5p64x0_pm_add(
struct
device
*
dev
,
struct
subsys_interface
*sif)
164
{
165
pm_cpu_prep
= s5p64x0_pm_prepare;
166
pm_cpu_sleep
= s5p64x0_cpu_suspend;
167
pm_uart_udivslot
= 1;
168
169
return
0;
170
}
171
172
static
struct
subsys_interface
s5p64x0_pm_interface = {
173
.name =
"s5p64x0_pm"
,
174
.subsys = &
s5p64x0_subsys
,
175
.add_dev = s5p64x0_pm_add,
176
};
177
178
static
__init
int
s5p64x0_pm_drvinit(
void
)
179
{
180
s3c_pm_init
();
181
182
return
subsys_interface_register
(&s5p64x0_pm_interface);
183
}
184
arch_initcall
(s5p64x0_pm_drvinit);
185
186
static
void
s5p64x0_pm_resume(
void
)
187
{
188
u32
tmp
;
189
190
tmp =
__raw_readl
(
S5P64X0_OTHERS
);
191
tmp |= (
S5P64X0_OTHERS_RET_MMC0
|
S5P64X0_OTHERS_RET_MMC1
| \
192
S5P64X0_OTHERS_RET_UART);
193
__raw_writel
(tmp ,
S5P64X0_OTHERS
);
194
}
195
196
static
struct
syscore_ops
s5p64x0_pm_syscore_ops = {
197
.resume = s5p64x0_pm_resume,
198
};
199
200
static
__init
int
s5p64x0_pm_syscore_init(
void
)
201
{
202
register_syscore_ops
(&s5p64x0_pm_syscore_ops);
203
204
return
0;
205
}
206
arch_initcall
(s5p64x0_pm_syscore_init);
Generated on Thu Jan 10 2013 12:56:59 for Linux Kernel by
1.8.2