diff mbox

[pm-core,v3,18/21] OMAP4: cpuidle: Add CPU hotplug notifier and prepare() hook.

Message ID 1301304157-2466-19-git-send-email-santosh.shilimkar@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Santosh Shilimkar March 28, 2011, 9:22 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index daf41e1..83b7f95 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -13,6 +13,8 @@ 
 #include <linux/sched.h>
 #include <linux/cpuidle.h>
 #include <linux/clockchips.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
 
 #include <asm/proc-fns.h>
 
@@ -51,6 +53,8 @@  struct omap4_processor_cx {
 
 struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
 static struct powerdomain *mpu_pd, *cpu1_pd, *core_pd;
+static int needs_state_data_update;
+static unsigned int state_flags = CPUIDLE_FLAG_IGNORE;
 
 /*
  * FIXME: Full latency numbers needs to be updated as part of
@@ -72,6 +76,31 @@  static struct cpuidle_params cpuidle_params_table[] = {
 };
 
 /**
+ * omap4_prepare_idle - Update C-state parameters dynamically
+ * @dev: cpuidle device
+ *
+ * Called from the CPUidle framework to prepare the device
+ * for idle before before calling the governor's select function.
+ */
+static int omap4_prepare_idle(struct cpuidle_device *dev)
+{
+	int i, ret = 0;
+
+	if (!needs_state_data_update)
+		return ret;
+
+	/*
+	 * Update the C-state flags based on CPU1 online
+	 * or offline state. On OMAP4, the low power C-states
+	 * are made available when only CPU1 is offline.
+	 */
+	for (i = OMAP4_STATE_C2; i < OMAP4_MAX_STATES; i++)
+		dev->states[i].flags = state_flags;
+
+	return ret;
+}
+
+/**
  * omap4_enter_idle - Programs OMAP4 to enter the specified state
  * @dev: cpuidle device
  * @state: The target state to be programmed
@@ -227,6 +256,36 @@  struct cpuidle_driver omap4_idle_driver = {
 	.owner =	THIS_MODULE,
 };
 
+/*
+ * CPU hotplug notifier to update the C-states when
+ * CPU1 is offline or onine. While updating C-state flag,
+ * keep the cpuidle disabled.
+ */
+static int __cpuinit omap_cpu_hotplug_notify(struct notifier_block *self,
+					 unsigned long action, void *unused)
+{
+	switch (action) {
+	case CPU_ONLINE:
+		disable_hlt();
+		needs_state_data_update = 1;
+		state_flags = CPUIDLE_FLAG_IGNORE;
+		enable_hlt();
+		break;
+	case CPU_DEAD:
+		disable_hlt();
+		needs_state_data_update = 1;
+		state_flags = CPUIDLE_FLAG_TIME_VALID;
+		enable_hlt();
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata omap_ilde_hotplug_notifier = {
+	.notifier_call = omap_cpu_hotplug_notify,
+};
+
 /**
  * omap4_idle_init - Init routine for OMAP4 idle
  *
@@ -272,12 +331,17 @@  int __init omap4_idle_init(void)
 	if (!count)
 		return -EINVAL;
 	dev->state_count = count;
+	dev->prepare = omap4_prepare_idle;
 
 	if (cpuidle_register_device(dev)) {
 		pr_err("%s: CPUidle register device failed\n", __func__);
 			return -EIO;
 		}
 
+	ret = register_hotcpu_notifier(&omap_ilde_hotplug_notifier);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 #else