Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/alchemy/common/power.c
26481 views
1
/*
2
* BRIEF MODULE DESCRIPTION
3
* Au1xx0 Power Management routines.
4
*
5
* Copyright 2001, 2008 MontaVista Software Inc.
6
* Author: MontaVista Software, Inc. <[email protected]>
7
*
8
* Some of the routines are right out of init/main.c, whose
9
* copyrights apply here.
10
*
11
* This program is free software; you can redistribute it and/or modify it
12
* under the terms of the GNU General Public License as published by the
13
* Free Software Foundation; either version 2 of the License, or (at your
14
* option) any later version.
15
*
16
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*
27
* You should have received a copy of the GNU General Public License along
28
* with this program; if not, write to the Free Software Foundation, Inc.,
29
* 675 Mass Ave, Cambridge, MA 02139, USA.
30
*/
31
32
#include <linux/pm.h>
33
#include <linux/sysctl.h>
34
#include <linux/jiffies.h>
35
36
#include <linux/uaccess.h>
37
#include <asm/mach-au1x00/au1000.h>
38
39
/*
40
* We need to save/restore a bunch of core registers that are
41
* either volatile or reset to some state across a processor sleep.
42
* If reading a register doesn't provide a proper result for a
43
* later restore, we have to provide a function for loading that
44
* register and save a copy.
45
*
46
* We only have to save/restore registers that aren't otherwise
47
* done as part of a driver pm_* function.
48
*/
49
static unsigned int sleep_sys_clocks[5];
50
static unsigned int sleep_sys_pinfunc;
51
static unsigned int sleep_static_memctlr[4][3];
52
53
54
static void save_core_regs(void)
55
{
56
/* Clocks and PLLs. */
57
sleep_sys_clocks[0] = alchemy_rdsys(AU1000_SYS_FREQCTRL0);
58
sleep_sys_clocks[1] = alchemy_rdsys(AU1000_SYS_FREQCTRL1);
59
sleep_sys_clocks[2] = alchemy_rdsys(AU1000_SYS_CLKSRC);
60
sleep_sys_clocks[3] = alchemy_rdsys(AU1000_SYS_CPUPLL);
61
sleep_sys_clocks[4] = alchemy_rdsys(AU1000_SYS_AUXPLL);
62
63
/* pin mux config */
64
sleep_sys_pinfunc = alchemy_rdsys(AU1000_SYS_PINFUNC);
65
66
/* Save the static memory controller configuration. */
67
sleep_static_memctlr[0][0] = alchemy_rdsmem(AU1000_MEM_STCFG0);
68
sleep_static_memctlr[0][1] = alchemy_rdsmem(AU1000_MEM_STTIME0);
69
sleep_static_memctlr[0][2] = alchemy_rdsmem(AU1000_MEM_STADDR0);
70
sleep_static_memctlr[1][0] = alchemy_rdsmem(AU1000_MEM_STCFG1);
71
sleep_static_memctlr[1][1] = alchemy_rdsmem(AU1000_MEM_STTIME1);
72
sleep_static_memctlr[1][2] = alchemy_rdsmem(AU1000_MEM_STADDR1);
73
sleep_static_memctlr[2][0] = alchemy_rdsmem(AU1000_MEM_STCFG2);
74
sleep_static_memctlr[2][1] = alchemy_rdsmem(AU1000_MEM_STTIME2);
75
sleep_static_memctlr[2][2] = alchemy_rdsmem(AU1000_MEM_STADDR2);
76
sleep_static_memctlr[3][0] = alchemy_rdsmem(AU1000_MEM_STCFG3);
77
sleep_static_memctlr[3][1] = alchemy_rdsmem(AU1000_MEM_STTIME3);
78
sleep_static_memctlr[3][2] = alchemy_rdsmem(AU1000_MEM_STADDR3);
79
}
80
81
static void restore_core_regs(void)
82
{
83
/* restore clock configuration. Writing CPUPLL last will
84
* stall a bit and stabilize other clocks (unless this is
85
* one of those Au1000 with a write-only PLL, where we dont
86
* have a valid value)
87
*/
88
alchemy_wrsys(sleep_sys_clocks[0], AU1000_SYS_FREQCTRL0);
89
alchemy_wrsys(sleep_sys_clocks[1], AU1000_SYS_FREQCTRL1);
90
alchemy_wrsys(sleep_sys_clocks[2], AU1000_SYS_CLKSRC);
91
alchemy_wrsys(sleep_sys_clocks[4], AU1000_SYS_AUXPLL);
92
if (!au1xxx_cpu_has_pll_wo())
93
alchemy_wrsys(sleep_sys_clocks[3], AU1000_SYS_CPUPLL);
94
95
alchemy_wrsys(sleep_sys_pinfunc, AU1000_SYS_PINFUNC);
96
97
/* Restore the static memory controller configuration. */
98
alchemy_wrsmem(sleep_static_memctlr[0][0], AU1000_MEM_STCFG0);
99
alchemy_wrsmem(sleep_static_memctlr[0][1], AU1000_MEM_STTIME0);
100
alchemy_wrsmem(sleep_static_memctlr[0][2], AU1000_MEM_STADDR0);
101
alchemy_wrsmem(sleep_static_memctlr[1][0], AU1000_MEM_STCFG1);
102
alchemy_wrsmem(sleep_static_memctlr[1][1], AU1000_MEM_STTIME1);
103
alchemy_wrsmem(sleep_static_memctlr[1][2], AU1000_MEM_STADDR1);
104
alchemy_wrsmem(sleep_static_memctlr[2][0], AU1000_MEM_STCFG2);
105
alchemy_wrsmem(sleep_static_memctlr[2][1], AU1000_MEM_STTIME2);
106
alchemy_wrsmem(sleep_static_memctlr[2][2], AU1000_MEM_STADDR2);
107
alchemy_wrsmem(sleep_static_memctlr[3][0], AU1000_MEM_STCFG3);
108
alchemy_wrsmem(sleep_static_memctlr[3][1], AU1000_MEM_STTIME3);
109
alchemy_wrsmem(sleep_static_memctlr[3][2], AU1000_MEM_STADDR3);
110
}
111
112
void au_sleep(void)
113
{
114
save_core_regs();
115
116
switch (alchemy_get_cputype()) {
117
case ALCHEMY_CPU_AU1000:
118
case ALCHEMY_CPU_AU1500:
119
case ALCHEMY_CPU_AU1100:
120
alchemy_sleep_au1000();
121
break;
122
case ALCHEMY_CPU_AU1550:
123
case ALCHEMY_CPU_AU1200:
124
alchemy_sleep_au1550();
125
break;
126
case ALCHEMY_CPU_AU1300:
127
alchemy_sleep_au1300();
128
break;
129
}
130
131
restore_core_regs();
132
}
133
134