Commit 54d8f4c2980f44963c528ad12fa96462813e3426

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

OMAP2+: Ensure that PM inits are done before allowing DVFS

Ensure that PM initializations are all ready before we proceed.

This allows drivers such as gfx, cpufreq which are ready earlier
than pm to not not attempt to use the scaling infrastructure before
it is ready.

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