Commit 3969406b1bc1d11ec362b61ee5c48d551e51fed3

Authored by Nishanth Menon
Committed by Afzal Mohammed
1 parent 0c7242c21a
Exists in master

OMAP2+: DVFS: provide ability to know if dvfs is scaling for a domain

Provide mechanism to know if DVFS is scaling on a specific domain.
This API will allow us to detect transition and take appropriate
measures in idle path

Acked-by: Todd Poynor <toddpoynor@google.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
[vaibhav.bedia@ti.com: Pull in for AM33xx]
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>

Showing 2 changed files with 47 additions and 0 deletions Inline Diff

arch/arm/mach-omap2/dvfs.c
1 /* 1 /*
2 * OMAP3/OMAP4 DVFS Management Routines 2 * OMAP3/OMAP4 DVFS Management Routines
3 * 3 *
4 * Author: Vishwanath BS <vishwanath.bs@ti.com> 4 * Author: Vishwanath BS <vishwanath.bs@ti.com>
5 * 5 *
6 * Copyright (C) 2011 Texas Instruments, Inc. 6 * Copyright (C) 2011 Texas Instruments, Inc.
7 * Vishwanath BS <vishwanath.bs@ti.com> 7 * Vishwanath BS <vishwanath.bs@ti.com>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13 13
14 #include <linux/err.h> 14 #include <linux/err.h>
15 #include <linux/spinlock.h> 15 #include <linux/spinlock.h>
16 #include <linux/plist.h> 16 #include <linux/plist.h>
17 #include <linux/slab.h> 17 #include <linux/slab.h>
18 #include <linux/opp.h> 18 #include <linux/opp.h>
19 #include <linux/clk.h> 19 #include <linux/clk.h>
20 #include <linux/debugfs.h> 20 #include <linux/debugfs.h>
21 #include <linux/seq_file.h> 21 #include <linux/seq_file.h>
22 #include <plat/common.h> 22 #include <plat/common.h>
23 #include <plat/omap_device.h> 23 #include <plat/omap_device.h>
24 #include <plat/omap_hwmod.h> 24 #include <plat/omap_hwmod.h>
25 #include <plat/clock.h> 25 #include <plat/clock.h>
26 #include <plat/dvfs.h> 26 #include <plat/dvfs.h>
27 #include "smartreflex.h" 27 #include "smartreflex.h"
28 #include "powerdomain.h" 28 #include "powerdomain.h"
29 29
30 /** 30 /**
31 * DOC: Introduction 31 * DOC: Introduction
32 * ================= 32 * =================
33 * DVFS is a technique that uses the optimal operating frequency and voltage to 33 * DVFS is a technique that uses the optimal operating frequency and voltage to
34 * allow a task to be performed in the required amount of time. 34 * allow a task to be performed in the required amount of time.
35 * OMAP processors have voltage domains whose voltage can be scaled to 35 * OMAP processors have voltage domains whose voltage can be scaled to
36 * various levels depending on which the operating frequencies of certain 36 * various levels depending on which the operating frequencies of certain
37 * devices belonging to the domain will also need to be scaled. This voltage 37 * devices belonging to the domain will also need to be scaled. This voltage
38 * frequency tuple is known as Operating Performance Point (OPP). A device 38 * frequency tuple is known as Operating Performance Point (OPP). A device
39 * can have multiple OPP's. Also a voltage domain could be shared between 39 * can have multiple OPP's. Also a voltage domain could be shared between
40 * multiple devices. Also there could be dependencies between various 40 * multiple devices. Also there could be dependencies between various
41 * voltage domains for maintaining system performance like VDD<X> 41 * voltage domains for maintaining system performance like VDD<X>
42 * should be at voltage v1 when VDD<Y> is at voltage v2. 42 * should be at voltage v1 when VDD<Y> is at voltage v2.
43 * 43 *
44 * The design of this framework takes into account all the above mentioned 44 * The design of this framework takes into account all the above mentioned
45 * points. To summarize the basic design of DVFS framework:- 45 * points. To summarize the basic design of DVFS framework:-
46 * 46 *
47 * 1. Have device opp tables for each device whose operating frequency can be 47 * 1. Have device opp tables for each device whose operating frequency can be
48 * scaled. This is easy now due to the existance of hwmod layer which 48 * scaled. This is easy now due to the existance of hwmod layer which
49 * allow storing of device specific info. The device opp tables contain 49 * allow storing of device specific info. The device opp tables contain
50 * the opp pairs (frequency voltage tuples), the voltage domain pointer 50 * the opp pairs (frequency voltage tuples), the voltage domain pointer
51 * to which the device belongs to, the device specific set_rate and 51 * to which the device belongs to, the device specific set_rate and
52 * get_rate API's which will do the actual scaling of the device frequency 52 * get_rate API's which will do the actual scaling of the device frequency
53 * and retrieve the current device frequency. 53 * and retrieve the current device frequency.
54 * 2. Introduce use counting on a per VDD basis. This is to take care multiple 54 * 2. Introduce use counting on a per VDD basis. This is to take care multiple
55 * requests to scale a VDD. The VDD will be scaled to the maximum of the 55 * requests to scale a VDD. The VDD will be scaled to the maximum of the
56 * voltages requested. 56 * voltages requested.
57 * 3. Keep track of all scalable devices belonging to a particular voltage 57 * 3. Keep track of all scalable devices belonging to a particular voltage
58 * domain the voltage layer. 58 * domain the voltage layer.
59 * 4. Keep track of frequency requests for each of the device. This will enable 59 * 4. Keep track of frequency requests for each of the device. This will enable
60 * to scale individual devices to different frequency (even w/o scaling 60 * to scale individual devices to different frequency (even w/o scaling
61 * voltage aka frequency throttling) 61 * voltage aka frequency throttling)
62 * 5. Generic dvfs API that can be called by anybody to scale a device opp. 62 * 5. Generic dvfs API that can be called by anybody to scale a device opp.
63 * This API takes the device pointer and frequency to which the device 63 * This API takes the device pointer and frequency to which the device
64 * needs to be scaled to. This API then internally finds out the voltage 64 * needs to be scaled to. This API then internally finds out the voltage
65 * domain to which the device belongs to and the voltage to which the voltage 65 * domain to which the device belongs to and the voltage to which the voltage
66 * domain needs to be put to for the device to be scaled to the new frequency 66 * domain needs to be put to for the device to be scaled to the new frequency
67 * from he device opp table. Then this API will add requested frequency into 67 * from he device opp table. Then this API will add requested frequency into
68 * the corresponding target device frequency list and add voltage request to 68 * the corresponding target device frequency list and add voltage request to
69 * the corresponding vdd. Subsequently it calls voltage scale function which 69 * the corresponding vdd. Subsequently it calls voltage scale function which
70 * will find out the highest requested voltage for the given vdd and scales 70 * will find out the highest requested voltage for the given vdd and scales
71 * the voltage to the required one. It also runs through the list of all 71 * the voltage to the required one. It also runs through the list of all
72 * scalable devices belonging to this voltage domain and scale them to the 72 * scalable devices belonging to this voltage domain and scale them to the
73 * appropriate frequencies using the set_rate pointer in the device opp 73 * appropriate frequencies using the set_rate pointer in the device opp
74 * tables. 74 * tables.
75 * 6. Handle inter VDD dependecies. 75 * 6. Handle inter VDD dependecies.
76 * 76 *
77 * 77 *
78 * DOC: The Core DVFS data structure: 78 * DOC: The Core DVFS data structure:
79 * ================================== 79 * ==================================
80 * Structure Name Example Tree 80 * Structure Name Example Tree
81 * --------- 81 * ---------
82 * /|\ +-------------------+ +-------------------+ 82 * /|\ +-------------------+ +-------------------+
83 * | |User2 (dev2, freq2)+---\ |User4 (dev4, freq4)+---\ 83 * | |User2 (dev2, freq2)+---\ |User4 (dev4, freq4)+---\
84 * | +-------------------+ | +-------------------+ | 84 * | +-------------------+ | +-------------------+ |
85 * (struct omap_dev_user_list) | | 85 * (struct omap_dev_user_list) | |
86 * | +-------------------+ | +-------------------+ | 86 * | +-------------------+ | +-------------------+ |
87 * | |User1 (dev1, freq1)+---| |User3 (dev3, freq3)+---| 87 * | |User1 (dev1, freq1)+---| |User3 (dev3, freq3)+---|
88 * \|/ +-------------------+ | +-------------------+ | 88 * \|/ +-------------------+ | +-------------------+ |
89 * --------- | | 89 * --------- | |
90 * /|\ +------------+------+ +---------------+--+ 90 * /|\ +------------+------+ +---------------+--+
91 * | | DEV1 (dev, | | DEV2 (dev) | 91 * | | DEV1 (dev, | | DEV2 (dev) |
92 * (struct omap_vdd_dev_list)|omap_dev_user_list)| |omap_dev_user_list| 92 * (struct omap_vdd_dev_list)|omap_dev_user_list)| |omap_dev_user_list|
93 * | +------------+------+ +--+---------------+ 93 * | +------------+------+ +--+---------------+
94 * \|/ /|\ /-----+-------------+------> others.. 94 * \|/ /|\ /-----+-------------+------> others..
95 * --------- Frequency | 95 * --------- Frequency |
96 * /|\ +--+------------------+ 96 * /|\ +--+------------------+
97 * | | VDD_n | 97 * | | VDD_n |
98 * | | (omap_vdd_dev_list, | 98 * | | (omap_vdd_dev_list, |
99 * (struct omap_vdd_dvfs_info)** | omap_vdd_user_list) | 99 * (struct omap_vdd_dvfs_info)** | omap_vdd_user_list) |
100 * | +--+------------------+ 100 * | +--+------------------+
101 * | | (ROOT NODE: omap_dvfs_info_list) 101 * | | (ROOT NODE: omap_dvfs_info_list)
102 * \|/ | 102 * \|/ |
103 * --------- Voltage \---+-------------+----------> others.. 103 * --------- Voltage \---+-------------+----------> others..
104 * /|\ \|/ +-------+----+ +-----+--------+ 104 * /|\ \|/ +-------+----+ +-----+--------+
105 * | | vdd_user2 | | vdd_user3 | 105 * | | vdd_user2 | | vdd_user3 |
106 * (struct omap_vdd_user_list) | (dev, volt)| | (dev, volt) | 106 * (struct omap_vdd_user_list) | (dev, volt)| | (dev, volt) |
107 * \|/ +------------+ +--------------+ 107 * \|/ +------------+ +--------------+
108 * --------- 108 * ---------
109 * Key: ** -> Root of the tree. 109 * Key: ** -> Root of the tree.
110 * NOTE: we use the priority to store the voltage/frequency 110 * NOTE: we use the priority to store the voltage/frequency
111 * 111 *
112 * For voltage dependency description, see: struct dependency: 112 * For voltage dependency description, see: struct dependency:
113 * voltagedomain -> (description of the voltagedomain) 113 * voltagedomain -> (description of the voltagedomain)
114 * omap_vdd_info -> (vdd information) 114 * omap_vdd_info -> (vdd information)
115 * omap_vdd_dep_info[]-> (stores array of depedency info) 115 * omap_vdd_dep_info[]-> (stores array of depedency info)
116 * omap_vdd_dep_volt[] -> (stores array of maps) 116 * omap_vdd_dep_volt[] -> (stores array of maps)
117 * (main_volt -> dep_volt) (a singular map) 117 * (main_volt -> dep_volt) (a singular map)
118 */ 118 */
119 119
120 /* Macros to give idea about scaling directions */ 120 /* Macros to give idea about scaling directions */
121 #define DVFS_VOLT_SCALE_DOWN 0 121 #define DVFS_VOLT_SCALE_DOWN 0
122 #define DVFS_VOLT_SCALE_NONE 1 122 #define DVFS_VOLT_SCALE_NONE 1
123 #define DVFS_VOLT_SCALE_UP 2 123 #define DVFS_VOLT_SCALE_UP 2
124 124
125 /** 125 /**
126 * struct omap_dev_user_list - Structure maitain userlist per devide 126 * struct omap_dev_user_list - Structure maitain userlist per devide
127 * @dev: The device requesting for a particular frequency 127 * @dev: The device requesting for a particular frequency
128 * @node: The list head entry 128 * @node: The list head entry
129 * 129 *
130 * Using this structure, user list (requesting dev * and frequency) for 130 * Using this structure, user list (requesting dev * and frequency) for
131 * each device is maintained. This is how we can have different devices 131 * each device is maintained. This is how we can have different devices
132 * at different frequencies (to support frequency locking and throttling). 132 * at different frequencies (to support frequency locking and throttling).
133 * Even if one of the devices in a given vdd has locked it's frequency, 133 * Even if one of the devices in a given vdd has locked it's frequency,
134 * other's can still scale their frequency using this list. 134 * other's can still scale their frequency using this list.
135 * If no one has placed a frequency request for a device, then device is 135 * If no one has placed a frequency request for a device, then device is
136 * set to the frequency from it's opp table. 136 * set to the frequency from it's opp table.
137 */ 137 */
138 struct omap_dev_user_list { 138 struct omap_dev_user_list {
139 struct device *dev; 139 struct device *dev;
140 struct plist_node node; 140 struct plist_node node;
141 }; 141 };
142 142
143 /** 143 /**
144 * struct omap_vdd_dev_list - Device list per vdd 144 * struct omap_vdd_dev_list - Device list per vdd
145 * @dev: The device belonging to a particular vdd 145 * @dev: The device belonging to a particular vdd
146 * @node: The list head entry 146 * @node: The list head entry
147 * @freq_user_list: The list of users for vdd device 147 * @freq_user_list: The list of users for vdd device
148 * @clk: frequency control clock for this dev 148 * @clk: frequency control clock for this dev
149 * @user_lock: The lock for plist manipulation 149 * @user_lock: The lock for plist manipulation
150 */ 150 */
151 struct omap_vdd_dev_list { 151 struct omap_vdd_dev_list {
152 struct device *dev; 152 struct device *dev;
153 struct list_head node; 153 struct list_head node;
154 struct plist_head freq_user_list; 154 struct plist_head freq_user_list;
155 struct clk *clk; 155 struct clk *clk;
156 spinlock_t user_lock; /* spinlock for plist */ 156 spinlock_t user_lock; /* spinlock for plist */
157 }; 157 };
158 158
159 /** 159 /**
160 * struct omap_vdd_user_list - The per vdd user list 160 * struct omap_vdd_user_list - The per vdd user list
161 * @dev: The device asking for the vdd to be set at a particular 161 * @dev: The device asking for the vdd to be set at a particular
162 * voltage 162 * voltage
163 * @node: The list head entry 163 * @node: The list head entry
164 */ 164 */
165 struct omap_vdd_user_list { 165 struct omap_vdd_user_list {
166 struct device *dev; 166 struct device *dev;
167 struct plist_node node; 167 struct plist_node node;
168 }; 168 };
169 169
170 /** 170 /**
171 * struct omap_vdd_dvfs_info - The per vdd dvfs info 171 * struct omap_vdd_dvfs_info - The per vdd dvfs info
172 * @node: list node for vdd_dvfs_info list 172 * @node: list node for vdd_dvfs_info list
173 * @user_lock: spinlock for plist operations 173 * @user_lock: spinlock for plist operations
174 * @vdd_user_list: The vdd user list 174 * @vdd_user_list: The vdd user list
175 * @voltdm: Voltage domains for which dvfs info stored 175 * @voltdm: Voltage domains for which dvfs info stored
176 * @dev_list: Device list maintained per domain 176 * @dev_list: Device list maintained per domain
177 * @is_scaling: flag to store information about scaling in progress or not
178 * this flag is already protected by the global mutex.
177 * 179 *
178 * This is a fundamental structure used to store all the required 180 * This is a fundamental structure used to store all the required
179 * DVFS related information for a vdd. 181 * DVFS related information for a vdd.
180 */ 182 */
181 struct omap_vdd_dvfs_info { 183 struct omap_vdd_dvfs_info {
182 struct list_head node; 184 struct list_head node;
183 185
184 spinlock_t user_lock; /* spin lock */ 186 spinlock_t user_lock; /* spin lock */
185 struct plist_head vdd_user_list; 187 struct plist_head vdd_user_list;
186 struct voltagedomain *voltdm; 188 struct voltagedomain *voltdm;
187 struct list_head dev_list; 189 struct list_head dev_list;
190 bool is_scaling;
188 }; 191 };
189 192
190 static LIST_HEAD(omap_dvfs_info_list); 193 static LIST_HEAD(omap_dvfs_info_list);
191 static DEFINE_MUTEX(omap_dvfs_lock); 194 static DEFINE_MUTEX(omap_dvfs_lock);
192 195
193 /* Dvfs scale helper function */ 196 /* Dvfs scale helper function */
194 static int _dvfs_scale(struct device *req_dev, struct device *target_dev, 197 static int _dvfs_scale(struct device *req_dev, struct device *target_dev,
195 struct omap_vdd_dvfs_info *tdvfs_info); 198 struct omap_vdd_dvfs_info *tdvfs_info);
196 199
197 /* Few search functions to traverse and find pointers of interest */ 200 /* Few search functions to traverse and find pointers of interest */
198 201
199 /** 202 /**
200 * _dvfs_info_to_dev() - Locate the parent device associated to dvfs_info 203 * _dvfs_info_to_dev() - Locate the parent device associated to dvfs_info
201 * @dvfs_info: dvfs_info to search for 204 * @dvfs_info: dvfs_info to search for
202 * 205 *
203 * Returns NULL on failure. 206 * Returns NULL on failure.
204 */ 207 */
205 static struct device *_dvfs_info_to_dev(struct omap_vdd_dvfs_info *dvfs_info) 208 static struct device *_dvfs_info_to_dev(struct omap_vdd_dvfs_info *dvfs_info)
206 { 209 {
207 struct omap_vdd_dev_list *tmp_dev; 210 struct omap_vdd_dev_list *tmp_dev;
208 if (IS_ERR_OR_NULL(dvfs_info)) 211 if (IS_ERR_OR_NULL(dvfs_info))
209 return NULL; 212 return NULL;
210 if (list_empty(&dvfs_info->dev_list)) 213 if (list_empty(&dvfs_info->dev_list))
211 return NULL; 214 return NULL;
212 tmp_dev = list_first_entry(&dvfs_info->dev_list, 215 tmp_dev = list_first_entry(&dvfs_info->dev_list,
213 struct omap_vdd_dev_list, node); 216 struct omap_vdd_dev_list, node);
214 return tmp_dev->dev; 217 return tmp_dev->dev;
215 } 218 }
216 219
217 /** 220 /**
218 * _dev_to_dvfs_info() - Locate the dvfs_info for a device 221 * _dev_to_dvfs_info() - Locate the dvfs_info for a device
219 * @dev: dev to search for 222 * @dev: dev to search for
220 * 223 *
221 * Returns NULL on failure. 224 * Returns NULL on failure.
222 */ 225 */
223 static struct omap_vdd_dvfs_info *_dev_to_dvfs_info(struct device *dev) 226 static struct omap_vdd_dvfs_info *_dev_to_dvfs_info(struct device *dev)
224 { 227 {
225 struct omap_vdd_dvfs_info *dvfs_info; 228 struct omap_vdd_dvfs_info *dvfs_info;
226 struct omap_vdd_dev_list *temp_dev; 229 struct omap_vdd_dev_list *temp_dev;
227 230
228 if (IS_ERR_OR_NULL(dev)) 231 if (IS_ERR_OR_NULL(dev))
229 return NULL; 232 return NULL;
230 233
231 list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) { 234 list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) {
232 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { 235 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) {
233 if (temp_dev->dev == dev) 236 if (temp_dev->dev == dev)
234 return dvfs_info; 237 return dvfs_info;
235 } 238 }
236 } 239 }
237 240
238 return NULL; 241 return NULL;
239 } 242 }
240 243
241 /** 244 /**
242 * _voltdm_to_dvfs_info() - Locate a dvfs_info given a voltdm pointer 245 * _voltdm_to_dvfs_info() - Locate a dvfs_info given a voltdm pointer
243 * @voltdm: voltdm to search for 246 * @voltdm: voltdm to search for
244 * 247 *
245 * Returns NULL on failure. 248 * Returns NULL on failure.
246 */ 249 */
247 static 250 static
248 struct omap_vdd_dvfs_info *_voltdm_to_dvfs_info(struct voltagedomain *voltdm) 251 struct omap_vdd_dvfs_info *_voltdm_to_dvfs_info(struct voltagedomain *voltdm)
249 { 252 {
250 struct omap_vdd_dvfs_info *dvfs_info; 253 struct omap_vdd_dvfs_info *dvfs_info;
251 254
252 if (IS_ERR_OR_NULL(voltdm)) 255 if (IS_ERR_OR_NULL(voltdm))
253 return NULL; 256 return NULL;
254 257
255 list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) { 258 list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) {
256 if (dvfs_info->voltdm == voltdm) 259 if (dvfs_info->voltdm == voltdm)
257 return dvfs_info; 260 return dvfs_info;
258 } 261 }
259 262
260 return NULL; 263 return NULL;
261 } 264 }
262 265
263 /** 266 /**
264 * _volt_to_opp() - Find OPP corresponding to a given voltage 267 * _volt_to_opp() - Find OPP corresponding to a given voltage
265 * @dev: device pointer associated with the OPP list 268 * @dev: device pointer associated with the OPP list
266 * @volt: voltage to search for in uV 269 * @volt: voltage to search for in uV
267 * 270 *
268 * Searches for exact match in the OPP list and returns handle to the matching 271 * Searches for exact match in the OPP list and returns handle to the matching
269 * OPP if found, else returns ERR_PTR in case of error and should be handled 272 * OPP if found, else returns ERR_PTR in case of error and should be handled
270 * using IS_ERR. If there are multiple opps with same voltage, it will return 273 * using IS_ERR. If there are multiple opps with same voltage, it will return
271 * the first available entry. Return pointer should be checked against IS_ERR. 274 * the first available entry. Return pointer should be checked against IS_ERR.
272 * 275 *
273 * NOTE: since this uses OPP functions, use under rcu_lock. This function also 276 * NOTE: since this uses OPP functions, use under rcu_lock. This function also
274 * assumes that the cpufreq table and OPP table are in sync - any modifications 277 * assumes that the cpufreq table and OPP table are in sync - any modifications
275 * to either should be synchronized. 278 * to either should be synchronized.
276 */ 279 */
277 static struct opp *_volt_to_opp(struct device *dev, unsigned long volt) 280 static struct opp *_volt_to_opp(struct device *dev, unsigned long volt)
278 { 281 {
279 struct opp *opp = ERR_PTR(-ENODEV); 282 struct opp *opp = ERR_PTR(-ENODEV);
280 unsigned long f = 0; 283 unsigned long f = 0;
281 284
282 do { 285 do {
283 opp = opp_find_freq_ceil(dev, &f); 286 opp = opp_find_freq_ceil(dev, &f);
284 if (IS_ERR(opp)) 287 if (IS_ERR(opp))
285 break; 288 break;
286 if (opp_get_voltage(opp) >= volt) 289 if (opp_get_voltage(opp) >= volt)
287 break; 290 break;
288 f++; 291 f++;
289 } while (1); 292 } while (1);
290 293
291 return opp; 294 return opp;
292 } 295 }
293 296
294 /* rest of the helper functions */ 297 /* rest of the helper functions */
295 /** 298 /**
296 * _add_vdd_user() - Add a voltage request 299 * _add_vdd_user() - Add a voltage request
297 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd 300 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd
298 * @dev: device making the request 301 * @dev: device making the request
299 * @volt: requested voltage in uV 302 * @volt: requested voltage in uV
300 * 303 *
301 * Adds the given device's voltage request into corresponding 304 * Adds the given device's voltage request into corresponding
302 * vdd's omap_vdd_dvfs_info user list (plist). This list is used 305 * vdd's omap_vdd_dvfs_info user list (plist). This list is used
303 * to find the maximum voltage request for a given vdd. 306 * to find the maximum voltage request for a given vdd.
304 * 307 *
305 * Returns 0 on success. 308 * Returns 0 on success.
306 */ 309 */
307 static int _add_vdd_user(struct omap_vdd_dvfs_info *dvfs_info, 310 static int _add_vdd_user(struct omap_vdd_dvfs_info *dvfs_info,
308 struct device *dev, unsigned long volt) 311 struct device *dev, unsigned long volt)
309 { 312 {
310 struct omap_vdd_user_list *user = NULL, *temp_user; 313 struct omap_vdd_user_list *user = NULL, *temp_user;
311 314
312 if (!dvfs_info || IS_ERR(dvfs_info)) { 315 if (!dvfs_info || IS_ERR(dvfs_info)) {
313 dev_warn(dev, "%s: VDD specified does not exist!\n", __func__); 316 dev_warn(dev, "%s: VDD specified does not exist!\n", __func__);
314 return -EINVAL; 317 return -EINVAL;
315 } 318 }
316 319
317 spin_lock(&dvfs_info->user_lock); 320 spin_lock(&dvfs_info->user_lock);
318 plist_for_each_entry(temp_user, &dvfs_info->vdd_user_list, node) { 321 plist_for_each_entry(temp_user, &dvfs_info->vdd_user_list, node) {
319 if (temp_user->dev == dev) { 322 if (temp_user->dev == dev) {
320 user = temp_user; 323 user = temp_user;
321 break; 324 break;
322 } 325 }
323 } 326 }
324 327
325 if (!user) { 328 if (!user) {
326 user = kzalloc(sizeof(struct omap_vdd_user_list), GFP_ATOMIC); 329 user = kzalloc(sizeof(struct omap_vdd_user_list), GFP_ATOMIC);
327 if (!user) { 330 if (!user) {
328 dev_err(dev, 331 dev_err(dev,
329 "%s: Unable to creat a new user for vdd_%s\n", 332 "%s: Unable to creat a new user for vdd_%s\n",
330 __func__, dvfs_info->voltdm->name); 333 __func__, dvfs_info->voltdm->name);
331 spin_unlock(&dvfs_info->user_lock); 334 spin_unlock(&dvfs_info->user_lock);
332 return -ENOMEM; 335 return -ENOMEM;
333 } 336 }
334 user->dev = dev; 337 user->dev = dev;
335 } else { 338 } else {
336 plist_del(&user->node, &dvfs_info->vdd_user_list); 339 plist_del(&user->node, &dvfs_info->vdd_user_list);
337 } 340 }
338 341
339 plist_node_init(&user->node, volt); 342 plist_node_init(&user->node, volt);
340 plist_add(&user->node, &dvfs_info->vdd_user_list); 343 plist_add(&user->node, &dvfs_info->vdd_user_list);
341 344
342 spin_unlock(&dvfs_info->user_lock); 345 spin_unlock(&dvfs_info->user_lock);
343 return 0; 346 return 0;
344 } 347 }
345 348
346 /** 349 /**
347 * _remove_vdd_user() - Remove a voltage request 350 * _remove_vdd_user() - Remove a voltage request
348 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd 351 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd
349 * @dev: device making the request 352 * @dev: device making the request
350 * 353 *
351 * Removes the given device's voltage request from corresponding 354 * Removes the given device's voltage request from corresponding
352 * vdd's omap_vdd_dvfs_info user list (plist). 355 * vdd's omap_vdd_dvfs_info user list (plist).
353 * 356 *
354 * Returns 0 on success. 357 * Returns 0 on success.
355 */ 358 */
356 static int _remove_vdd_user(struct omap_vdd_dvfs_info *dvfs_info, 359 static int _remove_vdd_user(struct omap_vdd_dvfs_info *dvfs_info,
357 struct device *dev) 360 struct device *dev)
358 { 361 {
359 struct omap_vdd_user_list *user = NULL, *temp_user; 362 struct omap_vdd_user_list *user = NULL, *temp_user;
360 int ret = 0; 363 int ret = 0;
361 364
362 if (!dvfs_info || IS_ERR(dvfs_info)) { 365 if (!dvfs_info || IS_ERR(dvfs_info)) {
363 dev_err(dev, "%s: VDD specified does not exist!\n", __func__); 366 dev_err(dev, "%s: VDD specified does not exist!\n", __func__);
364 return -EINVAL; 367 return -EINVAL;
365 } 368 }
366 369
367 spin_lock(&dvfs_info->user_lock); 370 spin_lock(&dvfs_info->user_lock);
368 plist_for_each_entry(temp_user, &dvfs_info->vdd_user_list, node) { 371 plist_for_each_entry(temp_user, &dvfs_info->vdd_user_list, node) {
369 if (temp_user->dev == dev) { 372 if (temp_user->dev == dev) {
370 user = temp_user; 373 user = temp_user;
371 break; 374 break;
372 } 375 }
373 } 376 }
374 377
375 if (user) 378 if (user)
376 plist_del(&user->node, &dvfs_info->vdd_user_list); 379 plist_del(&user->node, &dvfs_info->vdd_user_list);
377 else { 380 else {
378 dev_err(dev, "%s: Unable to find the user for vdd_%s\n", 381 dev_err(dev, "%s: Unable to find the user for vdd_%s\n",
379 __func__, dvfs_info->voltdm->name); 382 __func__, dvfs_info->voltdm->name);
380 ret = -ENOENT; 383 ret = -ENOENT;
381 } 384 }
382 385
383 spin_unlock(&dvfs_info->user_lock); 386 spin_unlock(&dvfs_info->user_lock);
384 kfree(user); 387 kfree(user);
385 388
386 return ret; 389 return ret;
387 } 390 }
388 391
389 /** 392 /**
390 * _add_freq_request() - Add a requested device frequency 393 * _add_freq_request() - Add a requested device frequency
391 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd 394 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd
392 * @req_dev: device making the request 395 * @req_dev: device making the request
393 * @target_dev: target device for which frequency request is being made 396 * @target_dev: target device for which frequency request is being made
394 * @freq: target device frequency 397 * @freq: target device frequency
395 * 398 *
396 * This adds a requested frequency into target device's frequency list. 399 * This adds a requested frequency into target device's frequency list.
397 * 400 *
398 * Returns 0 on success. 401 * Returns 0 on success.
399 */ 402 */
400 static int _add_freq_request(struct omap_vdd_dvfs_info *dvfs_info, 403 static int _add_freq_request(struct omap_vdd_dvfs_info *dvfs_info,
401 struct device *req_dev, struct device *target_dev, unsigned long freq) 404 struct device *req_dev, struct device *target_dev, unsigned long freq)
402 { 405 {
403 struct omap_dev_user_list *dev_user = NULL, *tmp_user; 406 struct omap_dev_user_list *dev_user = NULL, *tmp_user;
404 struct omap_vdd_dev_list *temp_dev; 407 struct omap_vdd_dev_list *temp_dev;
405 408
406 if (!dvfs_info || IS_ERR(dvfs_info)) { 409 if (!dvfs_info || IS_ERR(dvfs_info)) {
407 dev_warn(target_dev, "%s: VDD specified does not exist!\n", 410 dev_warn(target_dev, "%s: VDD specified does not exist!\n",
408 __func__); 411 __func__);
409 return -EINVAL; 412 return -EINVAL;
410 } 413 }
411 414
412 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { 415 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) {
413 if (temp_dev->dev == target_dev) 416 if (temp_dev->dev == target_dev)
414 break; 417 break;
415 } 418 }
416 419
417 if (temp_dev->dev != target_dev) { 420 if (temp_dev->dev != target_dev) {
418 dev_warn(target_dev, "%s: target_dev does not exist!\n", 421 dev_warn(target_dev, "%s: target_dev does not exist!\n",
419 __func__); 422 __func__);
420 return -EINVAL; 423 return -EINVAL;
421 } 424 }
422 425
423 spin_lock(&temp_dev->user_lock); 426 spin_lock(&temp_dev->user_lock);
424 plist_for_each_entry(tmp_user, &temp_dev->freq_user_list, node) { 427 plist_for_each_entry(tmp_user, &temp_dev->freq_user_list, node) {
425 if (tmp_user->dev == req_dev) { 428 if (tmp_user->dev == req_dev) {
426 dev_user = tmp_user; 429 dev_user = tmp_user;
427 break; 430 break;
428 } 431 }
429 } 432 }
430 433
431 if (!dev_user) { 434 if (!dev_user) {
432 dev_user = kzalloc(sizeof(struct omap_dev_user_list), 435 dev_user = kzalloc(sizeof(struct omap_dev_user_list),
433 GFP_ATOMIC); 436 GFP_ATOMIC);
434 if (!dev_user) { 437 if (!dev_user) {
435 dev_err(target_dev, 438 dev_err(target_dev,
436 "%s: Unable to creat a new user for vdd_%s\n", 439 "%s: Unable to creat a new user for vdd_%s\n",
437 __func__, dvfs_info->voltdm->name); 440 __func__, dvfs_info->voltdm->name);
438 spin_unlock(&temp_dev->user_lock); 441 spin_unlock(&temp_dev->user_lock);
439 return -ENOMEM; 442 return -ENOMEM;
440 } 443 }
441 dev_user->dev = req_dev; 444 dev_user->dev = req_dev;
442 } else { 445 } else {
443 plist_del(&dev_user->node, &temp_dev->freq_user_list); 446 plist_del(&dev_user->node, &temp_dev->freq_user_list);
444 } 447 }
445 448
446 plist_node_init(&dev_user->node, freq); 449 plist_node_init(&dev_user->node, freq);
447 plist_add(&dev_user->node, &temp_dev->freq_user_list); 450 plist_add(&dev_user->node, &temp_dev->freq_user_list);
448 spin_unlock(&temp_dev->user_lock); 451 spin_unlock(&temp_dev->user_lock);
449 return 0; 452 return 0;
450 } 453 }
451 454
452 /** 455 /**
453 * _remove_freq_request() - Remove the requested device frequency 456 * _remove_freq_request() - Remove the requested device frequency
454 * 457 *
455 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd 458 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd
456 * @req_dev: device removing the request 459 * @req_dev: device removing the request
457 * @target_dev: target device from which frequency request is being removed 460 * @target_dev: target device from which frequency request is being removed
458 * 461 *
459 * This removes a requested frequency from target device's frequency list. 462 * This removes a requested frequency from target device's frequency list.
460 * 463 *
461 * Returns 0 on success. 464 * Returns 0 on success.
462 */ 465 */
463 static int _remove_freq_request(struct omap_vdd_dvfs_info *dvfs_info, 466 static int _remove_freq_request(struct omap_vdd_dvfs_info *dvfs_info,
464 struct device *req_dev, struct device *target_dev) 467 struct device *req_dev, struct device *target_dev)
465 { 468 {
466 struct omap_dev_user_list *dev_user = NULL, *tmp_user; 469 struct omap_dev_user_list *dev_user = NULL, *tmp_user;
467 int ret = 0; 470 int ret = 0;
468 struct omap_vdd_dev_list *temp_dev; 471 struct omap_vdd_dev_list *temp_dev;
469 472
470 if (!dvfs_info || IS_ERR(dvfs_info)) { 473 if (!dvfs_info || IS_ERR(dvfs_info)) {
471 dev_warn(target_dev, "%s: VDD specified does not exist!\n", 474 dev_warn(target_dev, "%s: VDD specified does not exist!\n",
472 __func__); 475 __func__);
473 return -EINVAL; 476 return -EINVAL;
474 } 477 }
475 478
476 479
477 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { 480 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) {
478 if (temp_dev->dev == target_dev) 481 if (temp_dev->dev == target_dev)
479 break; 482 break;
480 } 483 }
481 484
482 if (temp_dev->dev != target_dev) { 485 if (temp_dev->dev != target_dev) {
483 dev_warn(target_dev, "%s: target_dev does not exist!\n", 486 dev_warn(target_dev, "%s: target_dev does not exist!\n",
484 __func__); 487 __func__);
485 return -EINVAL; 488 return -EINVAL;
486 } 489 }
487 490
488 spin_lock(&temp_dev->user_lock); 491 spin_lock(&temp_dev->user_lock);
489 plist_for_each_entry(tmp_user, &temp_dev->freq_user_list, node) { 492 plist_for_each_entry(tmp_user, &temp_dev->freq_user_list, node) {
490 if (tmp_user->dev == req_dev) { 493 if (tmp_user->dev == req_dev) {
491 dev_user = tmp_user; 494 dev_user = tmp_user;
492 break; 495 break;
493 } 496 }
494 } 497 }
495 498
496 if (dev_user) { 499 if (dev_user) {
497 plist_del(&dev_user->node, &temp_dev->freq_user_list); 500 plist_del(&dev_user->node, &temp_dev->freq_user_list);
498 } else { 501 } else {
499 dev_err(target_dev, 502 dev_err(target_dev,
500 "%s: Unable to remove the user for vdd_%s\n", 503 "%s: Unable to remove the user for vdd_%s\n",
501 __func__, dvfs_info->voltdm->name); 504 __func__, dvfs_info->voltdm->name);
502 ret = -EINVAL; 505 ret = -EINVAL;
503 } 506 }
504 507
505 spin_unlock(&temp_dev->user_lock); 508 spin_unlock(&temp_dev->user_lock);
506 kfree(dev_user); 509 kfree(dev_user);
507 510
508 return ret; 511 return ret;
509 } 512 }
510 513
511 /** 514 /**
512 * _dep_scan_table() - Scan a dependency table and mark for scaling 515 * _dep_scan_table() - Scan a dependency table and mark for scaling
513 * @dev: device requesting the dependency scan (req_dev) 516 * @dev: device requesting the dependency scan (req_dev)
514 * @dep_info: dependency information (contains the table) 517 * @dep_info: dependency information (contains the table)
515 * @main_volt: voltage dependency to search for 518 * @main_volt: voltage dependency to search for
516 * 519 *
517 * This runs down the table provided to find the match for main_volt 520 * This runs down the table provided to find the match for main_volt
518 * provided and sets up a scale request for the dependent domain 521 * provided and sets up a scale request for the dependent domain
519 * for the dependent voltage. 522 * for the dependent voltage.
520 * 523 *
521 * Returns 0 if all went well. 524 * Returns 0 if all went well.
522 */ 525 */
523 static int _dep_scan_table(struct device *dev, 526 static int _dep_scan_table(struct device *dev,
524 struct omap_vdd_dep_info *dep_info, unsigned long main_volt) 527 struct omap_vdd_dep_info *dep_info, unsigned long main_volt)
525 { 528 {
526 struct omap_vdd_dep_volt *dep_table = dep_info->dep_table; 529 struct omap_vdd_dep_volt *dep_table = dep_info->dep_table;
527 int i; 530 int i;
528 unsigned long dep_volt = 0; 531 unsigned long dep_volt = 0;
529 532
530 if (!dep_table) { 533 if (!dep_table) {
531 dev_err(dev, "%s: deptable not present for vdd%s\n", 534 dev_err(dev, "%s: deptable not present for vdd%s\n",
532 __func__, dep_info->name); 535 __func__, dep_info->name);
533 return -EINVAL; 536 return -EINVAL;
534 } 537 }
535 538
536 /* Now scan through the the dep table for a match */ 539 /* Now scan through the the dep table for a match */
537 for (i = 0; i < dep_info->nr_dep_entries; i++) { 540 for (i = 0; i < dep_info->nr_dep_entries; i++) {
538 if (dep_table[i].main_vdd_volt == main_volt) { 541 if (dep_table[i].main_vdd_volt == main_volt) {
539 dep_volt = dep_table[i].dep_vdd_volt; 542 dep_volt = dep_table[i].dep_vdd_volt;
540 break; 543 break;
541 } 544 }
542 } 545 }
543 if (!dep_volt) { 546 if (!dep_volt) {
544 dev_warn(dev, "%s: %ld volt map missing in vdd_%s\n", 547 dev_warn(dev, "%s: %ld volt map missing in vdd_%s\n",
545 __func__, main_volt, dep_info->name); 548 __func__, main_volt, dep_info->name);
546 return -EINVAL; 549 return -EINVAL;
547 } 550 }
548 551
549 /* populate voltdm if it is not present */ 552 /* populate voltdm if it is not present */
550 if (!dep_info->_dep_voltdm) { 553 if (!dep_info->_dep_voltdm) {
551 dep_info->_dep_voltdm = voltdm_lookup(dep_info->name); 554 dep_info->_dep_voltdm = voltdm_lookup(dep_info->name);
552 if (!dep_info->_dep_voltdm) { 555 if (!dep_info->_dep_voltdm) {
553 dev_warn(dev, "%s: unable to get vdm%s\n", 556 dev_warn(dev, "%s: unable to get vdm%s\n",
554 __func__, dep_info->name); 557 __func__, dep_info->name);
555 return -ENODEV; 558 return -ENODEV;
556 } 559 }
557 } 560 }
558 561
559 /* See if dep_volt is possible for the vdd*/ 562 /* See if dep_volt is possible for the vdd*/
560 i = _add_vdd_user(_voltdm_to_dvfs_info(dep_info->_dep_voltdm), 563 i = _add_vdd_user(_voltdm_to_dvfs_info(dep_info->_dep_voltdm),
561 dev, dep_volt); 564 dev, dep_volt);
562 if (i) 565 if (i)
563 dev_err(dev, "%s: Failed to add dep to domain %s volt=%ld\n", 566 dev_err(dev, "%s: Failed to add dep to domain %s volt=%ld\n",
564 __func__, dep_info->name, dep_volt); 567 __func__, dep_info->name, dep_volt);
565 return i; 568 return i;
566 } 569 }
567 570
568 /** 571 /**
569 * _dep_scan_domains() - Scan dependency domains for a device 572 * _dep_scan_domains() - Scan dependency domains for a device
570 * @dev: device requesting the scan 573 * @dev: device requesting the scan
571 * @vdd: vdd_info corresponding to the device 574 * @vdd: vdd_info corresponding to the device
572 * @main_volt: voltage to scan for 575 * @main_volt: voltage to scan for
573 * 576 *
574 * Since each domain *may* have multiple dependent domains, we scan 577 * Since each domain *may* have multiple dependent domains, we scan
575 * through each of the dependent domains and invoke _dep_scan_table to 578 * through each of the dependent domains and invoke _dep_scan_table to
576 * scan each table for dependent domain for dependency scaling. 579 * scan each table for dependent domain for dependency scaling.
577 * 580 *
578 * This assumes that the dependent domain information is NULL entry terminated. 581 * This assumes that the dependent domain information is NULL entry terminated.
579 * Returns 0 if all went well. 582 * Returns 0 if all went well.
580 */ 583 */
581 static int _dep_scan_domains(struct device *dev, 584 static int _dep_scan_domains(struct device *dev,
582 struct omap_vdd_info *vdd, unsigned long main_volt) 585 struct omap_vdd_info *vdd, unsigned long main_volt)
583 { 586 {
584 struct omap_vdd_dep_info *dep_info = vdd->dep_vdd_info; 587 struct omap_vdd_dep_info *dep_info = vdd->dep_vdd_info;
585 int ret = 0, r; 588 int ret = 0, r;
586 589
587 if (!dep_info) { 590 if (!dep_info) {
588 dev_dbg(dev, "%s: No dependent VDD\n", __func__); 591 dev_dbg(dev, "%s: No dependent VDD\n", __func__);
589 return 0; 592 return 0;
590 } 593 }
591 594
592 /* First scan through the mydomain->dep_domain list */ 595 /* First scan through the mydomain->dep_domain list */
593 while (dep_info->nr_dep_entries) { 596 while (dep_info->nr_dep_entries) {
594 r = _dep_scan_table(dev, dep_info, main_volt); 597 r = _dep_scan_table(dev, dep_info, main_volt);
595 /* Store last failed value */ 598 /* Store last failed value */
596 ret = (r) ? r : ret; 599 ret = (r) ? r : ret;
597 dep_info++; 600 dep_info++;
598 } 601 }
599 602
600 return ret; 603 return ret;
601 } 604 }
602 605
603 /** 606 /**
604 * _dep_scale_domains() - Cause a scale of all dependent domains 607 * _dep_scale_domains() - Cause a scale of all dependent domains
605 * @req_dev: device requesting the scale 608 * @req_dev: device requesting the scale
606 * @req_vdd: vdd_info corresponding to the requesting device. 609 * @req_vdd: vdd_info corresponding to the requesting device.
607 * 610 *
608 * This walks through every dependent domain and triggers a scale 611 * This walks through every dependent domain and triggers a scale
609 * It is assumed that the corresponding scale handling for the 612 * It is assumed that the corresponding scale handling for the
610 * domain translates this to freq and voltage scale operations as 613 * domain translates this to freq and voltage scale operations as
611 * needed. 614 * needed.
612 * 615 *
613 * Note: This is uses _dvfs_scale and one should be careful not to 616 * Note: This is uses _dvfs_scale and one should be careful not to
614 * create a circular depedency (e.g. vdd_mpu->vdd_core->vdd->mpu) 617 * create a circular depedency (e.g. vdd_mpu->vdd_core->vdd->mpu)
615 * which can create deadlocks. No protection is provided to prevent 618 * which can create deadlocks. No protection is provided to prevent
616 * this condition and a tree organization is assumed. 619 * this condition and a tree organization is assumed.
617 * 620 *
618 * Returns 0 if all went fine. 621 * Returns 0 if all went fine.
619 */ 622 */
620 static int _dep_scale_domains(struct device *req_dev, 623 static int _dep_scale_domains(struct device *req_dev,
621 struct omap_vdd_info *req_vdd) 624 struct omap_vdd_info *req_vdd)
622 { 625 {
623 struct omap_vdd_dep_info *dep_info = req_vdd->dep_vdd_info; 626 struct omap_vdd_dep_info *dep_info = req_vdd->dep_vdd_info;
624 int ret = 0, r; 627 int ret = 0, r;
625 628
626 if (!dep_info) { 629 if (!dep_info) {
627 dev_dbg(req_dev, "%s: No dependent VDD\n", __func__); 630 dev_dbg(req_dev, "%s: No dependent VDD\n", __func__);
628 return 0; 631 return 0;
629 } 632 }
630 633
631 /* First scan through the mydomain->dep_domain list */ 634 /* First scan through the mydomain->dep_domain list */
632 while (dep_info->nr_dep_entries) { 635 while (dep_info->nr_dep_entries) {
633 struct voltagedomain *tvoltdm = dep_info->_dep_voltdm; 636 struct voltagedomain *tvoltdm = dep_info->_dep_voltdm;
634 637
635 r = 0; 638 r = 0;
636 /* Scale it only if I have a voltdm mapped up for the dep */ 639 /* Scale it only if I have a voltdm mapped up for the dep */
637 if (tvoltdm) { 640 if (tvoltdm) {
638 struct omap_vdd_dvfs_info *tdvfs_info; 641 struct omap_vdd_dvfs_info *tdvfs_info;
639 struct device *target_dev; 642 struct device *target_dev;
640 tdvfs_info = _voltdm_to_dvfs_info(tvoltdm); 643 tdvfs_info = _voltdm_to_dvfs_info(tvoltdm);
641 if (!tdvfs_info) { 644 if (!tdvfs_info) {
642 dev_warn(req_dev, "%s: no dvfs_info\n", 645 dev_warn(req_dev, "%s: no dvfs_info\n",
643 __func__); 646 __func__);
644 goto next; 647 goto next;
645 } 648 }
646 target_dev = _dvfs_info_to_dev(tdvfs_info); 649 target_dev = _dvfs_info_to_dev(tdvfs_info);
647 if (!target_dev) { 650 if (!target_dev) {
648 dev_warn(req_dev, "%s: no target_dev\n", 651 dev_warn(req_dev, "%s: no target_dev\n",
649 __func__); 652 __func__);
650 goto next; 653 goto next;
651 } 654 }
652 r = _dvfs_scale(req_dev, target_dev, tdvfs_info); 655 r = _dvfs_scale(req_dev, target_dev, tdvfs_info);
653 next: 656 next:
654 if (r) 657 if (r)
655 dev_err(req_dev, "%s: dvfs_scale to %s =%d\n", 658 dev_err(req_dev, "%s: dvfs_scale to %s =%d\n",
656 __func__, dev_name(target_dev), r); 659 __func__, dev_name(target_dev), r);
657 } 660 }
658 /* Store last failed value */ 661 /* Store last failed value */
659 ret = (r) ? r : ret; 662 ret = (r) ? r : ret;
660 dep_info++; 663 dep_info++;
661 } 664 }
662 665
663 return ret; 666 return ret;
664 } 667 }
665 668
666 /** 669 /**
667 * _dvfs_scale() : Scale the devices associated with a voltage domain 670 * _dvfs_scale() : Scale the devices associated with a voltage domain
668 * @req_dev: Device requesting the scale 671 * @req_dev: Device requesting the scale
669 * @target_dev: Device requesting to be scaled 672 * @target_dev: Device requesting to be scaled
670 * @tdvfs_info: omap_vdd_dvfs_info pointer for the target domain 673 * @tdvfs_info: omap_vdd_dvfs_info pointer for the target domain
671 * 674 *
672 * This runs through the list of devices associated with the 675 * This runs through the list of devices associated with the
673 * voltage domain and scales the device rates to the one requested 676 * voltage domain and scales the device rates to the one requested
674 * by the user or those corresponding to the new voltage of the 677 * by the user or those corresponding to the new voltage of the
675 * voltage domain. Target voltage is the highest voltage in the vdd_user_list. 678 * voltage domain. Target voltage is the highest voltage in the vdd_user_list.
676 * 679 *
677 * Returns 0 on success else the error value. 680 * Returns 0 on success else the error value.
678 */ 681 */
679 static int _dvfs_scale(struct device *req_dev, struct device *target_dev, 682 static int _dvfs_scale(struct device *req_dev, struct device *target_dev,
680 struct omap_vdd_dvfs_info *tdvfs_info) 683 struct omap_vdd_dvfs_info *tdvfs_info)
681 { 684 {
682 unsigned long curr_volt, new_volt; 685 unsigned long curr_volt, new_volt;
683 int volt_scale_dir = DVFS_VOLT_SCALE_DOWN; 686 int volt_scale_dir = DVFS_VOLT_SCALE_DOWN;
684 struct omap_vdd_dev_list *temp_dev; 687 struct omap_vdd_dev_list *temp_dev;
685 struct plist_node *node; 688 struct plist_node *node;
686 int ret = 0; 689 int ret = 0;
687 struct voltagedomain *voltdm; 690 struct voltagedomain *voltdm;
688 struct omap_vdd_info *vdd; 691 struct omap_vdd_info *vdd;
689 692
690 voltdm = tdvfs_info->voltdm; 693 voltdm = tdvfs_info->voltdm;
691 if (IS_ERR_OR_NULL(voltdm)) { 694 if (IS_ERR_OR_NULL(voltdm)) {
692 dev_err(target_dev, "%s: bad voltdm\n", __func__); 695 dev_err(target_dev, "%s: bad voltdm\n", __func__);
693 return -EINVAL; 696 return -EINVAL;
694 } 697 }
695 vdd = voltdm->vdd; 698 vdd = voltdm->vdd;
696 699
700 /* Mark that we are scaling for this device */
701 tdvfs_info->is_scaling = true;
702 /* let the other CPU know as well */
703 smp_wmb();
704
697 /* Find the highest voltage being requested */ 705 /* Find the highest voltage being requested */
698 node = plist_last(&tdvfs_info->vdd_user_list); 706 node = plist_last(&tdvfs_info->vdd_user_list);
699 new_volt = node->prio; 707 new_volt = node->prio;
700 708
701 curr_volt = voltdm_get_voltage(voltdm); 709 curr_volt = voltdm_get_voltage(voltdm);
702 710
703 /* Disable smartreflex module across voltage and frequency scaling */ 711 /* Disable smartreflex module across voltage and frequency scaling */
704 omap_sr_disable(voltdm); 712 omap_sr_disable(voltdm);
705 713
706 if (curr_volt == new_volt) { 714 if (curr_volt == new_volt) {
707 volt_scale_dir = DVFS_VOLT_SCALE_NONE; 715 volt_scale_dir = DVFS_VOLT_SCALE_NONE;
708 } else if (curr_volt < new_volt) { 716 } else if (curr_volt < new_volt) {
709 ret = voltdm_scale(voltdm, new_volt); 717 ret = voltdm_scale(voltdm, new_volt);
710 if (ret) { 718 if (ret) {
711 dev_err(target_dev, 719 dev_err(target_dev,
712 "%s: Unable to scale the %s to %ld volt\n", 720 "%s: Unable to scale the %s to %ld volt\n",
713 __func__, voltdm->name, new_volt); 721 __func__, voltdm->name, new_volt);
714 goto out; 722 goto out;
715 } 723 }
716 volt_scale_dir = DVFS_VOLT_SCALE_UP; 724 volt_scale_dir = DVFS_VOLT_SCALE_UP;
717 } 725 }
718 726
719 /* if we fail scale for dependent domains, go back to prev state */ 727 /* if we fail scale for dependent domains, go back to prev state */
720 ret = _dep_scan_domains(target_dev, vdd, new_volt); 728 ret = _dep_scan_domains(target_dev, vdd, new_volt);
721 if (ret) { 729 if (ret) {
722 dev_err(target_dev, 730 dev_err(target_dev,
723 "%s: Error in scan domains for vdd_%s\n", 731 "%s: Error in scan domains for vdd_%s\n",
724 __func__, voltdm->name); 732 __func__, voltdm->name);
725 goto fail; 733 goto fail;
726 } 734 }
727 735
728 /* unless we are moving down, scale dependents before we shift freq */ 736 /* unless we are moving down, scale dependents before we shift freq */
729 if (!(DVFS_VOLT_SCALE_DOWN == volt_scale_dir)) { 737 if (!(DVFS_VOLT_SCALE_DOWN == volt_scale_dir)) {
730 ret = _dep_scale_domains(target_dev, vdd); 738 ret = _dep_scale_domains(target_dev, vdd);
731 if (ret) { 739 if (ret) {
732 dev_err(target_dev, 740 dev_err(target_dev,
733 "%s: Error(%d)scale dependent with %ld volt\n", 741 "%s: Error(%d)scale dependent with %ld volt\n",
734 __func__, ret, new_volt); 742 __func__, ret, new_volt);
735 goto fail; 743 goto fail;
736 } 744 }
737 } 745 }
738 746
739 /* Move all devices in list to the required frequencies */ 747 /* Move all devices in list to the required frequencies */
740 list_for_each_entry(temp_dev, &tdvfs_info->dev_list, node) { 748 list_for_each_entry(temp_dev, &tdvfs_info->dev_list, node) {
741 struct device *dev; 749 struct device *dev;
742 struct opp *opp; 750 struct opp *opp;
743 unsigned long freq = 0; 751 unsigned long freq = 0;
744 int r; 752 int r;
745 753
746 dev = temp_dev->dev; 754 dev = temp_dev->dev;
747 if (!plist_head_empty(&temp_dev->freq_user_list)) { 755 if (!plist_head_empty(&temp_dev->freq_user_list)) {
748 node = plist_last(&temp_dev->freq_user_list); 756 node = plist_last(&temp_dev->freq_user_list);
749 freq = node->prio; 757 freq = node->prio;
750 } else { 758 } else {
751 /* dep domain? we'd probably have a voltage request */ 759 /* dep domain? we'd probably have a voltage request */
752 rcu_read_lock(); 760 rcu_read_lock();
753 opp = _volt_to_opp(dev, new_volt); 761 opp = _volt_to_opp(dev, new_volt);
754 if (!IS_ERR(opp)) 762 if (!IS_ERR(opp))
755 freq = opp_get_freq(opp); 763 freq = opp_get_freq(opp);
756 rcu_read_unlock(); 764 rcu_read_unlock();
757 if (!freq) 765 if (!freq)
758 continue; 766 continue;
759 } 767 }
760 768
761 if (freq == clk_get_rate(temp_dev->clk)) { 769 if (freq == clk_get_rate(temp_dev->clk)) {
762 dev_dbg(dev, "%s: Already at the requested" 770 dev_dbg(dev, "%s: Already at the requested"
763 "rate %ld\n", __func__, freq); 771 "rate %ld\n", __func__, freq);
764 continue; 772 continue;
765 } 773 }
766 774
767 r = clk_set_rate(temp_dev->clk, freq); 775 r = clk_set_rate(temp_dev->clk, freq);
768 if (r < 0) { 776 if (r < 0) {
769 dev_err(dev, "%s: clk set rate frq=%ld failed(%d)\n", 777 dev_err(dev, "%s: clk set rate frq=%ld failed(%d)\n",
770 __func__, freq, r); 778 __func__, freq, r);
771 ret = r; 779 ret = r;
772 } 780 }
773 } 781 }
774 782
775 if (ret) 783 if (ret)
776 goto fail; 784 goto fail;
777 785
778 if (DVFS_VOLT_SCALE_DOWN == volt_scale_dir) { 786 if (DVFS_VOLT_SCALE_DOWN == volt_scale_dir) {
779 voltdm_scale(voltdm, new_volt); 787 voltdm_scale(voltdm, new_volt);
780 _dep_scale_domains(target_dev, vdd); 788 _dep_scale_domains(target_dev, vdd);
781 } 789 }
782 790
783 /* All clear.. go out gracefully */ 791 /* All clear.. go out gracefully */
784 goto out; 792 goto out;
785 793
786 fail: 794 fail:
787 pr_warning("%s: domain%s: No clean recovery available! could be bad!\n", 795 pr_warning("%s: domain%s: No clean recovery available! could be bad!\n",
788 __func__, voltdm->name); 796 __func__, voltdm->name);
789 out: 797 out:
790 /* Re-enable Smartreflex module */ 798 /* Re-enable Smartreflex module */
791 omap_sr_enable(voltdm); 799 omap_sr_enable(voltdm);
792 800
801 /* Mark done */
802 tdvfs_info->is_scaling = false;
803 /* let the other CPU know as well */
804 smp_wmb();
805
793 return ret; 806 return ret;
794 } 807 }
795 808
796 /* Public functions */ 809 /* Public functions */
797 810
798 /** 811 /**
799 * omap_device_scale() - Set a new rate at which the device is to operate 812 * omap_device_scale() - Set a new rate at which the device is to operate
800 * @req_dev: pointer to the device requesting the scaling. 813 * @req_dev: pointer to the device requesting the scaling.
801 * @target_dev: pointer to the device that is to be scaled 814 * @target_dev: pointer to the device that is to be scaled
802 * @rate: the rnew rate for the device. 815 * @rate: the rnew rate for the device.
803 * 816 *
804 * This API gets the device opp table associated with this device and 817 * This API gets the device opp table associated with this device and
805 * tries putting the device to the requested rate and the voltage domain 818 * tries putting the device to the requested rate and the voltage domain
806 * associated with the device to the voltage corresponding to the 819 * associated with the device to the voltage corresponding to the
807 * requested rate. Since multiple devices can be assocciated with a 820 * requested rate. Since multiple devices can be assocciated with a
808 * voltage domain this API finds out the possible voltage the 821 * voltage domain this API finds out the possible voltage the
809 * voltage domain can enter and then decides on the final device 822 * voltage domain can enter and then decides on the final device
810 * rate. 823 * rate.
811 * 824 *
812 * Return 0 on success else the error value 825 * Return 0 on success else the error value
813 */ 826 */
814 int omap_device_scale(struct device *req_dev, struct device *target_dev, 827 int omap_device_scale(struct device *req_dev, struct device *target_dev,
815 unsigned long rate) 828 unsigned long rate)
816 { 829 {
817 struct opp *opp; 830 struct opp *opp;
818 unsigned long volt, freq = rate; 831 unsigned long volt, freq = rate;
819 struct omap_vdd_dvfs_info *tdvfs_info; 832 struct omap_vdd_dvfs_info *tdvfs_info;
820 struct platform_device *pdev; 833 struct platform_device *pdev;
821 int ret = 0; 834 int ret = 0;
822 835
823 pdev = container_of(target_dev, struct platform_device, dev); 836 pdev = container_of(target_dev, struct platform_device, dev);
824 if (IS_ERR_OR_NULL(pdev)) { 837 if (IS_ERR_OR_NULL(pdev)) {
825 pr_err("%s: pdev is null!\n", __func__); 838 pr_err("%s: pdev is null!\n", __func__);
826 return -EINVAL; 839 return -EINVAL;
827 } 840 }
828 841
829 /* Lock me to ensure cross domain scaling is secure */ 842 /* Lock me to ensure cross domain scaling is secure */
830 mutex_lock(&omap_dvfs_lock); 843 mutex_lock(&omap_dvfs_lock);
831 844
832 rcu_read_lock(); 845 rcu_read_lock();
833 opp = opp_find_freq_ceil(target_dev, &freq); 846 opp = opp_find_freq_ceil(target_dev, &freq);
834 if (IS_ERR(opp)) { 847 if (IS_ERR(opp)) {
835 rcu_read_unlock(); 848 rcu_read_unlock();
836 dev_err(target_dev, "%s: Unable to find OPP for freq%ld\n", 849 dev_err(target_dev, "%s: Unable to find OPP for freq%ld\n",
837 __func__, rate); 850 __func__, rate);
838 ret = -ENODEV; 851 ret = -ENODEV;
839 goto out; 852 goto out;
840 } 853 }
841 volt = opp_get_voltage(opp); 854 volt = opp_get_voltage(opp);
842 rcu_read_unlock(); 855 rcu_read_unlock();
843 856
844 tdvfs_info = _dev_to_dvfs_info(target_dev); 857 tdvfs_info = _dev_to_dvfs_info(target_dev);
845 if (IS_ERR_OR_NULL(tdvfs_info)) { 858 if (IS_ERR_OR_NULL(tdvfs_info)) {
846 dev_err(target_dev, "%s: (req=%s) no vdd![f=%ld, v=%ld]\n", 859 dev_err(target_dev, "%s: (req=%s) no vdd![f=%ld, v=%ld]\n",
847 __func__, dev_name(req_dev), freq, volt); 860 __func__, dev_name(req_dev), freq, volt);
848 ret = -ENODEV; 861 ret = -ENODEV;
849 goto out; 862 goto out;
850 } 863 }
851 864
852 ret = _add_freq_request(tdvfs_info, req_dev, target_dev, freq); 865 ret = _add_freq_request(tdvfs_info, req_dev, target_dev, freq);
853 if (ret) { 866 if (ret) {
854 dev_err(target_dev, "%s: freqadd(%s) failed %d[f=%ld, v=%ld]\n", 867 dev_err(target_dev, "%s: freqadd(%s) failed %d[f=%ld, v=%ld]\n",
855 __func__, dev_name(req_dev), ret, freq, volt); 868 __func__, dev_name(req_dev), ret, freq, volt);
856 goto out; 869 goto out;
857 } 870 }
858 871
859 ret = _add_vdd_user(tdvfs_info, req_dev, volt); 872 ret = _add_vdd_user(tdvfs_info, req_dev, volt);
860 if (ret) { 873 if (ret) {
861 dev_err(target_dev, "%s: vddadd(%s) failed %d[f=%ld, v=%ld]\n", 874 dev_err(target_dev, "%s: vddadd(%s) failed %d[f=%ld, v=%ld]\n",
862 __func__, dev_name(req_dev), ret, freq, volt); 875 __func__, dev_name(req_dev), ret, freq, volt);
863 _remove_freq_request(tdvfs_info, req_dev, 876 _remove_freq_request(tdvfs_info, req_dev,
864 target_dev); 877 target_dev);
865 goto out; 878 goto out;
866 } 879 }
867 880
868 /* Do the actual scaling */ 881 /* Do the actual scaling */
869 ret = _dvfs_scale(req_dev, target_dev, tdvfs_info); 882 ret = _dvfs_scale(req_dev, target_dev, tdvfs_info);
870 if (ret) { 883 if (ret) {
871 dev_err(target_dev, "%s: scale by %s failed %d[f=%ld, v=%ld]\n", 884 dev_err(target_dev, "%s: scale by %s failed %d[f=%ld, v=%ld]\n",
872 __func__, dev_name(req_dev), ret, freq, volt); 885 __func__, dev_name(req_dev), ret, freq, volt);
873 _remove_freq_request(tdvfs_info, req_dev, 886 _remove_freq_request(tdvfs_info, req_dev,
874 target_dev); 887 target_dev);
875 _remove_vdd_user(tdvfs_info, target_dev); 888 _remove_vdd_user(tdvfs_info, target_dev);
876 /* Fall through */ 889 /* Fall through */
877 } 890 }
878 /* Fall through */ 891 /* Fall through */
879 out: 892 out:
880 mutex_unlock(&omap_dvfs_lock); 893 mutex_unlock(&omap_dvfs_lock);
881 return ret; 894 return ret;
882 } 895 }
883 EXPORT_SYMBOL(omap_device_scale); 896 EXPORT_SYMBOL(omap_device_scale);
897
898 /**
899 * omap_dvfs_is_scaling() - Tells the caller if the domain is scaling
900 * @voltdm: voltage domain we are interested in
901 *
902 * Returns true if the domain is in the middle of scale operation,
903 * returns false if there is no scale operation is in progress or an
904 * invalid parameter was passed.
905 */
906 bool omap_dvfs_is_scaling(struct voltagedomain *voltdm)
907 {
908 struct omap_vdd_dvfs_info *dvfs_info;
909
910 if (IS_ERR_OR_NULL(voltdm)) {
911 pr_err("%s: bad voltdm\n", __func__);
912 return false;
913 }
914
915 dvfs_info = _voltdm_to_dvfs_info(voltdm);
916 if (IS_ERR_OR_NULL(dvfs_info)) {
917 pr_err("%s: no dvfsinfo for voltdm %s\n",
918 __func__, voltdm->name);
919 return false;
920 }
921
922 return dvfs_info->is_scaling;
923 }
924 EXPORT_SYMBOL(omap_dvfs_is_scaling);
884 925
885 #ifdef CONFIG_PM_DEBUG 926 #ifdef CONFIG_PM_DEBUG
886 static int dvfs_dump_vdd(struct seq_file *sf, void *unused) 927 static int dvfs_dump_vdd(struct seq_file *sf, void *unused)
887 { 928 {
888 int k; 929 int k;
889 struct omap_vdd_dvfs_info *dvfs_info; 930 struct omap_vdd_dvfs_info *dvfs_info;
890 struct omap_vdd_dev_list *tdev; 931 struct omap_vdd_dev_list *tdev;
891 struct omap_dev_user_list *duser; 932 struct omap_dev_user_list *duser;
892 struct omap_vdd_user_list *vuser; 933 struct omap_vdd_user_list *vuser;
893 struct omap_vdd_info *vdd; 934 struct omap_vdd_info *vdd;
894 struct omap_vdd_dep_info *dep_info; 935 struct omap_vdd_dep_info *dep_info;
895 struct voltagedomain *voltdm; 936 struct voltagedomain *voltdm;
896 struct omap_volt_data *volt_data; 937 struct omap_volt_data *volt_data;
897 int anyreq; 938 int anyreq;
898 int anyreq2; 939 int anyreq2;
899 940
900 dvfs_info = (struct omap_vdd_dvfs_info *)sf->private; 941 dvfs_info = (struct omap_vdd_dvfs_info *)sf->private;
901 if (IS_ERR_OR_NULL(dvfs_info)) { 942 if (IS_ERR_OR_NULL(dvfs_info)) {
902 pr_err("%s: NO DVFS?\n", __func__); 943 pr_err("%s: NO DVFS?\n", __func__);
903 return -EINVAL; 944 return -EINVAL;
904 } 945 }
905 946
906 voltdm = dvfs_info->voltdm; 947 voltdm = dvfs_info->voltdm;
907 if (IS_ERR_OR_NULL(voltdm)) { 948 if (IS_ERR_OR_NULL(voltdm)) {
908 pr_err("%s: NO voltdm?\n", __func__); 949 pr_err("%s: NO voltdm?\n", __func__);
909 return -EINVAL; 950 return -EINVAL;
910 } 951 }
911 952
912 vdd = voltdm->vdd; 953 vdd = voltdm->vdd;
913 if (IS_ERR_OR_NULL(vdd)) { 954 if (IS_ERR_OR_NULL(vdd)) {
914 pr_err("%s: NO vdd data?\n", __func__); 955 pr_err("%s: NO vdd data?\n", __func__);
915 return -EINVAL; 956 return -EINVAL;
916 } 957 }
917 958
918 seq_printf(sf, "vdd_%s\n", voltdm->name); 959 seq_printf(sf, "vdd_%s\n", voltdm->name);
919 mutex_lock(&omap_dvfs_lock); 960 mutex_lock(&omap_dvfs_lock);
920 spin_lock(&dvfs_info->user_lock); 961 spin_lock(&dvfs_info->user_lock);
921 962
922 seq_printf(sf, "|- voltage requests\n| |\n"); 963 seq_printf(sf, "|- voltage requests\n| |\n");
923 anyreq = 0; 964 anyreq = 0;
924 plist_for_each_entry(vuser, &dvfs_info->vdd_user_list, node) { 965 plist_for_each_entry(vuser, &dvfs_info->vdd_user_list, node) {
925 seq_printf(sf, "| |-%d: %s:%s\n", 966 seq_printf(sf, "| |-%d: %s:%s\n",
926 vuser->node.prio, 967 vuser->node.prio,
927 dev_driver_string(vuser->dev), dev_name(vuser->dev)); 968 dev_driver_string(vuser->dev), dev_name(vuser->dev));
928 anyreq = 1; 969 anyreq = 1;
929 } 970 }
930 971
931 spin_unlock(&dvfs_info->user_lock); 972 spin_unlock(&dvfs_info->user_lock);
932 973
933 if (!anyreq) 974 if (!anyreq)
934 seq_printf(sf, "| `-none\n"); 975 seq_printf(sf, "| `-none\n");
935 else 976 else
936 seq_printf(sf, "| X\n"); 977 seq_printf(sf, "| X\n");
937 seq_printf(sf, "|\n"); 978 seq_printf(sf, "|\n");
938 979
939 seq_printf(sf, "|- frequency requests\n| |\n"); 980 seq_printf(sf, "|- frequency requests\n| |\n");
940 anyreq2 = 0; 981 anyreq2 = 0;
941 list_for_each_entry(tdev, &dvfs_info->dev_list, node) { 982 list_for_each_entry(tdev, &dvfs_info->dev_list, node) {
942 anyreq = 0; 983 anyreq = 0;
943 seq_printf(sf, "| |- %s:%s\n", 984 seq_printf(sf, "| |- %s:%s\n",
944 dev_driver_string(tdev->dev), dev_name(tdev->dev)); 985 dev_driver_string(tdev->dev), dev_name(tdev->dev));
945 spin_lock(&tdev->user_lock); 986 spin_lock(&tdev->user_lock);
946 plist_for_each_entry(duser, &tdev->freq_user_list, node) { 987 plist_for_each_entry(duser, &tdev->freq_user_list, node) {
947 seq_printf(sf, "| | |-%d: %s:%s\n", 988 seq_printf(sf, "| | |-%d: %s:%s\n",
948 duser->node.prio, 989 duser->node.prio,
949 dev_driver_string(duser->dev), 990 dev_driver_string(duser->dev),
950 dev_name(duser->dev)); 991 dev_name(duser->dev));
951 anyreq = 1; 992 anyreq = 1;
952 } 993 }
953 994
954 spin_unlock(&tdev->user_lock); 995 spin_unlock(&tdev->user_lock);
955 996
956 if (!anyreq) 997 if (!anyreq)
957 seq_printf(sf, "| | `-none\n"); 998 seq_printf(sf, "| | `-none\n");
958 else 999 else
959 seq_printf(sf, "| | X\n"); 1000 seq_printf(sf, "| | X\n");
960 anyreq2 = 1; 1001 anyreq2 = 1;
961 } 1002 }
962 if (!anyreq2) 1003 if (!anyreq2)
963 seq_printf(sf, "| `-none\n"); 1004 seq_printf(sf, "| `-none\n");
964 else 1005 else
965 seq_printf(sf, "| X\n"); 1006 seq_printf(sf, "| X\n");
966 1007
967 volt_data = vdd->volt_data; 1008 volt_data = vdd->volt_data;
968 seq_printf(sf, "|- Supported voltages\n| |\n"); 1009 seq_printf(sf, "|- Supported voltages\n| |\n");
969 anyreq = 0; 1010 anyreq = 0;
970 while (volt_data && volt_data->volt_nominal) { 1011 while (volt_data && volt_data->volt_nominal) {
971 seq_printf(sf, "| |-%d\n", volt_data->volt_nominal); 1012 seq_printf(sf, "| |-%d\n", volt_data->volt_nominal);
972 anyreq = 1; 1013 anyreq = 1;
973 volt_data++; 1014 volt_data++;
974 } 1015 }
975 if (!anyreq) 1016 if (!anyreq)
976 seq_printf(sf, "| `-none\n"); 1017 seq_printf(sf, "| `-none\n");
977 else 1018 else
978 seq_printf(sf, "| X\n"); 1019 seq_printf(sf, "| X\n");
979 1020
980 dep_info = vdd->dep_vdd_info; 1021 dep_info = vdd->dep_vdd_info;
981 seq_printf(sf, "`- voltage dependencies\n |\n"); 1022 seq_printf(sf, "`- voltage dependencies\n |\n");
982 anyreq = 0; 1023 anyreq = 0;
983 while (dep_info && dep_info->nr_dep_entries) { 1024 while (dep_info && dep_info->nr_dep_entries) {
984 struct omap_vdd_dep_volt *dep_table = dep_info->dep_table; 1025 struct omap_vdd_dep_volt *dep_table = dep_info->dep_table;
985 1026
986 seq_printf(sf, " |-on vdd_%s\n", dep_info->name); 1027 seq_printf(sf, " |-on vdd_%s\n", dep_info->name);
987 1028
988 for (k = 0; k < dep_info->nr_dep_entries; k++) { 1029 for (k = 0; k < dep_info->nr_dep_entries; k++) {
989 seq_printf(sf, " | |- %d => %d\n", 1030 seq_printf(sf, " | |- %d => %d\n",
990 dep_table[k].main_vdd_volt, 1031 dep_table[k].main_vdd_volt,
991 dep_table[k].dep_vdd_volt); 1032 dep_table[k].dep_vdd_volt);
992 } 1033 }
993 1034
994 anyreq = 1; 1035 anyreq = 1;
995 dep_info++; 1036 dep_info++;
996 } 1037 }
997 1038
998 if (!anyreq) 1039 if (!anyreq)
999 seq_printf(sf, " `- none\n"); 1040 seq_printf(sf, " `- none\n");
1000 else 1041 else
1001 seq_printf(sf, " X X\n"); 1042 seq_printf(sf, " X X\n");
1002 1043
1003 mutex_unlock(&omap_dvfs_lock); 1044 mutex_unlock(&omap_dvfs_lock);
1004 return 0; 1045 return 0;
1005 } 1046 }
1006 1047
1007 static int dvfs_dbg_open(struct inode *inode, struct file *file) 1048 static int dvfs_dbg_open(struct inode *inode, struct file *file)
1008 { 1049 {
1009 return single_open(file, dvfs_dump_vdd, inode->i_private); 1050 return single_open(file, dvfs_dump_vdd, inode->i_private);
1010 } 1051 }
1011 1052
1012 static struct file_operations debugdvfs_fops = { 1053 static struct file_operations debugdvfs_fops = {
1013 .open = dvfs_dbg_open, 1054 .open = dvfs_dbg_open,
1014 .read = seq_read, 1055 .read = seq_read,
1015 .llseek = seq_lseek, 1056 .llseek = seq_lseek,
1016 .release = single_release, 1057 .release = single_release,
1017 }; 1058 };
1018 1059
1019 static struct dentry __initdata *dvfsdebugfs_dir; 1060 static struct dentry __initdata *dvfsdebugfs_dir;
1020 1061
1021 static void __init dvfs_dbg_init(struct omap_vdd_dvfs_info *dvfs_info) 1062 static void __init dvfs_dbg_init(struct omap_vdd_dvfs_info *dvfs_info)
1022 { 1063 {
1023 struct dentry *ddir; 1064 struct dentry *ddir;
1024 1065
1025 /* create a base dir */ 1066 /* create a base dir */
1026 if (!dvfsdebugfs_dir) 1067 if (!dvfsdebugfs_dir)
1027 dvfsdebugfs_dir = debugfs_create_dir("dvfs", NULL); 1068 dvfsdebugfs_dir = debugfs_create_dir("dvfs", NULL);
1028 if (IS_ERR_OR_NULL(dvfsdebugfs_dir)) { 1069 if (IS_ERR_OR_NULL(dvfsdebugfs_dir)) {
1029 WARN_ONCE("%s: Unable to create base DVFS dir\n", __func__); 1070 WARN_ONCE("%s: Unable to create base DVFS dir\n", __func__);
1030 return; 1071 return;
1031 } 1072 }
1032 1073
1033 if (IS_ERR_OR_NULL(dvfs_info->voltdm)) { 1074 if (IS_ERR_OR_NULL(dvfs_info->voltdm)) {
1034 pr_err("%s: no voltdm\n", __func__); 1075 pr_err("%s: no voltdm\n", __func__);
1035 return; 1076 return;
1036 } 1077 }
1037 1078
1038 ddir = debugfs_create_dir(dvfs_info->voltdm->name, dvfsdebugfs_dir); 1079 ddir = debugfs_create_dir(dvfs_info->voltdm->name, dvfsdebugfs_dir);
1039 if (IS_ERR_OR_NULL(ddir)) { 1080 if (IS_ERR_OR_NULL(ddir)) {
1040 pr_warning("%s: unable to create subdir %s\n", __func__, 1081 pr_warning("%s: unable to create subdir %s\n", __func__,
1041 dvfs_info->voltdm->name); 1082 dvfs_info->voltdm->name);
1042 return; 1083 return;
1043 } 1084 }
1044 1085
1045 debugfs_create_file("info", S_IRUGO, ddir, 1086 debugfs_create_file("info", S_IRUGO, ddir,
1046 (void *)dvfs_info, &debugdvfs_fops); 1087 (void *)dvfs_info, &debugdvfs_fops);
1047 } 1088 }
1048 #else /* CONFIG_PM_DEBUG */ 1089 #else /* CONFIG_PM_DEBUG */
1049 static inline void dvfs_dbg_init(struct omap_vdd_dvfs_info *dvfs_info) 1090 static inline void dvfs_dbg_init(struct omap_vdd_dvfs_info *dvfs_info)
1050 { 1091 {
1051 return; 1092 return;
1052 } 1093 }
1053 #endif /* CONFIG_PM_DEBUG */ 1094 #endif /* CONFIG_PM_DEBUG */
1054 1095
1055 /** 1096 /**
1056 * omap_dvfs_register_device - Add a parent device into dvfs managed list 1097 * omap_dvfs_register_device - Add a parent device into dvfs managed list
1057 * @dev: Device to be added 1098 * @dev: Device to be added
1058 * @voltdm_name: Name of the voltage domain for the device 1099 * @voltdm_name: Name of the voltage domain for the device
1059 * @clk_name: Name of the clock for the device 1100 * @clk_name: Name of the clock for the device
1060 * 1101 *
1061 * This function adds a given device into user_list of corresponding 1102 * This function adds a given device into user_list of corresponding
1062 * vdd's omap_vdd_dvfs_info strucure. This list is traversed to scale 1103 * vdd's omap_vdd_dvfs_info strucure. This list is traversed to scale
1063 * frequencies of all the devices on a given vdd. 1104 * frequencies of all the devices on a given vdd.
1064 * 1105 *
1065 * Returns 0 on success. 1106 * Returns 0 on success.
1066 */ 1107 */
1067 int __init omap_dvfs_register_device(struct device *dev, char *voltdm_name, 1108 int __init omap_dvfs_register_device(struct device *dev, char *voltdm_name,
1068 char *clk_name) 1109 char *clk_name)
1069 { 1110 {
1070 struct omap_vdd_dev_list *temp_dev; 1111 struct omap_vdd_dev_list *temp_dev;
1071 struct omap_vdd_dvfs_info *dvfs_info; 1112 struct omap_vdd_dvfs_info *dvfs_info;
1072 struct clk *clk = NULL; 1113 struct clk *clk = NULL;
1073 struct voltagedomain *voltdm; 1114 struct voltagedomain *voltdm;
1074 int ret = 0; 1115 int ret = 0;
1075 1116
1076 if (!voltdm_name) { 1117 if (!voltdm_name) {
1077 dev_err(dev, "%s: Bad voltdm name!\n", __func__); 1118 dev_err(dev, "%s: Bad voltdm name!\n", __func__);
1078 return -EINVAL; 1119 return -EINVAL;
1079 } 1120 }
1080 if (!clk_name) { 1121 if (!clk_name) {
1081 dev_err(dev, "%s: Bad clk name!\n", __func__); 1122 dev_err(dev, "%s: Bad clk name!\n", __func__);
1082 return -EINVAL; 1123 return -EINVAL;
1083 } 1124 }
1084 1125
1085 /* Lock me to secure structure changes */ 1126 /* Lock me to secure structure changes */
1086 mutex_lock(&omap_dvfs_lock); 1127 mutex_lock(&omap_dvfs_lock);
1087 1128
1088 voltdm = voltdm_lookup(voltdm_name); 1129 voltdm = voltdm_lookup(voltdm_name);
1089 if (!voltdm) { 1130 if (!voltdm) {
1090 dev_warn(dev, "%s: unable to find voltdm %s!\n", 1131 dev_warn(dev, "%s: unable to find voltdm %s!\n",
1091 __func__, voltdm_name); 1132 __func__, voltdm_name);
1092 ret = -EINVAL; 1133 ret = -EINVAL;
1093 goto out; 1134 goto out;
1094 } 1135 }
1095 dvfs_info = _voltdm_to_dvfs_info(voltdm); 1136 dvfs_info = _voltdm_to_dvfs_info(voltdm);
1096 if (!dvfs_info) { 1137 if (!dvfs_info) {
1097 dvfs_info = kzalloc(sizeof(struct omap_vdd_dvfs_info), 1138 dvfs_info = kzalloc(sizeof(struct omap_vdd_dvfs_info),
1098 GFP_KERNEL); 1139 GFP_KERNEL);
1099 if (!dvfs_info) { 1140 if (!dvfs_info) {
1100 dev_warn(dev, "%s: unable to alloc memory!\n", 1141 dev_warn(dev, "%s: unable to alloc memory!\n",
1101 __func__); 1142 __func__);
1102 ret = -ENOMEM; 1143 ret = -ENOMEM;
1103 goto out; 1144 goto out;
1104 } 1145 }
1105 dvfs_info->voltdm = voltdm; 1146 dvfs_info->voltdm = voltdm;
1106 1147
1107 /* Init the plist */ 1148 /* Init the plist */
1108 spin_lock_init(&dvfs_info->user_lock); 1149 spin_lock_init(&dvfs_info->user_lock);
1109 plist_head_init(&dvfs_info->vdd_user_list); 1150 plist_head_init(&dvfs_info->vdd_user_list);
1110 1151
1111 /* Init the device list */ 1152 /* Init the device list */
1112 INIT_LIST_HEAD(&dvfs_info->dev_list); 1153 INIT_LIST_HEAD(&dvfs_info->dev_list);
1113 1154
1114 list_add(&dvfs_info->node, &omap_dvfs_info_list); 1155 list_add(&dvfs_info->node, &omap_dvfs_info_list);
1115 1156
1116 dvfs_dbg_init(dvfs_info); 1157 dvfs_dbg_init(dvfs_info);
1117 } 1158 }
1118 1159
1119 /* If device already added, we dont need to do more.. */ 1160 /* If device already added, we dont need to do more.. */
1120 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { 1161 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) {
1121 if (temp_dev->dev == dev) 1162 if (temp_dev->dev == dev)
1122 goto out; 1163 goto out;
1123 } 1164 }
1124 1165
1125 temp_dev = kzalloc(sizeof(struct omap_vdd_dev_list), GFP_KERNEL); 1166 temp_dev = kzalloc(sizeof(struct omap_vdd_dev_list), GFP_KERNEL);
1126 if (!temp_dev) { 1167 if (!temp_dev) {
1127 dev_err(dev, "%s: Unable to creat a new device for vdd_%s\n", 1168 dev_err(dev, "%s: Unable to creat a new device for vdd_%s\n",
1128 __func__, dvfs_info->voltdm->name); 1169 __func__, dvfs_info->voltdm->name);
1129 ret = -ENOMEM; 1170 ret = -ENOMEM;
1130 goto out; 1171 goto out;
1131 } 1172 }
1132 1173
1133 clk = clk_get(dev, clk_name); 1174 clk = clk_get(dev, clk_name);
1134 if (IS_ERR_OR_NULL(clk)) { 1175 if (IS_ERR_OR_NULL(clk)) {
1135 dev_warn(dev, "%s: Bad clk pointer!\n", __func__); 1176 dev_warn(dev, "%s: Bad clk pointer!\n", __func__);
1136 kfree(temp_dev); 1177 kfree(temp_dev);
1137 ret = -EINVAL; 1178 ret = -EINVAL;
1138 goto out; 1179 goto out;
1139 } 1180 }
1140 1181
1141 /* Initialize priority ordered list */ 1182 /* Initialize priority ordered list */
1142 spin_lock_init(&temp_dev->user_lock); 1183 spin_lock_init(&temp_dev->user_lock);
1143 plist_head_init(&temp_dev->freq_user_list); 1184 plist_head_init(&temp_dev->freq_user_list);
1144 1185
1145 temp_dev->dev = dev; 1186 temp_dev->dev = dev;
1146 temp_dev->clk = clk; 1187 temp_dev->clk = clk;
1147 list_add_tail(&temp_dev->node, &dvfs_info->dev_list); 1188 list_add_tail(&temp_dev->node, &dvfs_info->dev_list);
1148 1189
1149 /* Fall through */ 1190 /* Fall through */
1150 out: 1191 out:
1151 mutex_unlock(&omap_dvfs_lock); 1192 mutex_unlock(&omap_dvfs_lock);
1152 return ret; 1193 return ret;
1153 } 1194 }
1154 1195
arch/arm/plat-omap/include/plat/dvfs.h
1 /* 1 /*
2 * OMAP3/OMAP4 DVFS Management Routines 2 * OMAP3/OMAP4 DVFS Management Routines
3 * 3 *
4 * Author: Vishwanath BS <vishwanath.bs@ti.com> 4 * Author: Vishwanath BS <vishwanath.bs@ti.com>
5 * 5 *
6 * Copyright (C) 2011 Texas Instruments, Inc. 6 * Copyright (C) 2011 Texas Instruments, Inc.
7 * Vishwanath BS <vishwanath.bs@ti.com> 7 * Vishwanath BS <vishwanath.bs@ti.com>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13 13
14 #ifndef __ARCH_ARM_MACH_OMAP2_DVFS_H 14 #ifndef __ARCH_ARM_MACH_OMAP2_DVFS_H
15 #define __ARCH_ARM_MACH_OMAP2_DVFS_H 15 #define __ARCH_ARM_MACH_OMAP2_DVFS_H
16 #include <plat/omap_hwmod.h> 16 #include <plat/omap_hwmod.h>
17 #include <plat/voltage.h> 17 #include <plat/voltage.h>
18 18
19 #ifdef CONFIG_PM 19 #ifdef CONFIG_PM
20 int omap_dvfs_register_device(struct device *dev, char *voltdm_name, 20 int omap_dvfs_register_device(struct device *dev, char *voltdm_name,
21 char *clk_name); 21 char *clk_name);
22 int omap_device_scale(struct device *req_dev, struct device *target_dev, 22 int omap_device_scale(struct device *req_dev, struct device *target_dev,
23 unsigned long rate); 23 unsigned long rate);
24
25 bool omap_dvfs_is_scaling(struct voltagedomain *voltdm);
24 #else 26 #else
25 static inline int omap_dvfs_register_device(struct omap_hwmod *oh, 27 static inline int omap_dvfs_register_device(struct omap_hwmod *oh,
26 struct device *dev) 28 struct device *dev)
27 static inline int omap_dvfs_register_device(struct device *dev, 29 static inline int omap_dvfs_register_device(struct device *dev,
28 char *voltdm_name, char *clk_name) 30 char *voltdm_name, char *clk_name)
29 { 31 {
30 return -EINVAL; 32 return -EINVAL;
31 } 33 }
32 static inline int omap_device_scale(struct device *req_dev, 34 static inline int omap_device_scale(struct device *req_dev,
33 struct device *target_dev, unsigned long rate) 35 struct device *target_dev, unsigned long rate)
34 { 36 {
35 return -EINVAL; 37 return -EINVAL;
38 }
39 static inline bool omap_dvfs_is_scaling(struct voltagedomain *voltdm)
40 {
41 return false;
36 } 42 }
37 #endif 43 #endif
38 #endif 44 #endif
39 45