aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powernv/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/powernv/setup.c')
-rw-r--r--arch/powerpc/platforms/powernv/setup.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 8723d32632f5..8c16a5f96728 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -27,6 +27,7 @@
27#include <linux/interrupt.h> 27#include <linux/interrupt.h>
28#include <linux/bug.h> 28#include <linux/bug.h>
29#include <linux/pci.h> 29#include <linux/pci.h>
30#include <linux/cpufreq.h>
30 31
31#include <asm/machdep.h> 32#include <asm/machdep.h>
32#include <asm/firmware.h> 33#include <asm/firmware.h>
@@ -98,11 +99,32 @@ static void pnv_show_cpuinfo(struct seq_file *m)
98 of_node_put(root); 99 of_node_put(root);
99} 100}
100 101
102static void pnv_prepare_going_down(void)
103{
104 /*
105 * Disable all notifiers from OPAL, we can't
106 * service interrupts anymore anyway
107 */
108 opal_notifier_disable();
109
110 /* Soft disable interrupts */
111 local_irq_disable();
112
113 /*
114 * Return secondary CPUs to firwmare if a flash update
115 * is pending otherwise we will get all sort of error
116 * messages about CPU being stuck etc.. This will also
117 * have the side effect of hard disabling interrupts so
118 * past this point, the kernel is effectively dead.
119 */
120 opal_flash_term_callback();
121}
122
101static void __noreturn pnv_restart(char *cmd) 123static void __noreturn pnv_restart(char *cmd)
102{ 124{
103 long rc = OPAL_BUSY; 125 long rc = OPAL_BUSY;
104 126
105 opal_notifier_disable(); 127 pnv_prepare_going_down();
106 128
107 while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { 129 while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
108 rc = opal_cec_reboot(); 130 rc = opal_cec_reboot();
@@ -119,7 +141,7 @@ static void __noreturn pnv_power_off(void)
119{ 141{
120 long rc = OPAL_BUSY; 142 long rc = OPAL_BUSY;
121 143
122 opal_notifier_disable(); 144 pnv_prepare_going_down();
123 145
124 while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { 146 while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
125 rc = opal_cec_power_down(0); 147 rc = opal_cec_power_down(0);
@@ -222,6 +244,13 @@ static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
222} 244}
223#endif /* CONFIG_KEXEC */ 245#endif /* CONFIG_KEXEC */
224 246
247#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
248static unsigned long pnv_memory_block_size(void)
249{
250 return 256UL * 1024 * 1024;
251}
252#endif
253
225static void __init pnv_setup_machdep_opal(void) 254static void __init pnv_setup_machdep_opal(void)
226{ 255{
227 ppc_md.get_boot_time = opal_get_boot_time; 256 ppc_md.get_boot_time = opal_get_boot_time;
@@ -269,6 +298,25 @@ static int __init pnv_probe(void)
269 return 1; 298 return 1;
270} 299}
271 300
301/*
302 * Returns the cpu frequency for 'cpu' in Hz. This is used by
303 * /proc/cpuinfo
304 */
305unsigned long pnv_get_proc_freq(unsigned int cpu)
306{
307 unsigned long ret_freq;
308
309 ret_freq = cpufreq_quick_get(cpu) * 1000ul;
310
311 /*
312 * If the backend cpufreq driver does not exist,
313 * then fallback to old way of reporting the clockrate.
314 */
315 if (!ret_freq)
316 ret_freq = ppc_proc_freq;
317 return ret_freq;
318}
319
272define_machine(powernv) { 320define_machine(powernv) {
273 .name = "PowerNV", 321 .name = "PowerNV",
274 .probe = pnv_probe, 322 .probe = pnv_probe,
@@ -276,6 +324,7 @@ define_machine(powernv) {
276 .setup_arch = pnv_setup_arch, 324 .setup_arch = pnv_setup_arch,
277 .init_IRQ = pnv_init_IRQ, 325 .init_IRQ = pnv_init_IRQ,
278 .show_cpuinfo = pnv_show_cpuinfo, 326 .show_cpuinfo = pnv_show_cpuinfo,
327 .get_proc_freq = pnv_get_proc_freq,
279 .progress = pnv_progress, 328 .progress = pnv_progress,
280 .machine_shutdown = pnv_shutdown, 329 .machine_shutdown = pnv_shutdown,
281 .power_save = power7_idle, 330 .power_save = power7_idle,
@@ -284,4 +333,7 @@ define_machine(powernv) {
284#ifdef CONFIG_KEXEC 333#ifdef CONFIG_KEXEC
285 .kexec_cpu_down = pnv_kexec_cpu_down, 334 .kexec_cpu_down = pnv_kexec_cpu_down,
286#endif 335#endif
336#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
337 .memory_block_size = pnv_memory_block_size,
338#endif
287}; 339};