diff mbox

[v2,01/14] OMAP: Introduce a user list for each voltage domain instance in the voltage driver.

Message ID 1288366708-32302-2-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 45b0958..f0ecc30 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -24,6 +24,9 @@ 
 #include <linux/err.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/plist.h>
+#include <linux/slab.h>
 
 #include <plat/common.h>
 #include <plat/voltage.h>
@@ -85,6 +88,20 @@  struct vp_reg_val {
 };
 
 /**
+ * struct omap_vdd_user_list - The per vdd user list
+ *
+ * @dev:	The device asking for the vdd to be set at a particular
+ *		voltage
+ * @node:	The list head entry
+ * @volt:	The voltage requested by the device <dev>
+ */
+struct omap_vdd_user_list {
+	struct device *dev;
+	struct plist_node node;
+	u32 volt;
+};
+
+/**
  * omap_vdd_info - Per Voltage Domain info
  *
  * @volt_data		: voltage table having the distinct voltages supported
@@ -95,9 +112,13 @@  struct vp_reg_val {
  *			  vp registers
  * @voltdm		: pointer to the voltage domain structure
  * @debug_dir		: debug directory for this voltage domain.
+ * @user_lock		: the lock to be used by the plist user_list
+ * @user_list		: the list head maintaining the various users.
+ * @scaling_mutex	: the dvfs muutex.
+ *			  of this vdd with the voltage requested by each user.
  * @volt_data_count	: number of distinct voltages supported by this vdd.
  * @nominal_volt	: nominal voltage for this vdd.
- * @curr_volt		: current voltage for this vdd;
+ * @curr_volt		: current voltage for this vdd.
  * cmdval_reg		: voltage controller cmdval register.
  * @vdd_sr_reg		: the smartreflex register associated with this VDD.
  */
@@ -107,6 +128,9 @@  struct omap_vdd_info{
 	struct vp_reg_val vp_reg;
 	struct voltagedomain voltdm;
 	struct dentry *debug_dir;
+	spinlock_t user_lock;
+	struct plist_head user_list;
+	struct mutex scaling_mutex;
 	int volt_data_count;
 	u32 nominal_volt;
 	u32 curr_volt;
@@ -591,6 +615,12 @@  static void __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
 	vdd->vp_reg.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT;
 	vdd->vp_reg.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT;
 	vdd->vp_reg.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT;
+
+	/* Init the plist */
+	spin_lock_init(&vdd->user_lock);
+	plist_head_init(&vdd->user_list, &vdd->user_lock);
+	/* Init the DVFS mutex */
+	mutex_init(&vdd->scaling_mutex);
 }
 
 /* OMAP4 specific voltage init functions */
@@ -715,6 +745,12 @@  static void __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
 	vdd->vp_reg.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT;
 	vdd->vp_reg.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT;
 	vdd->vp_reg.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT;
+
+	/* Init the plist */
+	spin_lock_init(&vdd->user_lock);
+	plist_head_init(&vdd->user_list, &vdd->user_lock);
+	/* Init the DVFS mutex */
+	mutex_init(&vdd->scaling_mutex);
 }
 
 /* Generic voltage init functions */
@@ -1140,6 +1176,69 @@  unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
 
 	return volt_pmic_info.vsel_to_uv(curr_vsel);
 }
+/**
+ * omap_voltage_add_request() - API to keep track of various requests to
+ *				scale the VDD and returns the best possible
+ *				voltage the VDD can be put to.
+ * @volt_domain:	pointer to the voltage domain.
+ * @dev:		the device pointer.
+ * @volt:		the voltage which is requested by the device.
+ *
+ * This API is to be called before the actual voltage scaling is
+ * done to determine what is the best possible voltage the VDD can
+ * be put to. This API adds the device <dev> in the user list of the
+ * vdd <volt_domain> with <volt> as the requested voltage. The user list
+ * is a plist with the priority element absolute voltage values.
+ * The API then finds the maximum of all the requested voltages for
+ * the VDD and returns it back through <volt> pointer itself.
+ * Returns error value in case of any errors.
+ */
+int omap_voltage_add_request(struct voltagedomain *voltdm, struct device *dev,
+		unsigned long *volt)
+{
+	struct omap_vdd_info *vdd;
+	struct omap_vdd_user_list *user;
+	struct plist_node *node;
+	int found = 0;
+
+	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);
+
+	plist_for_each_entry(user, &vdd->user_list, node) {
+		if (user->dev == dev) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		user = kzalloc(sizeof(struct omap_vdd_user_list), GFP_KERNEL);
+		if (!user) {
+			pr_err("%s: Unable to creat a new user for vdd_%s\n",
+				__func__, voltdm->name);
+			mutex_unlock(&vdd->scaling_mutex);
+			return -ENOMEM;
+		}
+		user->dev = dev;
+	} else {
+		plist_del(&user->node, &vdd->user_list);
+	}
+
+	plist_node_init(&user->node, *volt);
+	plist_add(&user->node, &vdd->user_list);
+	node = plist_last(&vdd->user_list);
+	*volt = user->volt = node->prio;
+
+	mutex_unlock(&vdd->scaling_mutex);
+
+	return 0;
+}
 
 /**
  * omap_vp_enable() - API to enable a particular VP
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
index 812266e..c226b6d 100644
--- a/arch/arm/plat-omap/include/plat/voltage.h
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -150,11 +150,18 @@  bool omap_voltage_override_params(struct voltagedomain *voltdm);
 void omap_voltage_register_pmic(struct omap_volt_pmic_info *pmic_info);
 void omap_voltage_init_vc(struct omap_volt_vc_data *setup_vc);
 void omap_change_voltscale_method(int voltscale_method);
+int omap_voltage_add_request(struct voltagedomain *voltdm, struct device *dev,
+		unsigned long *volt);
 #else
 static inline void omap_voltage_register_pmic
 			(struct omap_volt_pmic_info *pmic_info) {}
 static inline void omap_voltage_init_vc(struct omap_volt_vc_data *setup_vc) {}
 static inline  void omap_change_voltscale_method(int voltscale_method) {}
+static inline int omap_voltage_add_request(struct voltagedomain *voltdm,
+		struct device *dev, unsigned long *volt)
+{
+	return -EINVAL;
+}
 #endif
 
 #endif