Blame view

arch/arm/mach-pnx4008/pm.c 3.63 KB
78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * arch/arm/mach-pnx4008/pm.c
   *
   * Power Management driver for PNX4008
   *
   * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
   *
   * 2005 (c) MontaVista Software, Inc. This file is licensed under
   * the terms of the GNU General Public License version 2. This program
   * is licensed "as is" without any warranty of any kind, whether express
   * or implied.
   */
  
  #include <linux/pm.h>
  #include <linux/rtc.h>
  #include <linux/sched.h>
  #include <linux/proc_fs.h>
95d9ffbe0   Rafael J. Wysocki   PM: Move definiti...
18
  #include <linux/suspend.h>
78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
19
20
  #include <linux/delay.h>
  #include <linux/clk.h>
fced80c73   Russell King   [ARM] Convert asm...
21
  #include <linux/io.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
22
  #include <linux/slab.h>
78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
23

78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
24
  #include <asm/cacheflush.h>
2781681ea   Russell King   ARM: PNX4008: rem...
25
26
  
  #include <mach/hardware.h>
a09e64fbc   Russell King   [ARM] Move includ...
27
28
  #include <mach/pm.h>
  #include <mach/clock.h>
78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  
  #define SRAM_VA IO_ADDRESS(PNX4008_IRAM_BASE)
  
  static void *saved_sram;
  
  static struct clk *pll4_clk;
  
  static inline void pnx4008_standby(void)
  {
  	void (*pnx4008_cpu_standby_ptr) (void);
  
  	local_irq_disable();
  	local_fiq_disable();
  
  	clk_disable(pll4_clk);
  
  	/*saving portion of SRAM to be used by suspend function. */
  	memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_standby_sz);
  
  	/*make sure SRAM copy gets physically written into SDRAM.
  	   SDRAM will be placed into self-refresh during power down */
  	flush_cache_all();
  
  	/*copy suspend function into SRAM */
  	memcpy((void *)SRAM_VA, pnx4008_cpu_standby, pnx4008_cpu_standby_sz);
  
  	/*do suspend */
  	pnx4008_cpu_standby_ptr = (void *)SRAM_VA;
  	pnx4008_cpu_standby_ptr();
  
  	/*restoring portion of SRAM that was used by suspend function */
  	memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_standby_sz);
  
  	clk_enable(pll4_clk);
  
  	local_fiq_enable();
  	local_irq_enable();
  }
  
  static inline void pnx4008_suspend(void)
  {
  	void (*pnx4008_cpu_suspend_ptr) (void);
  
  	local_irq_disable();
  	local_fiq_disable();
  
  	clk_disable(pll4_clk);
  
  	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
  	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
  
  	/*saving portion of SRAM to be used by suspend function. */
  	memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_suspend_sz);
  
  	/*make sure SRAM copy gets physically written into SDRAM.
  	   SDRAM will be placed into self-refresh during power down */
  	flush_cache_all();
  
  	/*copy suspend function into SRAM */
  	memcpy((void *)SRAM_VA, pnx4008_cpu_suspend, pnx4008_cpu_suspend_sz);
  
  	/*do suspend */
  	pnx4008_cpu_suspend_ptr = (void *)SRAM_VA;
  	pnx4008_cpu_suspend_ptr();
  
  	/*restoring portion of SRAM that was used by suspend function */
  	memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_suspend_sz);
  
  	clk_enable(pll4_clk);
  
  	local_fiq_enable();
  	local_irq_enable();
  }
  
  static int pnx4008_pm_enter(suspend_state_t state)
  {
  	switch (state) {
  	case PM_SUSPEND_STANDBY:
  		pnx4008_standby();
  		break;
  	case PM_SUSPEND_MEM:
  		pnx4008_suspend();
  		break;
78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
112
113
114
  	}
  	return 0;
  }
e8c9c5026   Johannes Berg   power management:...
115
  static int pnx4008_pm_valid(suspend_state_t state)
78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
116
  {
e8c9c5026   Johannes Berg   power management:...
117
118
  	return (state == PM_SUSPEND_STANDBY) ||
  	       (state == PM_SUSPEND_MEM);
78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
119
  }
2f55ac072   Lionel Debroux   suspend: constify...
120
  static const struct platform_suspend_ops pnx4008_pm_ops = {
78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
121
  	.enter = pnx4008_pm_enter,
e8c9c5026   Johannes Berg   power management:...
122
  	.valid = pnx4008_pm_valid,
78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  };
  
  static int __init pnx4008_pm_init(void)
  {
  	u32 sram_size_to_allocate;
  
  	pll4_clk = clk_get(0, "ck_pll4");
  	if (IS_ERR(pll4_clk)) {
  		printk(KERN_ERR
  		       "PM Suspend cannot acquire ARM(PLL4) clock control
  ");
  		return PTR_ERR(pll4_clk);
  	}
  
  	if (pnx4008_cpu_standby_sz > pnx4008_cpu_suspend_sz)
  		sram_size_to_allocate = pnx4008_cpu_standby_sz;
  	else
  		sram_size_to_allocate = pnx4008_cpu_suspend_sz;
  
  	saved_sram = kmalloc(sram_size_to_allocate, GFP_ATOMIC);
  	if (!saved_sram) {
  		printk(KERN_ERR
  		       "PM Suspend: cannot allocate memory to save portion of SRAM
  ");
  		clk_put(pll4_clk);
  		return -ENOMEM;
  	}
26398a70e   Rafael J. Wysocki   PM: Rename struct...
150
  	suspend_set_ops(&pnx4008_pm_ops);
78818e477   Vitaly Wool   [ARM] 3466/1: [2/...
151
152
153
154
  	return 0;
  }
  
  late_initcall(pnx4008_pm_init);