aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-omap-2.6.37/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-omap-2.6.37/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch')
-rw-r--r--recipes/linux/linux-omap-2.6.37/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch195
1 files changed, 195 insertions, 0 deletions
diff --git a/recipes/linux/linux-omap-2.6.37/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch b/recipes/linux/linux-omap-2.6.37/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch
new file mode 100644
index 0000000000..814643f79d
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.37/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch
@@ -0,0 +1,195 @@
+From 444b19e90ae45ccd68c84285fe8339d797a08911 Mon Sep 17 00:00:00 2001
+From: Thara Gopinath <thara@ti.com>
+Date: Fri, 2 Jul 2010 13:06:57 +0530
+Subject: [PATCH 11/19] OMAP: Introduce dependent voltage domain support.
+
+There could be dependencies between various voltage domains for
+maintaining system performance or hardware limitation reasons
+like VDD<X> should be at voltage v1 when VDD<Y> is at voltage v2.
+This patch introduce dependent vdd information structures in the
+voltage layer which can be used to populate these dependencies
+for a voltage domain. This patch also adds support to scale
+the dependent vdd and the scalable devices belonging to it
+during the scaling of a main vdd through omap_voltage_scale.
+
+Signed-off-by: Thara Gopinath <thara@ti.com>
+---
+ arch/arm/mach-omap2/voltage.c | 122 +++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 122 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
+index 9adf9d1..c83d968 100644
+--- a/arch/arm/mach-omap2/voltage.c
++++ b/arch/arm/mach-omap2/voltage.c
+@@ -123,6 +123,36 @@ struct vc_reg_info {
+ };
+
+ /**
++ * omap_vdd_dep_volt - Table containing the parent vdd voltage and the
++ * dependent vdd voltage corresponding to it.
++ *
++ * @main_vdd_volt : The main vdd voltage
++ * @dep_vdd_volt : The voltage at which the dependent vdd should be
++ * when the main vdd is at <main_vdd_volt> voltage
++ */
++struct omap_vdd_dep_volt {
++ u32 main_vdd_volt;
++ u32 dep_vdd_volt;
++};
++
++/**
++ * omap_vdd_dep_info - Dependent vdd info
++ *
++ * @name : Dependent vdd name
++ * @voltdm : Dependent vdd pointer
++ * @dep_table : Table containing the dependent vdd voltage
++ * corresponding to every main vdd voltage.
++ * @cur_dep_volt : The voltage to which dependent vdd should be put
++ * to for the current main vdd voltage.
++ */
++struct omap_vdd_dep_info {
++ char *name;
++ struct voltagedomain *voltdm;
++ struct omap_vdd_dep_volt *dep_table;
++ unsigned long cur_dep_volt;
++};
++
++/**
+ * struct omap_vdd_user_list - The per vdd user list
+ *
+ * @dev: The device asking for the vdd to be set at a particular
+@@ -174,11 +204,13 @@ struct omap_vdd_info {
+ struct vp_reg_val vp_reg;
+ struct vc_reg_info vc_reg;
+ struct voltagedomain voltdm;
++ struct omap_vdd_dep_info *dep_vdd_info;
+ struct dentry *debug_dir;
+ spinlock_t user_lock;
+ struct plist_head user_list;
+ struct mutex scaling_mutex;
+ struct list_head dev_list;
++ int nr_dep_vdd;
+ u32 curr_volt;
+ u16 ocp_mod;
+ u8 prm_irqst_reg;
+@@ -1160,6 +1192,80 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
+ return 0;
+ }
+
++static int calc_dep_vdd_volt(struct device *dev,
++ struct omap_vdd_info *main_vdd, unsigned long main_volt)
++{
++ struct omap_vdd_dep_info *dep_vdds;
++ int i, ret = 0;
++
++ if (!main_vdd->dep_vdd_info) {
++ pr_debug("%s: No dependent VDD's for vdd_%s\n",
++ __func__, main_vdd->voltdm.name);
++ return 0;
++ }
++
++ dep_vdds = main_vdd->dep_vdd_info;
++
++ for (i = 0; i < main_vdd->nr_dep_vdd; i++) {
++ struct omap_vdd_dep_volt *volt_table = dep_vdds[i].dep_table;
++ int nr_volt = 0;
++ unsigned long dep_volt = 0, act_volt = 0;
++
++ while (volt_table[nr_volt].main_vdd_volt != 0) {
++ if (volt_table[nr_volt].main_vdd_volt == main_volt) {
++ dep_volt = volt_table[nr_volt].dep_vdd_volt;
++ break;
++ }
++ nr_volt++;
++ }
++ if (!dep_volt) {
++ pr_warning("%s: Not able to find a matching volt for"
++ "vdd_%s corresponding to vdd_%s %ld volt\n",
++ __func__, dep_vdds[i].name,
++ main_vdd->voltdm.name, main_volt);
++ ret = -EINVAL;
++ continue;
++ }
++
++ if (!dep_vdds[i].voltdm)
++ dep_vdds[i].voltdm =
++ omap_voltage_domain_lookup(dep_vdds[i].name);
++
++ act_volt = dep_volt;
++
++ /* See if dep_volt is possible for the vdd*/
++ ret = omap_voltage_add_request(dep_vdds[i].voltdm, dev,
++ &act_volt);
++
++ /*
++ * Currently we do not bother if the dep volt and act volt are
++ * different. We could add a check if needed.
++ */
++ dep_vdds[i].cur_dep_volt = act_volt;
++ }
++
++ return ret;
++}
++
++static int scale_dep_vdd(struct omap_vdd_info *main_vdd)
++{
++ struct omap_vdd_dep_info *dep_vdds;
++ int i;
++
++ if (!main_vdd->dep_vdd_info) {
++ pr_debug("%s: No dependent VDD's for vdd_%s\n",
++ __func__, main_vdd->voltdm.name);
++ return 0;
++ }
++
++ dep_vdds = main_vdd->dep_vdd_info;
++
++ for (i = 0; i < main_vdd->nr_dep_vdd; i++)
++ omap_voltage_scale(dep_vdds[i].voltdm,
++ dep_vdds[i].cur_dep_volt);
++ return 0;
++}
++
+ /* Public functions */
+ /**
+ * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
+@@ -1675,6 +1781,8 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
+ int is_volt_scaled = 0;
+ struct omap_vdd_info *vdd;
+ struct omap_vdd_dev_list *temp_dev;
++ struct plist_node *node;
++ struct omap_vdd_user_list *user;
+
+ if (!voltdm || IS_ERR(voltdm)) {
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
+@@ -1687,6 +1795,17 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
+
+ curr_volt = omap_voltage_get_nom_volt(voltdm);
+
++ /* Find the device requesting the voltage scaling */
++ node = plist_first(&vdd->user_list);
++ user = container_of(node, struct omap_vdd_user_list, node);
++
++ /* calculate the voltages for dependent vdd's */
++ if (calc_dep_vdd_volt(user->dev, vdd, volt)) {
++ pr_warning("%s: Error in calculating dependent vdd voltages"
++ "for vdd_%s\n", __func__, voltdm->name);
++ return -EINVAL;
++ }
++
+ if (curr_volt == volt) {
+ is_volt_scaled = 1;
+ } else if (curr_volt < volt) {
+@@ -1721,6 +1840,9 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
+
+ mutex_unlock(&vdd->scaling_mutex);
+
++ /* Scale dependent vdds */
++ scale_dep_vdd(vdd);
++
+ return 0;
+ }
+
+--
+1.6.6.1
+