#define OPAL_IPMI_RECV                         108
 #define OPAL_I2C_REQUEST                       109
 
+/* Device tree flags */
+
+/* Flags set in power-mgmt nodes in device tree if
+ * respective idle states are supported in the platform.
+ */
+#define OPAL_PM_NAP_ENABLED    0x00010000
+#define OPAL_PM_SLEEP_ENABLED  0x00020000
+
 #ifndef __ASSEMBLY__
 
 #include <linux/notifier.h>
 
 }
 #endif
 
+extern u32 pnv_get_supported_cpuidle_states(void);
+
 extern void pnv_lpc_init(void);
 
 bool cpu_core_split_required(void);
 
 }
 #endif /* CONFIG_PPC_POWERNV_RTAS */
 
+static u32 supported_cpuidle_states;
+
+u32 pnv_get_supported_cpuidle_states(void)
+{
+       return supported_cpuidle_states;
+}
+
+static int __init pnv_init_idle_states(void)
+{
+       struct device_node *power_mgt;
+       int dt_idle_states;
+       const __be32 *idle_state_flags;
+       u32 len_flags, flags;
+       int i;
+
+       supported_cpuidle_states = 0;
+
+       if (cpuidle_disable != IDLE_NO_OVERRIDE)
+               return 0;
+
+       if (!firmware_has_feature(FW_FEATURE_OPALv3))
+               return 0;
+
+       power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
+       if (!power_mgt) {
+               pr_warn("opal: PowerMgmt Node not found\n");
+               return 0;
+       }
+
+       idle_state_flags = of_get_property(power_mgt,
+                       "ibm,cpu-idle-state-flags", &len_flags);
+       if (!idle_state_flags) {
+               pr_warn("DT-PowerMgmt: missing ibm,cpu-idle-state-flags\n");
+               return 0;
+       }
+
+       dt_idle_states = len_flags / sizeof(u32);
+
+       for (i = 0; i < dt_idle_states; i++) {
+               flags = be32_to_cpu(idle_state_flags[i]);
+               supported_cpuidle_states |= flags;
+       }
+
+       return 0;
+}
+
+subsys_initcall(pnv_init_idle_states);
+
+
 static int __init pnv_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 
 {
        unsigned int cpu;
        unsigned long srr1;
+       u32 idle_states;
 
        /* Standard hot unplug procedure */
        local_irq_disable();
        generic_set_cpu_dead(cpu);
        smp_wmb();
 
+       idle_states = pnv_get_supported_cpuidle_states();
        /* We don't want to take decrementer interrupts while we are offline,
         * so clear LPCR:PECE1. We keep PECE2 enabled.
         */
        mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
        while (!generic_check_cpu_restart(cpu)) {
                ppc64_runlatch_off();
-               srr1 = power7_nap(1);
+               if (idle_states & OPAL_PM_SLEEP_ENABLED)
+                       srr1 = power7_sleep();
+               else
+                       srr1 = power7_nap(1);
                ppc64_runlatch_on();
 
                /*
 
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
+#include <asm/opal.h>
 #include <asm/runlatch.h>
 
-/* Flags and constants used in PowerNV platform */
-
 #define MAX_POWERNV_IDLE_STATES        8
-#define IDLE_USE_INST_NAP      0x00010000 /* Use nap instruction */
-#define IDLE_USE_INST_SLEEP    0x00020000 /* Use sleep instruction */
 
 struct cpuidle_driver powernv_idle_driver = {
        .name             = "powernv_idle",
                 * target residency to be 10x exit_latency
                 */
                latency_ns = be32_to_cpu(idle_state_latency[i]);
-               if (flags & IDLE_USE_INST_NAP) {
+               if (flags & OPAL_PM_NAP_ENABLED) {
                        /* Add NAP state */
                        strcpy(powernv_states[nr_idle_states].name, "Nap");
                        strcpy(powernv_states[nr_idle_states].desc, "Nap");
                        nr_idle_states++;
                }
 
-               if (flags & IDLE_USE_INST_SLEEP) {
+               if (flags & OPAL_PM_SLEEP_ENABLED) {
                        /* Add FASTSLEEP state */
                        strcpy(powernv_states[nr_idle_states].name, "FastSleep");
                        strcpy(powernv_states[nr_idle_states].desc, "FastSleep");