diff options
author | Alexander Graf <agraf@suse.de> | 2014-10-13 10:01:09 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2014-11-02 20:12:51 -0500 |
commit | 9178ba294b6839eeff1a91bed95515d783f3ee6c (patch) | |
tree | 61252a8808bba5208c7b7c0f0af31301278272de | |
parent | 0df1f2487d2f0d04703f142813d53615d62a1da4 (diff) |
powerpc: Convert power off logic to pm_power_off
The generic Linux framework to power off the machine is a function pointer
called pm_power_off. The trick about this pointer is that device drivers can
potentially implement it rather than board files.
Today on powerpc we set pm_power_off to invoke our generic full machine power
off logic which then calls ppc_md.power_off to invoke machine specific power
off.
However, when we want to add a power off GPIO via the "gpio-poweroff" driver,
this card house falls apart. That driver only registers itself if pm_power_off
is NULL to ensure it doesn't override board specific logic. However, since we
always set pm_power_off to the generic power off logic (which will just not
power off the machine if no ppc_md.power_off call is implemented), we can't
implement power off via the generic GPIO power off driver.
To fix this up, let's get rid of the ppc_md.power_off logic and just always use
pm_power_off as was intended. Then individual drivers such as the GPIO power off
driver can implement power off logic via that function pointer.
With this patch set applied and a few patches on top of QEMU that implement a
power off GPIO on the virt e500 machine, I can successfully turn off my virtual
machine after halt.
Signed-off-by: Alexander Graf <agraf@suse.de>
[mpe: Squash into one patch and update changelog based on cover letter]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
21 files changed, 66 insertions, 58 deletions
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 307347f8ddbd..f15f15c92544 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -142,7 +142,6 @@ struct machdep_calls { | |||
142 | #endif | 142 | #endif |
143 | 143 | ||
144 | void (*restart)(char *cmd); | 144 | void (*restart)(char *cmd); |
145 | void (*power_off)(void); | ||
146 | void (*halt)(void); | 145 | void (*halt)(void); |
147 | void (*panic)(char *str); | 146 | void (*panic)(char *str); |
148 | void (*cpu_die)(void); | 147 | void (*cpu_die)(void); |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 1362cd62b3fa..44c8d03558ac 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -139,8 +139,8 @@ void machine_restart(char *cmd) | |||
139 | void machine_power_off(void) | 139 | void machine_power_off(void) |
140 | { | 140 | { |
141 | machine_shutdown(); | 141 | machine_shutdown(); |
142 | if (ppc_md.power_off) | 142 | if (pm_power_off) |
143 | ppc_md.power_off(); | 143 | pm_power_off(); |
144 | #ifdef CONFIG_SMP | 144 | #ifdef CONFIG_SMP |
145 | smp_send_stop(); | 145 | smp_send_stop(); |
146 | #endif | 146 | #endif |
@@ -151,7 +151,7 @@ void machine_power_off(void) | |||
151 | /* Used by the G5 thermal driver */ | 151 | /* Used by the G5 thermal driver */ |
152 | EXPORT_SYMBOL_GPL(machine_power_off); | 152 | EXPORT_SYMBOL_GPL(machine_power_off); |
153 | 153 | ||
154 | void (*pm_power_off)(void) = machine_power_off; | 154 | void (*pm_power_off)(void); |
155 | EXPORT_SYMBOL_GPL(pm_power_off); | 155 | EXPORT_SYMBOL_GPL(pm_power_off); |
156 | 156 | ||
157 | void machine_halt(void) | 157 | void machine_halt(void) |
diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c index 58db9d083969..c11ce6516c8f 100644 --- a/arch/powerpc/platforms/44x/ppc476.c +++ b/arch/powerpc/platforms/44x/ppc476.c | |||
@@ -94,7 +94,7 @@ static int avr_probe(struct i2c_client *client, | |||
94 | { | 94 | { |
95 | avr_i2c_client = client; | 95 | avr_i2c_client = client; |
96 | ppc_md.restart = avr_reset_system; | 96 | ppc_md.restart = avr_reset_system; |
97 | ppc_md.power_off = avr_power_off_system; | 97 | pm_power_off = avr_power_off_system; |
98 | return 0; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 3feffde9128d..6af651e69129 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c | |||
@@ -212,6 +212,8 @@ static int __init efika_probe(void) | |||
212 | DMA_MODE_READ = 0x44; | 212 | DMA_MODE_READ = 0x44; |
213 | DMA_MODE_WRITE = 0x48; | 213 | DMA_MODE_WRITE = 0x48; |
214 | 214 | ||
215 | pm_power_off = rtas_power_off; | ||
216 | |||
215 | return 1; | 217 | return 1; |
216 | } | 218 | } |
217 | 219 | ||
@@ -225,7 +227,6 @@ define_machine(efika) | |||
225 | .init_IRQ = mpc52xx_init_irq, | 227 | .init_IRQ = mpc52xx_init_irq, |
226 | .get_irq = mpc52xx_get_irq, | 228 | .get_irq = mpc52xx_get_irq, |
227 | .restart = rtas_restart, | 229 | .restart = rtas_restart, |
228 | .power_off = rtas_power_off, | ||
229 | .halt = rtas_halt, | 230 | .halt = rtas_halt, |
230 | .set_rtc_time = rtas_set_rtc_time, | 231 | .set_rtc_time = rtas_set_rtc_time, |
231 | .get_rtc_time = rtas_get_rtc_time, | 232 | .get_rtc_time = rtas_get_rtc_time, |
diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c index 463fa91ee5b6..15e8021ddef9 100644 --- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c +++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c | |||
@@ -167,10 +167,10 @@ static int mcu_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
167 | if (ret) | 167 | if (ret) |
168 | goto err; | 168 | goto err; |
169 | 169 | ||
170 | /* XXX: this is potentially racy, but there is no lock for ppc_md */ | 170 | /* XXX: this is potentially racy, but there is no lock for pm_power_off */ |
171 | if (!ppc_md.power_off) { | 171 | if (!pm_power_off) { |
172 | glob_mcu = mcu; | 172 | glob_mcu = mcu; |
173 | ppc_md.power_off = mcu_power_off; | 173 | pm_power_off = mcu_power_off; |
174 | dev_info(&client->dev, "will provide power-off service\n"); | 174 | dev_info(&client->dev, "will provide power-off service\n"); |
175 | } | 175 | } |
176 | 176 | ||
@@ -197,7 +197,7 @@ static int mcu_remove(struct i2c_client *client) | |||
197 | device_remove_file(&client->dev, &dev_attr_status); | 197 | device_remove_file(&client->dev, &dev_attr_status); |
198 | 198 | ||
199 | if (glob_mcu == mcu) { | 199 | if (glob_mcu == mcu) { |
200 | ppc_md.power_off = NULL; | 200 | pm_power_off = NULL; |
201 | glob_mcu = NULL; | 201 | glob_mcu = NULL; |
202 | } | 202 | } |
203 | 203 | ||
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c index e56b89a792ed..1f309ccb096e 100644 --- a/arch/powerpc/platforms/85xx/corenet_generic.c +++ b/arch/powerpc/platforms/85xx/corenet_generic.c | |||
@@ -170,7 +170,7 @@ static int __init corenet_generic_probe(void) | |||
170 | 170 | ||
171 | ppc_md.get_irq = ehv_pic_get_irq; | 171 | ppc_md.get_irq = ehv_pic_get_irq; |
172 | ppc_md.restart = fsl_hv_restart; | 172 | ppc_md.restart = fsl_hv_restart; |
173 | ppc_md.power_off = fsl_hv_halt; | 173 | pm_power_off = fsl_hv_halt; |
174 | ppc_md.halt = fsl_hv_halt; | 174 | ppc_md.halt = fsl_hv_halt; |
175 | #ifdef CONFIG_SMP | 175 | #ifdef CONFIG_SMP |
176 | /* | 176 | /* |
diff --git a/arch/powerpc/platforms/85xx/sgy_cts1000.c b/arch/powerpc/platforms/85xx/sgy_cts1000.c index 8162b0412117..e149c9ec26ae 100644 --- a/arch/powerpc/platforms/85xx/sgy_cts1000.c +++ b/arch/powerpc/platforms/85xx/sgy_cts1000.c | |||
@@ -120,7 +120,7 @@ static int gpio_halt_probe(struct platform_device *pdev) | |||
120 | 120 | ||
121 | /* Register our halt function */ | 121 | /* Register our halt function */ |
122 | ppc_md.halt = gpio_halt_cb; | 122 | ppc_md.halt = gpio_halt_cb; |
123 | ppc_md.power_off = gpio_halt_cb; | 123 | pm_power_off = gpio_halt_cb; |
124 | 124 | ||
125 | printk(KERN_INFO "gpio-halt: registered GPIO %d (%d trigger, %d" | 125 | printk(KERN_INFO "gpio-halt: registered GPIO %d (%d trigger, %d" |
126 | " irq).\n", gpio, trigger, irq); | 126 | " irq).\n", gpio, trigger, irq); |
@@ -137,7 +137,7 @@ static int gpio_halt_remove(struct platform_device *pdev) | |||
137 | free_irq(irq, halt_node); | 137 | free_irq(irq, halt_node); |
138 | 138 | ||
139 | ppc_md.halt = NULL; | 139 | ppc_md.halt = NULL; |
140 | ppc_md.power_off = NULL; | 140 | pm_power_off = NULL; |
141 | 141 | ||
142 | gpio_free(gpio); | 142 | gpio_free(gpio); |
143 | 143 | ||
diff --git a/arch/powerpc/platforms/cell/celleb_setup.c b/arch/powerpc/platforms/cell/celleb_setup.c index 34e8ce2976aa..90be8ec51686 100644 --- a/arch/powerpc/platforms/cell/celleb_setup.c +++ b/arch/powerpc/platforms/cell/celleb_setup.c | |||
@@ -142,6 +142,7 @@ static int __init celleb_probe_beat(void) | |||
142 | powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS | 142 | powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS |
143 | | FW_FEATURE_BEAT | FW_FEATURE_LPAR; | 143 | | FW_FEATURE_BEAT | FW_FEATURE_LPAR; |
144 | hpte_init_beat_v3(); | 144 | hpte_init_beat_v3(); |
145 | pm_power_off = beat_power_off; | ||
145 | 146 | ||
146 | return 1; | 147 | return 1; |
147 | } | 148 | } |
@@ -190,6 +191,7 @@ static int __init celleb_probe_native(void) | |||
190 | 191 | ||
191 | powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS; | 192 | powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS; |
192 | hpte_init_native(); | 193 | hpte_init_native(); |
194 | pm_power_off = rtas_power_off; | ||
193 | 195 | ||
194 | return 1; | 196 | return 1; |
195 | } | 197 | } |
@@ -204,7 +206,6 @@ define_machine(celleb_beat) { | |||
204 | .setup_arch = celleb_setup_arch_beat, | 206 | .setup_arch = celleb_setup_arch_beat, |
205 | .show_cpuinfo = celleb_show_cpuinfo, | 207 | .show_cpuinfo = celleb_show_cpuinfo, |
206 | .restart = beat_restart, | 208 | .restart = beat_restart, |
207 | .power_off = beat_power_off, | ||
208 | .halt = beat_halt, | 209 | .halt = beat_halt, |
209 | .get_rtc_time = beat_get_rtc_time, | 210 | .get_rtc_time = beat_get_rtc_time, |
210 | .set_rtc_time = beat_set_rtc_time, | 211 | .set_rtc_time = beat_set_rtc_time, |
@@ -230,7 +231,6 @@ define_machine(celleb_native) { | |||
230 | .setup_arch = celleb_setup_arch_native, | 231 | .setup_arch = celleb_setup_arch_native, |
231 | .show_cpuinfo = celleb_show_cpuinfo, | 232 | .show_cpuinfo = celleb_show_cpuinfo, |
232 | .restart = rtas_restart, | 233 | .restart = rtas_restart, |
233 | .power_off = rtas_power_off, | ||
234 | .halt = rtas_halt, | 234 | .halt = rtas_halt, |
235 | .get_boot_time = rtas_get_boot_time, | 235 | .get_boot_time = rtas_get_boot_time, |
236 | .get_rtc_time = rtas_get_rtc_time, | 236 | .get_rtc_time = rtas_get_rtc_time, |
diff --git a/arch/powerpc/platforms/cell/qpace_setup.c b/arch/powerpc/platforms/cell/qpace_setup.c index 6e3409d590ac..d328140dc6f5 100644 --- a/arch/powerpc/platforms/cell/qpace_setup.c +++ b/arch/powerpc/platforms/cell/qpace_setup.c | |||
@@ -127,6 +127,7 @@ static int __init qpace_probe(void) | |||
127 | return 0; | 127 | return 0; |
128 | 128 | ||
129 | hpte_init_native(); | 129 | hpte_init_native(); |
130 | pm_power_off = rtas_power_off; | ||
130 | 131 | ||
131 | return 1; | 132 | return 1; |
132 | } | 133 | } |
@@ -137,7 +138,6 @@ define_machine(qpace) { | |||
137 | .setup_arch = qpace_setup_arch, | 138 | .setup_arch = qpace_setup_arch, |
138 | .show_cpuinfo = qpace_show_cpuinfo, | 139 | .show_cpuinfo = qpace_show_cpuinfo, |
139 | .restart = rtas_restart, | 140 | .restart = rtas_restart, |
140 | .power_off = rtas_power_off, | ||
141 | .halt = rtas_halt, | 141 | .halt = rtas_halt, |
142 | .get_boot_time = rtas_get_boot_time, | 142 | .get_boot_time = rtas_get_boot_time, |
143 | .get_rtc_time = rtas_get_rtc_time, | 143 | .get_rtc_time = rtas_get_rtc_time, |
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 6ae25fb62015..d62aa982d530 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
@@ -259,6 +259,7 @@ static int __init cell_probe(void) | |||
259 | return 0; | 259 | return 0; |
260 | 260 | ||
261 | hpte_init_native(); | 261 | hpte_init_native(); |
262 | pm_power_off = rtas_power_off; | ||
262 | 263 | ||
263 | return 1; | 264 | return 1; |
264 | } | 265 | } |
@@ -269,7 +270,6 @@ define_machine(cell) { | |||
269 | .setup_arch = cell_setup_arch, | 270 | .setup_arch = cell_setup_arch, |
270 | .show_cpuinfo = cell_show_cpuinfo, | 271 | .show_cpuinfo = cell_show_cpuinfo, |
271 | .restart = rtas_restart, | 272 | .restart = rtas_restart, |
272 | .power_off = rtas_power_off, | ||
273 | .halt = rtas_halt, | 273 | .halt = rtas_halt, |
274 | .get_boot_time = rtas_get_boot_time, | 274 | .get_boot_time = rtas_get_boot_time, |
275 | .get_rtc_time = rtas_get_rtc_time, | 275 | .get_rtc_time = rtas_get_rtc_time, |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 5b77b1919fd2..860a59eb8ea2 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -585,6 +585,8 @@ static int __init chrp_probe(void) | |||
585 | DMA_MODE_READ = 0x44; | 585 | DMA_MODE_READ = 0x44; |
586 | DMA_MODE_WRITE = 0x48; | 586 | DMA_MODE_WRITE = 0x48; |
587 | 587 | ||
588 | pm_power_off = rtas_power_off; | ||
589 | |||
588 | return 1; | 590 | return 1; |
589 | } | 591 | } |
590 | 592 | ||
@@ -597,7 +599,6 @@ define_machine(chrp) { | |||
597 | .show_cpuinfo = chrp_show_cpuinfo, | 599 | .show_cpuinfo = chrp_show_cpuinfo, |
598 | .init_IRQ = chrp_init_IRQ, | 600 | .init_IRQ = chrp_init_IRQ, |
599 | .restart = rtas_restart, | 601 | .restart = rtas_restart, |
600 | .power_off = rtas_power_off, | ||
601 | .halt = rtas_halt, | 602 | .halt = rtas_halt, |
602 | .time_init = chrp_time_init, | 603 | .time_init = chrp_time_init, |
603 | .set_rtc_time = chrp_set_rtc_time, | 604 | .set_rtc_time = chrp_set_rtc_time, |
diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c index bd4ba5d7d568..fe0ed6ee285e 100644 --- a/arch/powerpc/platforms/embedded6xx/gamecube.c +++ b/arch/powerpc/platforms/embedded6xx/gamecube.c | |||
@@ -67,6 +67,8 @@ static int __init gamecube_probe(void) | |||
67 | if (!of_flat_dt_is_compatible(dt_root, "nintendo,gamecube")) | 67 | if (!of_flat_dt_is_compatible(dt_root, "nintendo,gamecube")) |
68 | return 0; | 68 | return 0; |
69 | 69 | ||
70 | pm_power_off = gamecube_power_off; | ||
71 | |||
70 | return 1; | 72 | return 1; |
71 | } | 73 | } |
72 | 74 | ||
@@ -80,7 +82,6 @@ define_machine(gamecube) { | |||
80 | .probe = gamecube_probe, | 82 | .probe = gamecube_probe, |
81 | .init_early = gamecube_init_early, | 83 | .init_early = gamecube_init_early, |
82 | .restart = gamecube_restart, | 84 | .restart = gamecube_restart, |
83 | .power_off = gamecube_power_off, | ||
84 | .halt = gamecube_halt, | 85 | .halt = gamecube_halt, |
85 | .init_IRQ = flipper_pic_probe, | 86 | .init_IRQ = flipper_pic_probe, |
86 | .get_irq = flipper_pic_get_irq, | 87 | .get_irq = flipper_pic_get_irq, |
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index 168e1d80b2e5..540eeb58d3f0 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c | |||
@@ -147,6 +147,9 @@ static int __init linkstation_probe(void) | |||
147 | 147 | ||
148 | if (!of_flat_dt_is_compatible(root, "linkstation")) | 148 | if (!of_flat_dt_is_compatible(root, "linkstation")) |
149 | return 0; | 149 | return 0; |
150 | |||
151 | pm_power_off = linkstation_power_off; | ||
152 | |||
150 | return 1; | 153 | return 1; |
151 | } | 154 | } |
152 | 155 | ||
@@ -158,7 +161,6 @@ define_machine(linkstation){ | |||
158 | .show_cpuinfo = linkstation_show_cpuinfo, | 161 | .show_cpuinfo = linkstation_show_cpuinfo, |
159 | .get_irq = mpic_get_irq, | 162 | .get_irq = mpic_get_irq, |
160 | .restart = linkstation_restart, | 163 | .restart = linkstation_restart, |
161 | .power_off = linkstation_power_off, | ||
162 | .halt = linkstation_halt, | 164 | .halt = linkstation_halt, |
163 | .calibrate_decr = generic_calibrate_decr, | 165 | .calibrate_decr = generic_calibrate_decr, |
164 | }; | 166 | }; |
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c index 388e29bab8f6..352592d3e44e 100644 --- a/arch/powerpc/platforms/embedded6xx/wii.c +++ b/arch/powerpc/platforms/embedded6xx/wii.c | |||
@@ -211,6 +211,8 @@ static int __init wii_probe(void) | |||
211 | if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii")) | 211 | if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii")) |
212 | return 0; | 212 | return 0; |
213 | 213 | ||
214 | pm_power_off = wii_power_off; | ||
215 | |||
214 | return 1; | 216 | return 1; |
215 | } | 217 | } |
216 | 218 | ||
@@ -226,7 +228,6 @@ define_machine(wii) { | |||
226 | .init_early = wii_init_early, | 228 | .init_early = wii_init_early, |
227 | .setup_arch = wii_setup_arch, | 229 | .setup_arch = wii_setup_arch, |
228 | .restart = wii_restart, | 230 | .restart = wii_restart, |
229 | .power_off = wii_power_off, | ||
230 | .halt = wii_halt, | 231 | .halt = wii_halt, |
231 | .init_IRQ = wii_pic_probe, | 232 | .init_IRQ = wii_pic_probe, |
232 | .get_irq = flipper_pic_get_irq, | 233 | .get_irq = flipper_pic_get_irq, |
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index cb1b0b35a0c6..56b85cd61aaf 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c | |||
@@ -169,7 +169,7 @@ static void __init maple_use_rtas_reboot_and_halt_if_present(void) | |||
169 | if (rtas_service_present("system-reboot") && | 169 | if (rtas_service_present("system-reboot") && |
170 | rtas_service_present("power-off")) { | 170 | rtas_service_present("power-off")) { |
171 | ppc_md.restart = rtas_restart; | 171 | ppc_md.restart = rtas_restart; |
172 | ppc_md.power_off = rtas_power_off; | 172 | pm_power_off = rtas_power_off; |
173 | ppc_md.halt = rtas_halt; | 173 | ppc_md.halt = rtas_halt; |
174 | } | 174 | } |
175 | } | 175 | } |
@@ -312,6 +312,7 @@ static int __init maple_probe(void) | |||
312 | alloc_dart_table(); | 312 | alloc_dart_table(); |
313 | 313 | ||
314 | hpte_init_native(); | 314 | hpte_init_native(); |
315 | pm_power_off = maple_power_off; | ||
315 | 316 | ||
316 | return 1; | 317 | return 1; |
317 | } | 318 | } |
@@ -325,7 +326,6 @@ define_machine(maple) { | |||
325 | .pci_irq_fixup = maple_pci_irq_fixup, | 326 | .pci_irq_fixup = maple_pci_irq_fixup, |
326 | .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, | 327 | .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, |
327 | .restart = maple_restart, | 328 | .restart = maple_restart, |
328 | .power_off = maple_power_off, | ||
329 | .halt = maple_halt, | 329 | .halt = maple_halt, |
330 | .get_boot_time = maple_get_boot_time, | 330 | .get_boot_time = maple_get_boot_time, |
331 | .set_rtc_time = maple_set_rtc_time, | 331 | .set_rtc_time = maple_set_rtc_time, |
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index b127a29ac526..713d36d45d1d 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -632,6 +632,8 @@ static int __init pmac_probe(void) | |||
632 | smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x80000000UL); | 632 | smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x80000000UL); |
633 | #endif /* CONFIG_PMAC_SMU */ | 633 | #endif /* CONFIG_PMAC_SMU */ |
634 | 634 | ||
635 | pm_power_off = pmac_power_off; | ||
636 | |||
635 | return 1; | 637 | return 1; |
636 | } | 638 | } |
637 | 639 | ||
@@ -663,7 +665,6 @@ define_machine(powermac) { | |||
663 | .get_irq = NULL, /* changed later */ | 665 | .get_irq = NULL, /* changed later */ |
664 | .pci_irq_fixup = pmac_pci_irq_fixup, | 666 | .pci_irq_fixup = pmac_pci_irq_fixup, |
665 | .restart = pmac_restart, | 667 | .restart = pmac_restart, |
666 | .power_off = pmac_power_off, | ||
667 | .halt = pmac_halt, | 668 | .halt = pmac_halt, |
668 | .time_init = pmac_time_init, | 669 | .time_init = pmac_time_init, |
669 | .get_boot_time = pmac_get_boot_time, | 670 | .get_boot_time = pmac_get_boot_time, |
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index 3f9546d8a51f..941831d67cb2 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
@@ -268,7 +268,7 @@ static void __init pnv_setup_machdep_opal(void) | |||
268 | ppc_md.get_rtc_time = opal_get_rtc_time; | 268 | ppc_md.get_rtc_time = opal_get_rtc_time; |
269 | ppc_md.set_rtc_time = opal_set_rtc_time; | 269 | ppc_md.set_rtc_time = opal_set_rtc_time; |
270 | ppc_md.restart = pnv_restart; | 270 | ppc_md.restart = pnv_restart; |
271 | ppc_md.power_off = pnv_power_off; | 271 | pm_power_off = pnv_power_off; |
272 | ppc_md.halt = pnv_halt; | 272 | ppc_md.halt = pnv_halt; |
273 | ppc_md.machine_check_exception = opal_machine_check; | 273 | ppc_md.machine_check_exception = opal_machine_check; |
274 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; | 274 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; |
@@ -285,7 +285,7 @@ static void __init pnv_setup_machdep_rtas(void) | |||
285 | ppc_md.set_rtc_time = rtas_set_rtc_time; | 285 | ppc_md.set_rtc_time = rtas_set_rtc_time; |
286 | } | 286 | } |
287 | ppc_md.restart = rtas_restart; | 287 | ppc_md.restart = rtas_restart; |
288 | ppc_md.power_off = rtas_power_off; | 288 | pm_power_off = rtas_power_off; |
289 | ppc_md.halt = rtas_halt; | 289 | ppc_md.halt = rtas_halt; |
290 | } | 290 | } |
291 | #endif /* CONFIG_PPC_POWERNV_RTAS */ | 291 | #endif /* CONFIG_PPC_POWERNV_RTAS */ |
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 3f509f86432c..009a2004b876 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c | |||
@@ -248,6 +248,7 @@ static int __init ps3_probe(void) | |||
248 | ps3_mm_init(); | 248 | ps3_mm_init(); |
249 | ps3_mm_vas_create(&htab_size); | 249 | ps3_mm_vas_create(&htab_size); |
250 | ps3_hpte_init(htab_size); | 250 | ps3_hpte_init(htab_size); |
251 | pm_power_off = ps3_power_off; | ||
251 | 252 | ||
252 | DBG(" <- %s:%d\n", __func__, __LINE__); | 253 | DBG(" <- %s:%d\n", __func__, __LINE__); |
253 | return 1; | 254 | return 1; |
@@ -278,7 +279,6 @@ define_machine(ps3) { | |||
278 | .calibrate_decr = ps3_calibrate_decr, | 279 | .calibrate_decr = ps3_calibrate_decr, |
279 | .progress = ps3_progress, | 280 | .progress = ps3_progress, |
280 | .restart = ps3_restart, | 281 | .restart = ps3_restart, |
281 | .power_off = ps3_power_off, | ||
282 | .halt = ps3_halt, | 282 | .halt = ps3_halt, |
283 | #if defined(CONFIG_KEXEC) | 283 | #if defined(CONFIG_KEXEC) |
284 | .kexec_cpu_down = ps3_kexec_cpu_down, | 284 | .kexec_cpu_down = ps3_kexec_cpu_down, |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 125c589eeef5..db0fc0c07568 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -659,6 +659,34 @@ static void __init pSeries_init_early(void) | |||
659 | pr_debug(" <- pSeries_init_early()\n"); | 659 | pr_debug(" <- pSeries_init_early()\n"); |
660 | } | 660 | } |
661 | 661 | ||
662 | /** | ||
663 | * pseries_power_off - tell firmware about how to power off the system. | ||
664 | * | ||
665 | * This function calls either the power-off rtas token in normal cases | ||
666 | * or the ibm,power-off-ups token (if present & requested) in case of | ||
667 | * a power failure. If power-off token is used, power on will only be | ||
668 | * possible with power button press. If ibm,power-off-ups token is used | ||
669 | * it will allow auto poweron after power is restored. | ||
670 | */ | ||
671 | static void pseries_power_off(void) | ||
672 | { | ||
673 | int rc; | ||
674 | int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups"); | ||
675 | |||
676 | if (rtas_flash_term_hook) | ||
677 | rtas_flash_term_hook(SYS_POWER_OFF); | ||
678 | |||
679 | if (rtas_poweron_auto == 0 || | ||
680 | rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) { | ||
681 | rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1); | ||
682 | printk(KERN_INFO "RTAS power-off returned %d\n", rc); | ||
683 | } else { | ||
684 | rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL); | ||
685 | printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc); | ||
686 | } | ||
687 | for (;;); | ||
688 | } | ||
689 | |||
662 | /* | 690 | /* |
663 | * Called very early, MMU is off, device-tree isn't unflattened | 691 | * Called very early, MMU is off, device-tree isn't unflattened |
664 | */ | 692 | */ |
@@ -741,6 +769,8 @@ static int __init pSeries_probe(void) | |||
741 | else | 769 | else |
742 | hpte_init_native(); | 770 | hpte_init_native(); |
743 | 771 | ||
772 | pm_power_off = pseries_power_off; | ||
773 | |||
744 | pr_debug("Machine is%s LPAR !\n", | 774 | pr_debug("Machine is%s LPAR !\n", |
745 | (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); | 775 | (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); |
746 | 776 | ||
@@ -754,34 +784,6 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) | |||
754 | return PCI_PROBE_NORMAL; | 784 | return PCI_PROBE_NORMAL; |
755 | } | 785 | } |
756 | 786 | ||
757 | /** | ||
758 | * pSeries_power_off - tell firmware about how to power off the system. | ||
759 | * | ||
760 | * This function calls either the power-off rtas token in normal cases | ||
761 | * or the ibm,power-off-ups token (if present & requested) in case of | ||
762 | * a power failure. If power-off token is used, power on will only be | ||
763 | * possible with power button press. If ibm,power-off-ups token is used | ||
764 | * it will allow auto poweron after power is restored. | ||
765 | */ | ||
766 | static void pSeries_power_off(void) | ||
767 | { | ||
768 | int rc; | ||
769 | int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups"); | ||
770 | |||
771 | if (rtas_flash_term_hook) | ||
772 | rtas_flash_term_hook(SYS_POWER_OFF); | ||
773 | |||
774 | if (rtas_poweron_auto == 0 || | ||
775 | rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) { | ||
776 | rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1); | ||
777 | printk(KERN_INFO "RTAS power-off returned %d\n", rc); | ||
778 | } else { | ||
779 | rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL); | ||
780 | printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc); | ||
781 | } | ||
782 | for (;;); | ||
783 | } | ||
784 | |||
785 | #ifndef CONFIG_PCI | 787 | #ifndef CONFIG_PCI |
786 | void pSeries_final_fixup(void) { } | 788 | void pSeries_final_fixup(void) { } |
787 | #endif | 789 | #endif |
@@ -796,7 +798,6 @@ define_machine(pseries) { | |||
796 | .pcibios_fixup = pSeries_final_fixup, | 798 | .pcibios_fixup = pSeries_final_fixup, |
797 | .pci_probe_mode = pSeries_pci_probe_mode, | 799 | .pci_probe_mode = pSeries_pci_probe_mode, |
798 | .restart = rtas_restart, | 800 | .restart = rtas_restart, |
799 | .power_off = pSeries_power_off, | ||
800 | .halt = rtas_halt, | 801 | .halt = rtas_halt, |
801 | .panic = rtas_os_term, | 802 | .panic = rtas_os_term, |
802 | .get_boot_time = rtas_get_boot_time, | 803 | .get_boot_time = rtas_get_boot_time, |
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index ffd1169ebaab..1e04568da3b9 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -238,7 +238,7 @@ void fsl_hv_restart(char *cmd) | |||
238 | /* | 238 | /* |
239 | * Halt the current partition | 239 | * Halt the current partition |
240 | * | 240 | * |
241 | * This function should be assigned to the ppc_md.power_off and ppc_md.halt | 241 | * This function should be assigned to the pm_power_off and ppc_md.halt |
242 | * function pointers, to shut down the partition when we're running under | 242 | * function pointers, to shut down the partition when we're running under |
243 | * the Freescale hypervisor. | 243 | * the Freescale hypervisor. |
244 | */ | 244 | */ |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index b988b5addf86..506d25681fe3 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -981,7 +981,8 @@ static void bootcmds(void) | |||
981 | else if (cmd == 'h') | 981 | else if (cmd == 'h') |
982 | ppc_md.halt(); | 982 | ppc_md.halt(); |
983 | else if (cmd == 'p') | 983 | else if (cmd == 'p') |
984 | ppc_md.power_off(); | 984 | if (pm_power_off) |
985 | pm_power_off(); | ||
985 | } | 986 | } |
986 | 987 | ||
987 | static int cpu_cmd(void) | 988 | static int cpu_cmd(void) |