Blame view

arch/arm/mach-s3c/pm.c 4.17 KB
4490e3c68   Krzysztof Kozlowski   ARM: SAMSUNG: Add...
1
2
3
4
5
6
7
8
  // SPDX-License-Identifier: GPL-2.0
  //
  // Copyright 2008 Openmoko, Inc.
  // Copyright 2004-2008 Simtec Electronics
  //	Ben Dooks <ben@simtec.co.uk>
  //	http://armlinux.simtec.co.uk/
  //
  // S3C common power management (suspend to ram) support.
6419711a1   Ben Dooks   [ARM] S3C: Move P...
9
10
11
12
  
  #include <linux/init.h>
  #include <linux/suspend.h>
  #include <linux/errno.h>
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
13
  #include <linux/delay.h>
cd3fc1b9a   Tomasz Figa   ARM: SAMSUNG: pm:...
14
  #include <linux/of.h>
334a1c70b   Tushar Behera   ARM: SAMSUNG: Rep...
15
  #include <linux/serial_s3c.h>
6419711a1   Ben Dooks   [ARM] S3C: Move P...
16
  #include <linux/io.h>
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
17
  #include <asm/cacheflush.h>
2c74a0cef   Russell King   ARM: pm: hide 1st...
18
  #include <asm/suspend.h>
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
19

c6ff132d4   Arnd Bergmann   ARM: s3c: make he...
20
21
22
  #include "map.h"
  #include "regs-clock.h"
  #include "regs-irq.h"
7ba8022fc   Arnd Bergmann   ARM: exynos: prep...
23
  #include <mach/irqs.h>
d6280ffb4   Tomasz Figa   ARM: SAMSUNG: Inc...
24

56b344268   Ben Dooks   [ARM] S3C: Make I...
25
  #include <asm/irq.h>
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
26

c6ff132d4   Arnd Bergmann   ARM: s3c: make he...
27
28
29
  #include "cpu.h"
  #include "pm.h"
  #include "pm-core.h"
6419711a1   Ben Dooks   [ARM] S3C: Move P...
30
31
32
33
  
  /* for external use */
  
  unsigned long s3c_pm_flags;
56b344268   Ben Dooks   [ARM] S3C: Make I...
34
35
36
37
38
  /* The IRQ ext-int code goes here, it is too small to currently bother
   * with its own file. */
  
  unsigned long s3c_irqwake_intmask	= 0xffffffffL;
  unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
f5aeffb78   Mark Brown   ARM: SAMSUNG: Con...
39
  int s3c_irqext_wake(struct irq_data *data, unsigned int state)
56b344268   Ben Dooks   [ARM] S3C: Make I...
40
  {
f5aeffb78   Mark Brown   ARM: SAMSUNG: Con...
41
  	unsigned long bit = 1L << IRQ_EINT_BIT(data->irq);
56b344268   Ben Dooks   [ARM] S3C: Make I...
42
43
44
45
46
47
  
  	if (!(s3c_irqwake_eintallow & bit))
  		return -ENOENT;
  
  	printk(KERN_INFO "wake %s for irq %d
  ",
f5aeffb78   Mark Brown   ARM: SAMSUNG: Con...
48
  	       state ? "enabled" : "disabled", data->irq);
56b344268   Ben Dooks   [ARM] S3C: Make I...
49
50
51
52
53
54
55
56
  
  	if (!state)
  		s3c_irqwake_eintmask |= bit;
  	else
  		s3c_irqwake_eintmask &= ~bit;
  
  	return 0;
  }
6419711a1   Ben Dooks   [ARM] S3C: Move P...
57

2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
58
  void (*pm_cpu_prep)(void);
29cb3cd20   Russell King   ARM: pm: allow su...
59
  int (*pm_cpu_sleep)(unsigned long);
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
60
61
62
63
64
65
66
67
68
69
  
  #define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
  
  /* s3c_pm_enter
   *
   * central control for sleep/resume process
  */
  
  static int s3c_pm_enter(suspend_state_t state)
  {
d3fcacf52   Abhilash Kesavan   ARM: SAMSUNG: Gra...
70
  	int ret;
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
71
  	/* ensure the debug is initialised (if enabled) */
1e574a665   Arnd Bergmann   ARM: samsung: rem...
72
  	s3c_pm_debug_init_uart();
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  
  	S3C_PMDBG("%s(%d)
  ", __func__, state);
  
  	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
  		printk(KERN_ERR "%s: error: no cpu sleep function
  ", __func__);
  		return -EINVAL;
  	}
  
  	/* check if we have anything to wake-up with... bad things seem
  	 * to happen if you suspend with no wakeup (system will often
  	 * require a full power-cycle)
  	*/
cd3fc1b9a   Tomasz Figa   ARM: SAMSUNG: pm:...
87
88
  	if (!of_have_populated_dt() &&
  	    !any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
89
90
91
92
93
94
95
  	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
  		printk(KERN_ERR "%s: No wake-up sources!
  ", __func__);
  		printk(KERN_ERR "%s: Aborting sleep
  ", __func__);
  		return -EINVAL;
  	}
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
96
  	/* save all necessary core registers not covered by the drivers */
cd3fc1b9a   Tomasz Figa   ARM: SAMSUNG: pm:...
97
98
99
100
  	if (!of_have_populated_dt()) {
  		samsung_pm_save_gpios();
  		samsung_pm_saved_gpios();
  	}
dbd6fefb5   Arnd Bergmann   ARM: samsung: mak...
101
  	s3c_pm_save_uarts(soc_is_s3c2410());
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  	s3c_pm_save_core();
  
  	/* set the irq configuration for wake */
  
  	s3c_pm_configure_extint();
  
  	S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx
  ",
  	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
  
  	s3c_pm_arch_prepare_irqs();
  
  	/* call cpu specific preparation */
  
  	pm_cpu_prep();
  
  	/* flush cache back to ram */
  
  	flush_cache_all();
  
  	s3c_pm_check_store();
  
  	/* send the cpu to sleep... */
  
  	s3c_pm_arch_stop_clocks();
e7089da95   Russell King   ARM: pm: samsung:...
127
  	/* this will also act as our return point from when
fff94cd9f   Ben Dooks   [ARM] S3C: Tidy s...
128
129
  	 * we resume as it saves its own register state and restores it
  	 * during the resume.  */
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
130

d3fcacf52   Abhilash Kesavan   ARM: SAMSUNG: Gra...
131
132
133
  	ret = cpu_suspend(0, pm_cpu_sleep);
  	if (ret)
  		return ret;
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
134

2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
135
136
137
  	/* restore the system state */
  
  	s3c_pm_restore_core();
dbd6fefb5   Arnd Bergmann   ARM: samsung: mak...
138
  	s3c_pm_restore_uarts(soc_is_s3c2410());
cd3fc1b9a   Tomasz Figa   ARM: SAMSUNG: pm:...
139
140
141
142
143
  
  	if (!of_have_populated_dt()) {
  		samsung_pm_restore_gpios();
  		s3c_pm_restored_gpios();
  	}
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
144

1e574a665   Arnd Bergmann   ARM: samsung: rem...
145
  	s3c_pm_debug_init_uart();
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
146
147
148
149
150
151
152
  
  	/* check what irq (if any) restored the system */
  
  	s3c_pm_arch_show_resume_irqs();
  
  	S3C_PMDBG("%s: post sleep, preparing to return
  ", __func__);
bd117bd16   Ben Dooks   [ARM] S3C64XX: In...
153
154
  	/* LEDs should now be 1110 */
  	s3c_pm_debug_smdkled(1 << 1, 0);
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
155
156
157
158
159
160
161
162
  	s3c_pm_check_restore();
  
  	/* ok, let's return from sleep */
  
  	S3C_PMDBG("S3C PM Resume (post-restore)
  ");
  	return 0;
  }
aa8aba694   Ben Dooks   [ARM] S3C: Do not...
163
164
165
166
167
168
169
170
171
172
173
174
  static int s3c_pm_prepare(void)
  {
  	/* prepare check area if configured */
  
  	s3c_pm_check_prepare();
  	return 0;
  }
  
  static void s3c_pm_finish(void)
  {
  	s3c_pm_check_cleanup();
  }
2f55ac072   Lionel Debroux   suspend: constify...
175
  static const struct platform_suspend_ops s3c_pm_ops = {
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
176
  	.enter		= s3c_pm_enter,
aa8aba694   Ben Dooks   [ARM] S3C: Do not...
177
178
  	.prepare	= s3c_pm_prepare,
  	.finish		= s3c_pm_finish,
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
179
180
  	.valid		= suspend_valid_only_mem,
  };
4e59c25dc   Ben Dooks   [ARM] S3C: Rename...
181
  /* s3c_pm_init
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
182
183
184
185
186
   *
   * Attach the power management functions. This should be called
   * from the board specific initialisation if the board supports
   * it.
  */
4e59c25dc   Ben Dooks   [ARM] S3C: Rename...
187
  int __init s3c_pm_init(void)
2261e0e6e   Ben Dooks   [ARM] S3C: Move p...
188
189
190
191
192
193
194
  {
  	printk("S3C Power Management, Copyright 2004 Simtec Electronics
  ");
  
  	suspend_set_ops(&s3c_pm_ops);
  	return 0;
  }