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-lpc32xx
pm.c
Go to the documentation of this file.
1
/*
2
* arch/arm/mach-lpc32xx/pm.c
3
*
4
* Original authors: Vitaly Wool, Dmitry Chigirev <
[email protected]
>
5
* Modified by Kevin Wells <
[email protected]
>
6
*
7
* 2005 (c) MontaVista Software, Inc. This file is licensed under
8
* the terms of the GNU General Public License version 2. This program
9
* is licensed "as is" without any warranty of any kind, whether express
10
* or implied.
11
*/
12
13
/*
14
* LPC32XX CPU and system power management
15
*
16
* The LPC32XX has three CPU modes for controlling system power: run,
17
* direct-run, and halt modes. When switching between halt and run modes,
18
* the CPU transistions through direct-run mode. For Linux, direct-run
19
* mode is not used in normal operation. Halt mode is used when the
20
* system is fully suspended.
21
*
22
* Run mode:
23
* The ARM CPU clock (HCLK_PLL), HCLK bus clock, and PCLK bus clocks are
24
* derived from the HCLK PLL. The HCLK and PCLK bus rates are divided from
25
* the HCLK_PLL rate. Linux runs in this mode.
26
*
27
* Direct-run mode:
28
* The ARM CPU clock, HCLK bus clock, and PCLK bus clocks are driven from
29
* SYSCLK. SYSCLK is usually around 13MHz, but may vary based on SYSCLK
30
* source or the frequency of the main oscillator. In this mode, the
31
* HCLK_PLL can be safely enabled, changed, or disabled.
32
*
33
* Halt mode:
34
* SYSCLK is gated off and the CPU and system clocks are halted.
35
* Peripherals based on the 32KHz oscillator clock (ie, RTC, touch,
36
* key scanner, etc.) still operate if enabled. In this state, an enabled
37
* system event (ie, GPIO state change, RTC match, key press, etc.) will
38
* wake the system up back into direct-run mode.
39
*
40
* DRAM refresh
41
* DRAM clocking and refresh are slightly different for systems with DDR
42
* DRAM or regular SDRAM devices. If SDRAM is used in the system, the
43
* SDRAM will still be accessible in direct-run mode. In DDR based systems,
44
* a transition to direct-run mode will stop all DDR accesses (no clocks).
45
* Because of this, the code to switch power modes and the code to enter
46
* and exit DRAM self-refresh modes must not be executed in DRAM. A small
47
* section of IRAM is used instead for this.
48
*
49
* Suspend is handled with the following logic:
50
* Backup a small area of IRAM used for the suspend code
51
* Copy suspend code to IRAM
52
* Transfer control to code in IRAM
53
* Places DRAMs in self-refresh mode
54
* Enter direct-run mode
55
* Save state of HCLK_PLL PLL
56
* Disable HCLK_PLL PLL
57
* Enter halt mode - CPU and buses will stop
58
* System enters direct-run mode when an enabled event occurs
59
* HCLK PLL state is restored
60
* Run mode is entered
61
* DRAMS are placed back into normal mode
62
* Code execution returns from IRAM
63
* IRAM code are used for suspend is restored
64
* Suspend mode is exited
65
*/
66
67
#include <
linux/suspend.h
>
68
#include <
linux/io.h
>
69
#include <linux/slab.h>
70
71
#include <asm/cacheflush.h>
72
73
#include <mach/hardware.h>
74
#include <mach/platform.h>
75
#include "
common.h
"
76
#include "
clock.h
"
77
78
#define TEMP_IRAM_AREA IO_ADDRESS(LPC32XX_IRAM_BASE)
79
80
/*
81
* Both STANDBY and MEM suspend states are handled the same with no
82
* loss of CPU or memory state
83
*/
84
static
int
lpc32xx_pm_enter(
suspend_state_t
state
)
85
{
86
int
(*lpc32xx_suspend_ptr) (
void
);
87
void
*iram_swap_area;
88
89
/* Allocate some space for temporary IRAM storage */
90
iram_swap_area =
kmalloc
(
lpc32xx_sys_suspend_sz
,
GFP_KERNEL
);
91
if
(!iram_swap_area) {
92
printk
(
KERN_ERR
93
"PM Suspend: cannot allocate memory to save portion "
94
"of SRAM\n"
);
95
return
-
ENOMEM
;
96
}
97
98
/* Backup a small area of IRAM used for the suspend code */
99
memcpy
(iram_swap_area, (
void
*)
TEMP_IRAM_AREA
,
100
lpc32xx_sys_suspend_sz
);
101
102
/*
103
* Copy code to suspend system into IRAM. The suspend code
104
* needs to run from IRAM as DRAM may no longer be available
105
* when the PLL is stopped.
106
*/
107
memcpy
((
void
*)
TEMP_IRAM_AREA
, &
lpc32xx_sys_suspend
,
108
lpc32xx_sys_suspend_sz
);
109
flush_icache_range
((
unsigned
long
)
TEMP_IRAM_AREA
,
110
(
unsigned
long
)(TEMP_IRAM_AREA) +
lpc32xx_sys_suspend_sz
);
111
112
/* Transfer to suspend code in IRAM */
113
lpc32xx_suspend_ptr = (
void
*) TEMP_IRAM_AREA;
114
flush_cache_all
();
115
(
void
) lpc32xx_suspend_ptr();
116
117
/* Restore original IRAM contents */
118
memcpy
((
void
*) TEMP_IRAM_AREA, iram_swap_area,
119
lpc32xx_sys_suspend_sz
);
120
121
kfree
(iram_swap_area);
122
123
return
0;
124
}
125
126
static
const
struct
platform_suspend_ops
lpc32xx_pm_ops = {
127
.valid =
suspend_valid_only_mem
,
128
.enter = lpc32xx_pm_enter,
129
};
130
131
#define EMC_DYN_MEM_CTRL_OFS 0x20
132
#define EMC_SRMMC (1 << 3)
133
#define EMC_CTRL_REG io_p2v(LPC32XX_EMC_BASE + EMC_DYN_MEM_CTRL_OFS)
134
static
int
__init
lpc32xx_pm_init(
void
)
135
{
136
/*
137
* Setup SDRAM self-refresh clock to automatically disable o
138
* start of self-refresh. This only needs to be done once.
139
*/
140
__raw_writel
(
__raw_readl
(
EMC_CTRL_REG
) |
EMC_SRMMC
,
EMC_CTRL_REG
);
141
142
suspend_set_ops
(&lpc32xx_pm_ops);
143
144
return
0;
145
}
146
arch_initcall
(lpc32xx_pm_init);
Generated on Thu Jan 10 2013 12:56:58 for Linux Kernel by
1.8.2