diff mbox

[v2,06/14] OMAP: Voltage layer changes to support DVFS.

Message ID 1288366708-32302-7-git-send-email-thara@ti.com (mailing list archive)
State Superseded
Delegated to: Kevin Hilman
Headers show

Commit Message

Thara Gopinath Oct. 29, 2010, 3:38 p.m. UTC
None
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 6c2e4ef..458f8c1 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -27,9 +27,11 @@ 
 #include <linux/spinlock.h>
 #include <linux/plist.h>
 #include <linux/slab.h>
+#include <linux/opp.h>
 
 #include <plat/common.h>
 #include <plat/voltage.h>
+#include <plat/omap_device.h>
 
 #include "prm-regbits-34xx.h"
 #include "prm44xx.h"
@@ -1678,6 +1680,76 @@  struct voltagedomain *omap_voltage_domain_lookup(char *name)
 }
 
 /**
+ * omap_voltage_scale : API to scale the devices associated with a
+ *			voltage domain vdd voltage.
+ * @volt_domain : the voltage domain to be scaled
+ * @volt : the new voltage for the voltage domain
+ *
+ * This API runs through the list of devices associated with the
+ * voltage domain and scales the device rates to those corresponding
+ * to the new voltage of the voltage domain. This API also scales
+ * the voltage domain voltage to the new value. Returns 0 on success
+ * else the error value.
+ */
+int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
+{
+	unsigned long curr_volt;
+	int is_volt_scaled = 0;
+	struct omap_vdd_info *vdd;
+	struct omap_vdd_dev_list *temp_dev;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return -EINVAL;
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
+
+	mutex_lock(&vdd->scaling_mutex);
+
+	curr_volt = omap_voltage_get_nom_volt(voltdm);
+
+	if (curr_volt == volt) {
+		is_volt_scaled = 1;
+	} else if (curr_volt < volt) {
+		omap_voltage_scale_vdd(voltdm, volt);
+		is_volt_scaled = 1;
+	}
+
+	list_for_each_entry(temp_dev, &vdd->dev_list, node) {
+		struct device *dev;
+		struct opp *opp;
+		unsigned long freq;
+
+		dev = temp_dev->dev;
+
+		opp = opp_find_voltage(dev, volt);
+		if (IS_ERR(opp)) {
+			dev_err(dev, "%s: Unable to find OPP for"
+				"volt%ld\n", __func__, volt);
+			continue;
+		}
+
+		freq = opp_get_freq(opp);
+
+		if (freq == omap_device_get_rate(dev)) {
+			dev_warn(dev, "%s: Already at the requested"
+				"rate %ld\n", __func__, freq);
+			continue;
+		}
+
+		omap_device_set_rate(dev, freq);
+	}
+
+	if (!is_volt_scaled)
+		omap_voltage_scale_vdd(voltdm, volt);
+
+	mutex_unlock(&vdd->scaling_mutex);
+
+	return 0;
+}
+
+/**
  * omap_voltage_init : Volatage init API which does VP and VC init.
  */
 static int __init omap_voltage_init(void)
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
index dc64a9a..54d50e2 100644
--- a/arch/arm/plat-omap/include/plat/voltage.h
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -153,6 +153,7 @@  void omap_change_voltscale_method(int voltscale_method);
 int omap_voltage_add_request(struct voltagedomain *voltdm, struct device *dev,
 		unsigned long *volt);
 int omap_voltage_add_dev(struct voltagedomain *voltdm, struct device *dev);
+int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt);
 #else
 static inline void omap_voltage_register_pmic
 			(struct omap_volt_pmic_info *pmic_info) {}
@@ -169,6 +170,12 @@  static inline int omap_voltage_add_dev(struct voltagedomain *voltdm,
 {
 	return -EINVAL;
 }
+
+static inline int omap_voltage_scale(struct voltagedomain *voltdm,
+		unsigned long volt)
+{
+	return -EINVAL;
+}
 #endif
 
 #endif