Commit 0c7242c21ab652451d68830f08d5b86d45ab1135

Authored by Todd Poynor
Committed by Afzal Mohammed
1 parent e3c57087ce
Exists in master

OMAP2+: DVFS: add debugfs support for visualizing

Ability to show the dependency table helps debug some of the quirky
issues associated with dvfs when multiple device requests are present

[nm@ti.com: log beautification, few fixes]
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Todd Poynor <toddpoynor@google.com>
[vaibhav.bedia@ti.com: Pull in for AM33xx]
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>

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