summaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch195
1 files changed, 195 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch b/extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch
new file mode 100644
index 00000000..6c4ca2ab
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch
@@ -0,0 +1,195 @@
1From b1b41c78d5a19260605fcb259a51ca7cd71c097a Mon Sep 17 00:00:00 2001
2From: Thara Gopinath <thara@ti.com>
3Date: Fri, 2 Jul 2010 13:06:57 +0530
4Subject: [PATCH 11/20] OMAP: Introduce dependent voltage domain support.
5
6There could be dependencies between various voltage domains for
7maintaining system performance or hardware limitation reasons
8like VDD<X> should be at voltage v1 when VDD<Y> is at voltage v2.
9This patch introduce dependent vdd information structures in the
10voltage layer which can be used to populate these dependencies
11for a voltage domain. This patch also adds support to scale
12the dependent vdd and the scalable devices belonging to it
13during the scaling of a main vdd through omap_voltage_scale.
14
15Signed-off-by: Thara Gopinath <thara@ti.com>
16---
17 arch/arm/mach-omap2/voltage.c | 122 +++++++++++++++++++++++++++++++++++++++++
18 1 files changed, 122 insertions(+), 0 deletions(-)
19
20diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
21index 9adf9d1..c83d968 100644
22--- a/arch/arm/mach-omap2/voltage.c
23+++ b/arch/arm/mach-omap2/voltage.c
24@@ -123,6 +123,36 @@ struct vc_reg_info {
25 };
26
27 /**
28+ * omap_vdd_dep_volt - Table containing the parent vdd voltage and the
29+ * dependent vdd voltage corresponding to it.
30+ *
31+ * @main_vdd_volt : The main vdd voltage
32+ * @dep_vdd_volt : The voltage at which the dependent vdd should be
33+ * when the main vdd is at <main_vdd_volt> voltage
34+ */
35+struct omap_vdd_dep_volt {
36+ u32 main_vdd_volt;
37+ u32 dep_vdd_volt;
38+};
39+
40+/**
41+ * omap_vdd_dep_info - Dependent vdd info
42+ *
43+ * @name : Dependent vdd name
44+ * @voltdm : Dependent vdd pointer
45+ * @dep_table : Table containing the dependent vdd voltage
46+ * corresponding to every main vdd voltage.
47+ * @cur_dep_volt : The voltage to which dependent vdd should be put
48+ * to for the current main vdd voltage.
49+ */
50+struct omap_vdd_dep_info {
51+ char *name;
52+ struct voltagedomain *voltdm;
53+ struct omap_vdd_dep_volt *dep_table;
54+ unsigned long cur_dep_volt;
55+};
56+
57+/**
58 * struct omap_vdd_user_list - The per vdd user list
59 *
60 * @dev: The device asking for the vdd to be set at a particular
61@@ -174,11 +204,13 @@ struct omap_vdd_info {
62 struct vp_reg_val vp_reg;
63 struct vc_reg_info vc_reg;
64 struct voltagedomain voltdm;
65+ struct omap_vdd_dep_info *dep_vdd_info;
66 struct dentry *debug_dir;
67 spinlock_t user_lock;
68 struct plist_head user_list;
69 struct mutex scaling_mutex;
70 struct list_head dev_list;
71+ int nr_dep_vdd;
72 u32 curr_volt;
73 u16 ocp_mod;
74 u8 prm_irqst_reg;
75@@ -1160,6 +1192,80 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
76 return 0;
77 }
78
79+static int calc_dep_vdd_volt(struct device *dev,
80+ struct omap_vdd_info *main_vdd, unsigned long main_volt)
81+{
82+ struct omap_vdd_dep_info *dep_vdds;
83+ int i, ret = 0;
84+
85+ if (!main_vdd->dep_vdd_info) {
86+ pr_debug("%s: No dependent VDD's for vdd_%s\n",
87+ __func__, main_vdd->voltdm.name);
88+ return 0;
89+ }
90+
91+ dep_vdds = main_vdd->dep_vdd_info;
92+
93+ for (i = 0; i < main_vdd->nr_dep_vdd; i++) {
94+ struct omap_vdd_dep_volt *volt_table = dep_vdds[i].dep_table;
95+ int nr_volt = 0;
96+ unsigned long dep_volt = 0, act_volt = 0;
97+
98+ while (volt_table[nr_volt].main_vdd_volt != 0) {
99+ if (volt_table[nr_volt].main_vdd_volt == main_volt) {
100+ dep_volt = volt_table[nr_volt].dep_vdd_volt;
101+ break;
102+ }
103+ nr_volt++;
104+ }
105+ if (!dep_volt) {
106+ pr_warning("%s: Not able to find a matching volt for"
107+ "vdd_%s corresponding to vdd_%s %ld volt\n",
108+ __func__, dep_vdds[i].name,
109+ main_vdd->voltdm.name, main_volt);
110+ ret = -EINVAL;
111+ continue;
112+ }
113+
114+ if (!dep_vdds[i].voltdm)
115+ dep_vdds[i].voltdm =
116+ omap_voltage_domain_lookup(dep_vdds[i].name);
117+
118+ act_volt = dep_volt;
119+
120+ /* See if dep_volt is possible for the vdd*/
121+ ret = omap_voltage_add_request(dep_vdds[i].voltdm, dev,
122+ &act_volt);
123+
124+ /*
125+ * Currently we do not bother if the dep volt and act volt are
126+ * different. We could add a check if needed.
127+ */
128+ dep_vdds[i].cur_dep_volt = act_volt;
129+ }
130+
131+ return ret;
132+}
133+
134+static int scale_dep_vdd(struct omap_vdd_info *main_vdd)
135+{
136+ struct omap_vdd_dep_info *dep_vdds;
137+ int i;
138+
139+ if (!main_vdd->dep_vdd_info) {
140+ pr_debug("%s: No dependent VDD's for vdd_%s\n",
141+ __func__, main_vdd->voltdm.name);
142+ return 0;
143+ }
144+
145+ dep_vdds = main_vdd->dep_vdd_info;
146+
147+ for (i = 0; i < main_vdd->nr_dep_vdd; i++)
148+ omap_voltage_scale(dep_vdds[i].voltdm,
149+ dep_vdds[i].cur_dep_volt);
150+ return 0;
151+}
152+
153 /* Public functions */
154 /**
155 * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
156@@ -1675,6 +1781,8 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
157 int is_volt_scaled = 0;
158 struct omap_vdd_info *vdd;
159 struct omap_vdd_dev_list *temp_dev;
160+ struct plist_node *node;
161+ struct omap_vdd_user_list *user;
162
163 if (!voltdm || IS_ERR(voltdm)) {
164 pr_warning("%s: VDD specified does not exist!\n", __func__);
165@@ -1687,6 +1795,17 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
166
167 curr_volt = omap_voltage_get_nom_volt(voltdm);
168
169+ /* Find the device requesting the voltage scaling */
170+ node = plist_first(&vdd->user_list);
171+ user = container_of(node, struct omap_vdd_user_list, node);
172+
173+ /* calculate the voltages for dependent vdd's */
174+ if (calc_dep_vdd_volt(user->dev, vdd, volt)) {
175+ pr_warning("%s: Error in calculating dependent vdd voltages"
176+ "for vdd_%s\n", __func__, voltdm->name);
177+ return -EINVAL;
178+ }
179+
180 if (curr_volt == volt) {
181 is_volt_scaled = 1;
182 } else if (curr_volt < volt) {
183@@ -1721,6 +1840,9 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
184
185 mutex_unlock(&vdd->scaling_mutex);
186
187+ /* Scale dependent vdds */
188+ scale_dep_vdd(vdd);
189+
190 return 0;
191 }
192
193--
1941.6.6.1
195