Commit 536a4c8bb76e77217216bebd40178fb30ac5422b

Authored by Afzal Mohammed
1 parent 90cdb1c234
Exists in master

arm: omap: am33x: Move header files to plat/

dvfs.h is required by omap cpufreq driver that
lives in drivers folder, so move it to plat/
directory. Also move voltage.h, vc.h & vp.h
similarly to have clean header file inclusions

Signed-off-by: Afzal Mohammed <afzal@ti.com>

Showing 31 changed files with 525 additions and 550 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 <plat/common.h> 20 #include <plat/common.h>
21 #include <plat/omap_device.h> 21 #include <plat/omap_device.h>
22 #include <plat/omap_hwmod.h> 22 #include <plat/omap_hwmod.h>
23 #include <plat/clock.h> 23 #include <plat/clock.h>
24 #include "dvfs.h" 24 #include <plat/dvfs.h>
25 #include "smartreflex.h" 25 #include "smartreflex.h"
26 #include "powerdomain.h" 26 #include "powerdomain.h"
27 27
28 /** 28 /**
29 * DOC: Introduction 29 * DOC: Introduction
30 * ================= 30 * =================
31 * DVFS is a technique that uses the optimal operating frequency and voltage to 31 * DVFS is a technique that uses the optimal operating frequency and voltage to
32 * allow a task to be performed in the required amount of time. 32 * allow a task to be performed in the required amount of time.
33 * OMAP processors have voltage domains whose voltage can be scaled to 33 * OMAP processors have voltage domains whose voltage can be scaled to
34 * various levels depending on which the operating frequencies of certain 34 * various levels depending on which the operating frequencies of certain
35 * devices belonging to the domain will also need to be scaled. This voltage 35 * devices belonging to the domain will also need to be scaled. This voltage
36 * frequency tuple is known as Operating Performance Point (OPP). A device 36 * frequency tuple is known as Operating Performance Point (OPP). A device
37 * can have multiple OPP's. Also a voltage domain could be shared between 37 * can have multiple OPP's. Also a voltage domain could be shared between
38 * multiple devices. Also there could be dependencies between various 38 * multiple devices. Also there could be dependencies between various
39 * voltage domains for maintaining system performance like VDD<X> 39 * voltage domains for maintaining system performance like VDD<X>
40 * should be at voltage v1 when VDD<Y> is at voltage v2. 40 * should be at voltage v1 when VDD<Y> is at voltage v2.
41 * 41 *
42 * The design of this framework takes into account all the above mentioned 42 * The design of this framework takes into account all the above mentioned
43 * points. To summarize the basic design of DVFS framework:- 43 * points. To summarize the basic design of DVFS framework:-
44 * 44 *
45 * 1. Have device opp tables for each device whose operating frequency can be 45 * 1. Have device opp tables for each device whose operating frequency can be
46 * scaled. This is easy now due to the existance of hwmod layer which 46 * scaled. This is easy now due to the existance of hwmod layer which
47 * allow storing of device specific info. The device opp tables contain 47 * allow storing of device specific info. The device opp tables contain
48 * the opp pairs (frequency voltage tuples), the voltage domain pointer 48 * the opp pairs (frequency voltage tuples), the voltage domain pointer
49 * to which the device belongs to, the device specific set_rate and 49 * to which the device belongs to, the device specific set_rate and
50 * get_rate API's which will do the actual scaling of the device frequency 50 * get_rate API's which will do the actual scaling of the device frequency
51 * and retrieve the current device frequency. 51 * and retrieve the current device frequency.
52 * 2. Introduce use counting on a per VDD basis. This is to take care multiple 52 * 2. Introduce use counting on a per VDD basis. This is to take care multiple
53 * requests to scale a VDD. The VDD will be scaled to the maximum of the 53 * requests to scale a VDD. The VDD will be scaled to the maximum of the
54 * voltages requested. 54 * voltages requested.
55 * 3. Keep track of all scalable devices belonging to a particular voltage 55 * 3. Keep track of all scalable devices belonging to a particular voltage
56 * domain the voltage layer. 56 * domain the voltage layer.
57 * 4. Keep track of frequency requests for each of the device. This will enable 57 * 4. Keep track of frequency requests for each of the device. This will enable
58 * to scale individual devices to different frequency (even w/o scaling 58 * to scale individual devices to different frequency (even w/o scaling
59 * voltage aka frequency throttling) 59 * voltage aka frequency throttling)
60 * 5. Generic dvfs API that can be called by anybody to scale a device opp. 60 * 5. Generic dvfs API that can be called by anybody to scale a device opp.
61 * This API takes the device pointer and frequency to which the device 61 * This API takes the device pointer and frequency to which the device
62 * needs to be scaled to. This API then internally finds out the voltage 62 * needs to be scaled to. This API then internally finds out the voltage
63 * domain to which the device belongs to and the voltage to which the voltage 63 * domain to which the device belongs to and the voltage to which the voltage
64 * domain needs to be put to for the device to be scaled to the new frequency 64 * domain needs to be put to for the device to be scaled to the new frequency
65 * from he device opp table. Then this API will add requested frequency into 65 * from he device opp table. Then this API will add requested frequency into
66 * the corresponding target device frequency list and add voltage request to 66 * the corresponding target device frequency list and add voltage request to
67 * the corresponding vdd. Subsequently it calls voltage scale function which 67 * the corresponding vdd. Subsequently it calls voltage scale function which
68 * will find out the highest requested voltage for the given vdd and scales 68 * will find out the highest requested voltage for the given vdd and scales
69 * the voltage to the required one. It also runs through the list of all 69 * the voltage to the required one. It also runs through the list of all
70 * scalable devices belonging to this voltage domain and scale them to the 70 * scalable devices belonging to this voltage domain and scale them to the
71 * appropriate frequencies using the set_rate pointer in the device opp 71 * appropriate frequencies using the set_rate pointer in the device opp
72 * tables. 72 * tables.
73 * 6. Handle inter VDD dependecies. 73 * 6. Handle inter VDD dependecies.
74 * 74 *
75 * 75 *
76 * DOC: The Core DVFS data structure: 76 * DOC: The Core DVFS data structure:
77 * ================================== 77 * ==================================
78 * Structure Name Example Tree 78 * Structure Name Example Tree
79 * --------- 79 * ---------
80 * /|\ +-------------------+ +-------------------+ 80 * /|\ +-------------------+ +-------------------+
81 * | |User2 (dev2, freq2)+---\ |User4 (dev4, freq4)+---\ 81 * | |User2 (dev2, freq2)+---\ |User4 (dev4, freq4)+---\
82 * | +-------------------+ | +-------------------+ | 82 * | +-------------------+ | +-------------------+ |
83 * (struct omap_dev_user_list) | | 83 * (struct omap_dev_user_list) | |
84 * | +-------------------+ | +-------------------+ | 84 * | +-------------------+ | +-------------------+ |
85 * | |User1 (dev1, freq1)+---| |User3 (dev3, freq3)+---| 85 * | |User1 (dev1, freq1)+---| |User3 (dev3, freq3)+---|
86 * \|/ +-------------------+ | +-------------------+ | 86 * \|/ +-------------------+ | +-------------------+ |
87 * --------- | | 87 * --------- | |
88 * /|\ +------------+------+ +---------------+--+ 88 * /|\ +------------+------+ +---------------+--+
89 * | | DEV1 (dev, | | DEV2 (dev) | 89 * | | DEV1 (dev, | | DEV2 (dev) |
90 * (struct omap_vdd_dev_list)|omap_dev_user_list)| |omap_dev_user_list| 90 * (struct omap_vdd_dev_list)|omap_dev_user_list)| |omap_dev_user_list|
91 * | +------------+------+ +--+---------------+ 91 * | +------------+------+ +--+---------------+
92 * \|/ /|\ /-----+-------------+------> others.. 92 * \|/ /|\ /-----+-------------+------> others..
93 * --------- Frequency | 93 * --------- Frequency |
94 * /|\ +--+------------------+ 94 * /|\ +--+------------------+
95 * | | VDD_n | 95 * | | VDD_n |
96 * | | (omap_vdd_dev_list, | 96 * | | (omap_vdd_dev_list, |
97 * (struct omap_vdd_dvfs_info)** | omap_vdd_user_list) | 97 * (struct omap_vdd_dvfs_info)** | omap_vdd_user_list) |
98 * | +--+------------------+ 98 * | +--+------------------+
99 * | | (ROOT NODE: omap_dvfs_info_list) 99 * | | (ROOT NODE: omap_dvfs_info_list)
100 * \|/ | 100 * \|/ |
101 * --------- Voltage \---+-------------+----------> others.. 101 * --------- Voltage \---+-------------+----------> others..
102 * /|\ \|/ +-------+----+ +-----+--------+ 102 * /|\ \|/ +-------+----+ +-----+--------+
103 * | | vdd_user2 | | vdd_user3 | 103 * | | vdd_user2 | | vdd_user3 |
104 * (struct omap_vdd_user_list) | (dev, volt)| | (dev, volt) | 104 * (struct omap_vdd_user_list) | (dev, volt)| | (dev, volt) |
105 * \|/ +------------+ +--------------+ 105 * \|/ +------------+ +--------------+
106 * --------- 106 * ---------
107 * Key: ** -> Root of the tree. 107 * Key: ** -> Root of the tree.
108 * NOTE: we use the priority to store the voltage/frequency 108 * NOTE: we use the priority to store the voltage/frequency
109 * 109 *
110 * For voltage dependency description, see: struct dependency: 110 * For voltage dependency description, see: struct dependency:
111 * voltagedomain -> (description of the voltagedomain) 111 * voltagedomain -> (description of the voltagedomain)
112 * omap_vdd_info -> (vdd information) 112 * omap_vdd_info -> (vdd information)
113 * omap_vdd_dep_info[]-> (stores array of depedency info) 113 * omap_vdd_dep_info[]-> (stores array of depedency info)
114 * omap_vdd_dep_volt[] -> (stores array of maps) 114 * omap_vdd_dep_volt[] -> (stores array of maps)
115 * (main_volt -> dep_volt) (a singular map) 115 * (main_volt -> dep_volt) (a singular map)
116 */ 116 */
117 117
118 /* Macros to give idea about scaling directions */ 118 /* Macros to give idea about scaling directions */
119 #define DVFS_VOLT_SCALE_DOWN 0 119 #define DVFS_VOLT_SCALE_DOWN 0
120 #define DVFS_VOLT_SCALE_NONE 1 120 #define DVFS_VOLT_SCALE_NONE 1
121 #define DVFS_VOLT_SCALE_UP 2 121 #define DVFS_VOLT_SCALE_UP 2
122 122
123 /** 123 /**
124 * struct omap_dev_user_list - Structure maitain userlist per devide 124 * struct omap_dev_user_list - Structure maitain userlist per devide
125 * @dev: The device requesting for a particular frequency 125 * @dev: The device requesting for a particular frequency
126 * @node: The list head entry 126 * @node: The list head entry
127 * 127 *
128 * Using this structure, user list (requesting dev * and frequency) for 128 * Using this structure, user list (requesting dev * and frequency) for
129 * each device is maintained. This is how we can have different devices 129 * each device is maintained. This is how we can have different devices
130 * at different frequencies (to support frequency locking and throttling). 130 * at different frequencies (to support frequency locking and throttling).
131 * Even if one of the devices in a given vdd has locked it's frequency, 131 * Even if one of the devices in a given vdd has locked it's frequency,
132 * other's can still scale their frequency using this list. 132 * other's can still scale their frequency using this list.
133 * If no one has placed a frequency request for a device, then device is 133 * If no one has placed a frequency request for a device, then device is
134 * set to the frequency from it's opp table. 134 * set to the frequency from it's opp table.
135 */ 135 */
136 struct omap_dev_user_list { 136 struct omap_dev_user_list {
137 struct device *dev; 137 struct device *dev;
138 struct plist_node node; 138 struct plist_node node;
139 }; 139 };
140 140
141 /** 141 /**
142 * struct omap_vdd_dev_list - Device list per vdd 142 * struct omap_vdd_dev_list - Device list per vdd
143 * @dev: The device belonging to a particular vdd 143 * @dev: The device belonging to a particular vdd
144 * @node: The list head entry 144 * @node: The list head entry
145 * @freq_user_list: The list of users for vdd device 145 * @freq_user_list: The list of users for vdd device
146 * @clk: frequency control clock for this dev 146 * @clk: frequency control clock for this dev
147 * @user_lock: The lock for plist manipulation 147 * @user_lock: The lock for plist manipulation
148 */ 148 */
149 struct omap_vdd_dev_list { 149 struct omap_vdd_dev_list {
150 struct device *dev; 150 struct device *dev;
151 struct list_head node; 151 struct list_head node;
152 struct plist_head freq_user_list; 152 struct plist_head freq_user_list;
153 struct clk *clk; 153 struct clk *clk;
154 spinlock_t user_lock; /* spinlock for plist */ 154 spinlock_t user_lock; /* spinlock for plist */
155 }; 155 };
156 156
157 /** 157 /**
158 * struct omap_vdd_user_list - The per vdd user list 158 * struct omap_vdd_user_list - The per vdd user list
159 * @dev: The device asking for the vdd to be set at a particular 159 * @dev: The device asking for the vdd to be set at a particular
160 * voltage 160 * voltage
161 * @node: The list head entry 161 * @node: The list head entry
162 */ 162 */
163 struct omap_vdd_user_list { 163 struct omap_vdd_user_list {
164 struct device *dev; 164 struct device *dev;
165 struct plist_node node; 165 struct plist_node node;
166 }; 166 };
167 167
168 /** 168 /**
169 * struct omap_vdd_dvfs_info - The per vdd dvfs info 169 * struct omap_vdd_dvfs_info - The per vdd dvfs info
170 * @node: list node for vdd_dvfs_info list 170 * @node: list node for vdd_dvfs_info list
171 * @user_lock: spinlock for plist operations 171 * @user_lock: spinlock for plist operations
172 * @vdd_user_list: The vdd user list 172 * @vdd_user_list: The vdd user list
173 * @voltdm: Voltage domains for which dvfs info stored 173 * @voltdm: Voltage domains for which dvfs info stored
174 * @dev_list: Device list maintained per domain 174 * @dev_list: Device list maintained per domain
175 * 175 *
176 * This is a fundamental structure used to store all the required 176 * This is a fundamental structure used to store all the required
177 * DVFS related information for a vdd. 177 * DVFS related information for a vdd.
178 */ 178 */
179 struct omap_vdd_dvfs_info { 179 struct omap_vdd_dvfs_info {
180 struct list_head node; 180 struct list_head node;
181 181
182 spinlock_t user_lock; /* spin lock */ 182 spinlock_t user_lock; /* spin lock */
183 struct plist_head vdd_user_list; 183 struct plist_head vdd_user_list;
184 struct voltagedomain *voltdm; 184 struct voltagedomain *voltdm;
185 struct list_head dev_list; 185 struct list_head dev_list;
186 }; 186 };
187 187
188 static LIST_HEAD(omap_dvfs_info_list); 188 static LIST_HEAD(omap_dvfs_info_list);
189 static DEFINE_MUTEX(omap_dvfs_lock); 189 static DEFINE_MUTEX(omap_dvfs_lock);
190 190
191 /* Dvfs scale helper function */ 191 /* Dvfs scale helper function */
192 static int _dvfs_scale(struct device *req_dev, struct device *target_dev, 192 static int _dvfs_scale(struct device *req_dev, struct device *target_dev,
193 struct omap_vdd_dvfs_info *tdvfs_info); 193 struct omap_vdd_dvfs_info *tdvfs_info);
194 194
195 /* Few search functions to traverse and find pointers of interest */ 195 /* Few search functions to traverse and find pointers of interest */
196 196
197 /** 197 /**
198 * _dvfs_info_to_dev() - Locate the parent device associated to dvfs_info 198 * _dvfs_info_to_dev() - Locate the parent device associated to dvfs_info
199 * @dvfs_info: dvfs_info to search for 199 * @dvfs_info: dvfs_info to search for
200 * 200 *
201 * Returns NULL on failure. 201 * Returns NULL on failure.
202 */ 202 */
203 static struct device *_dvfs_info_to_dev(struct omap_vdd_dvfs_info *dvfs_info) 203 static struct device *_dvfs_info_to_dev(struct omap_vdd_dvfs_info *dvfs_info)
204 { 204 {
205 struct omap_vdd_dev_list *tmp_dev; 205 struct omap_vdd_dev_list *tmp_dev;
206 if (IS_ERR_OR_NULL(dvfs_info)) 206 if (IS_ERR_OR_NULL(dvfs_info))
207 return NULL; 207 return NULL;
208 if (list_empty(&dvfs_info->dev_list)) 208 if (list_empty(&dvfs_info->dev_list))
209 return NULL; 209 return NULL;
210 tmp_dev = list_first_entry(&dvfs_info->dev_list, 210 tmp_dev = list_first_entry(&dvfs_info->dev_list,
211 struct omap_vdd_dev_list, node); 211 struct omap_vdd_dev_list, node);
212 return tmp_dev->dev; 212 return tmp_dev->dev;
213 } 213 }
214 214
215 /** 215 /**
216 * _dev_to_dvfs_info() - Locate the dvfs_info for a device 216 * _dev_to_dvfs_info() - Locate the dvfs_info for a device
217 * @dev: dev to search for 217 * @dev: dev to search for
218 * 218 *
219 * Returns NULL on failure. 219 * Returns NULL on failure.
220 */ 220 */
221 static struct omap_vdd_dvfs_info *_dev_to_dvfs_info(struct device *dev) 221 static struct omap_vdd_dvfs_info *_dev_to_dvfs_info(struct device *dev)
222 { 222 {
223 struct omap_vdd_dvfs_info *dvfs_info; 223 struct omap_vdd_dvfs_info *dvfs_info;
224 struct omap_vdd_dev_list *temp_dev; 224 struct omap_vdd_dev_list *temp_dev;
225 225
226 if (IS_ERR_OR_NULL(dev)) 226 if (IS_ERR_OR_NULL(dev))
227 return NULL; 227 return NULL;
228 228
229 list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) { 229 list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) {
230 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { 230 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) {
231 if (temp_dev->dev == dev) 231 if (temp_dev->dev == dev)
232 return dvfs_info; 232 return dvfs_info;
233 } 233 }
234 } 234 }
235 235
236 return NULL; 236 return NULL;
237 } 237 }
238 238
239 /** 239 /**
240 * _voltdm_to_dvfs_info() - Locate a dvfs_info given a voltdm pointer 240 * _voltdm_to_dvfs_info() - Locate a dvfs_info given a voltdm pointer
241 * @voltdm: voltdm to search for 241 * @voltdm: voltdm to search for
242 * 242 *
243 * Returns NULL on failure. 243 * Returns NULL on failure.
244 */ 244 */
245 static 245 static
246 struct omap_vdd_dvfs_info *_voltdm_to_dvfs_info(struct voltagedomain *voltdm) 246 struct omap_vdd_dvfs_info *_voltdm_to_dvfs_info(struct voltagedomain *voltdm)
247 { 247 {
248 struct omap_vdd_dvfs_info *dvfs_info; 248 struct omap_vdd_dvfs_info *dvfs_info;
249 249
250 if (IS_ERR_OR_NULL(voltdm)) 250 if (IS_ERR_OR_NULL(voltdm))
251 return NULL; 251 return NULL;
252 252
253 list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) { 253 list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) {
254 if (dvfs_info->voltdm == voltdm) 254 if (dvfs_info->voltdm == voltdm)
255 return dvfs_info; 255 return dvfs_info;
256 } 256 }
257 257
258 return NULL; 258 return NULL;
259 } 259 }
260 260
261 /** 261 /**
262 * _volt_to_opp() - Find OPP corresponding to a given voltage 262 * _volt_to_opp() - Find OPP corresponding to a given voltage
263 * @dev: device pointer associated with the OPP list 263 * @dev: device pointer associated with the OPP list
264 * @volt: voltage to search for in uV 264 * @volt: voltage to search for in uV
265 * 265 *
266 * Searches for exact match in the OPP list and returns handle to the matching 266 * Searches for exact match in the OPP list and returns handle to the matching
267 * OPP if found, else returns ERR_PTR in case of error and should be handled 267 * OPP if found, else returns ERR_PTR in case of error and should be handled
268 * using IS_ERR. If there are multiple opps with same voltage, it will return 268 * using IS_ERR. If there are multiple opps with same voltage, it will return
269 * the first available entry. Return pointer should be checked against IS_ERR. 269 * the first available entry. Return pointer should be checked against IS_ERR.
270 * 270 *
271 * NOTE: since this uses OPP functions, use under rcu_lock. This function also 271 * NOTE: since this uses OPP functions, use under rcu_lock. This function also
272 * assumes that the cpufreq table and OPP table are in sync - any modifications 272 * assumes that the cpufreq table and OPP table are in sync - any modifications
273 * to either should be synchronized. 273 * to either should be synchronized.
274 */ 274 */
275 static struct opp *_volt_to_opp(struct device *dev, unsigned long volt) 275 static struct opp *_volt_to_opp(struct device *dev, unsigned long volt)
276 { 276 {
277 struct opp *opp = ERR_PTR(-ENODEV); 277 struct opp *opp = ERR_PTR(-ENODEV);
278 unsigned long f = 0; 278 unsigned long f = 0;
279 279
280 do { 280 do {
281 opp = opp_find_freq_ceil(dev, &f); 281 opp = opp_find_freq_ceil(dev, &f);
282 if (IS_ERR(opp)) 282 if (IS_ERR(opp))
283 break; 283 break;
284 if (opp_get_voltage(opp) >= volt) 284 if (opp_get_voltage(opp) >= volt)
285 break; 285 break;
286 f++; 286 f++;
287 } while (1); 287 } while (1);
288 288
289 return opp; 289 return opp;
290 } 290 }
291 291
292 /* rest of the helper functions */ 292 /* rest of the helper functions */
293 /** 293 /**
294 * _add_vdd_user() - Add a voltage request 294 * _add_vdd_user() - Add a voltage request
295 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd 295 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd
296 * @dev: device making the request 296 * @dev: device making the request
297 * @volt: requested voltage in uV 297 * @volt: requested voltage in uV
298 * 298 *
299 * Adds the given device's voltage request into corresponding 299 * Adds the given device's voltage request into corresponding
300 * vdd's omap_vdd_dvfs_info user list (plist). This list is used 300 * vdd's omap_vdd_dvfs_info user list (plist). This list is used
301 * to find the maximum voltage request for a given vdd. 301 * to find the maximum voltage request for a given vdd.
302 * 302 *
303 * Returns 0 on success. 303 * Returns 0 on success.
304 */ 304 */
305 static int _add_vdd_user(struct omap_vdd_dvfs_info *dvfs_info, 305 static int _add_vdd_user(struct omap_vdd_dvfs_info *dvfs_info,
306 struct device *dev, unsigned long volt) 306 struct device *dev, unsigned long volt)
307 { 307 {
308 struct omap_vdd_user_list *user = NULL, *temp_user; 308 struct omap_vdd_user_list *user = NULL, *temp_user;
309 309
310 if (!dvfs_info || IS_ERR(dvfs_info)) { 310 if (!dvfs_info || IS_ERR(dvfs_info)) {
311 dev_warn(dev, "%s: VDD specified does not exist!\n", __func__); 311 dev_warn(dev, "%s: VDD specified does not exist!\n", __func__);
312 return -EINVAL; 312 return -EINVAL;
313 } 313 }
314 314
315 spin_lock(&dvfs_info->user_lock); 315 spin_lock(&dvfs_info->user_lock);
316 plist_for_each_entry(temp_user, &dvfs_info->vdd_user_list, node) { 316 plist_for_each_entry(temp_user, &dvfs_info->vdd_user_list, node) {
317 if (temp_user->dev == dev) { 317 if (temp_user->dev == dev) {
318 user = temp_user; 318 user = temp_user;
319 break; 319 break;
320 } 320 }
321 } 321 }
322 322
323 if (!user) { 323 if (!user) {
324 user = kzalloc(sizeof(struct omap_vdd_user_list), GFP_ATOMIC); 324 user = kzalloc(sizeof(struct omap_vdd_user_list), GFP_ATOMIC);
325 if (!user) { 325 if (!user) {
326 dev_err(dev, 326 dev_err(dev,
327 "%s: Unable to creat a new user for vdd_%s\n", 327 "%s: Unable to creat a new user for vdd_%s\n",
328 __func__, dvfs_info->voltdm->name); 328 __func__, dvfs_info->voltdm->name);
329 spin_unlock(&dvfs_info->user_lock); 329 spin_unlock(&dvfs_info->user_lock);
330 return -ENOMEM; 330 return -ENOMEM;
331 } 331 }
332 user->dev = dev; 332 user->dev = dev;
333 } else { 333 } else {
334 plist_del(&user->node, &dvfs_info->vdd_user_list); 334 plist_del(&user->node, &dvfs_info->vdd_user_list);
335 } 335 }
336 336
337 plist_node_init(&user->node, volt); 337 plist_node_init(&user->node, volt);
338 plist_add(&user->node, &dvfs_info->vdd_user_list); 338 plist_add(&user->node, &dvfs_info->vdd_user_list);
339 339
340 spin_unlock(&dvfs_info->user_lock); 340 spin_unlock(&dvfs_info->user_lock);
341 return 0; 341 return 0;
342 } 342 }
343 343
344 /** 344 /**
345 * _remove_vdd_user() - Remove a voltage request 345 * _remove_vdd_user() - Remove a voltage request
346 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd 346 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd
347 * @dev: device making the request 347 * @dev: device making the request
348 * 348 *
349 * Removes the given device's voltage request from corresponding 349 * Removes the given device's voltage request from corresponding
350 * vdd's omap_vdd_dvfs_info user list (plist). 350 * vdd's omap_vdd_dvfs_info user list (plist).
351 * 351 *
352 * Returns 0 on success. 352 * Returns 0 on success.
353 */ 353 */
354 static int _remove_vdd_user(struct omap_vdd_dvfs_info *dvfs_info, 354 static int _remove_vdd_user(struct omap_vdd_dvfs_info *dvfs_info,
355 struct device *dev) 355 struct device *dev)
356 { 356 {
357 struct omap_vdd_user_list *user = NULL, *temp_user; 357 struct omap_vdd_user_list *user = NULL, *temp_user;
358 int ret = 0; 358 int ret = 0;
359 359
360 if (!dvfs_info || IS_ERR(dvfs_info)) { 360 if (!dvfs_info || IS_ERR(dvfs_info)) {
361 dev_err(dev, "%s: VDD specified does not exist!\n", __func__); 361 dev_err(dev, "%s: VDD specified does not exist!\n", __func__);
362 return -EINVAL; 362 return -EINVAL;
363 } 363 }
364 364
365 spin_lock(&dvfs_info->user_lock); 365 spin_lock(&dvfs_info->user_lock);
366 plist_for_each_entry(temp_user, &dvfs_info->vdd_user_list, node) { 366 plist_for_each_entry(temp_user, &dvfs_info->vdd_user_list, node) {
367 if (temp_user->dev == dev) { 367 if (temp_user->dev == dev) {
368 user = temp_user; 368 user = temp_user;
369 break; 369 break;
370 } 370 }
371 } 371 }
372 372
373 if (user) 373 if (user)
374 plist_del(&user->node, &dvfs_info->vdd_user_list); 374 plist_del(&user->node, &dvfs_info->vdd_user_list);
375 else { 375 else {
376 dev_err(dev, "%s: Unable to find the user for vdd_%s\n", 376 dev_err(dev, "%s: Unable to find the user for vdd_%s\n",
377 __func__, dvfs_info->voltdm->name); 377 __func__, dvfs_info->voltdm->name);
378 ret = -ENOENT; 378 ret = -ENOENT;
379 } 379 }
380 380
381 spin_unlock(&dvfs_info->user_lock); 381 spin_unlock(&dvfs_info->user_lock);
382 kfree(user); 382 kfree(user);
383 383
384 return ret; 384 return ret;
385 } 385 }
386 386
387 /** 387 /**
388 * _add_freq_request() - Add a requested device frequency 388 * _add_freq_request() - Add a requested device frequency
389 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd 389 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd
390 * @req_dev: device making the request 390 * @req_dev: device making the request
391 * @target_dev: target device for which frequency request is being made 391 * @target_dev: target device for which frequency request is being made
392 * @freq: target device frequency 392 * @freq: target device frequency
393 * 393 *
394 * This adds a requested frequency into target device's frequency list. 394 * This adds a requested frequency into target device's frequency list.
395 * 395 *
396 * Returns 0 on success. 396 * Returns 0 on success.
397 */ 397 */
398 static int _add_freq_request(struct omap_vdd_dvfs_info *dvfs_info, 398 static int _add_freq_request(struct omap_vdd_dvfs_info *dvfs_info,
399 struct device *req_dev, struct device *target_dev, unsigned long freq) 399 struct device *req_dev, struct device *target_dev, unsigned long freq)
400 { 400 {
401 struct omap_dev_user_list *dev_user = NULL, *tmp_user; 401 struct omap_dev_user_list *dev_user = NULL, *tmp_user;
402 struct omap_vdd_dev_list *temp_dev; 402 struct omap_vdd_dev_list *temp_dev;
403 403
404 if (!dvfs_info || IS_ERR(dvfs_info)) { 404 if (!dvfs_info || IS_ERR(dvfs_info)) {
405 dev_warn(target_dev, "%s: VDD specified does not exist!\n", 405 dev_warn(target_dev, "%s: VDD specified does not exist!\n",
406 __func__); 406 __func__);
407 return -EINVAL; 407 return -EINVAL;
408 } 408 }
409 409
410 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { 410 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) {
411 if (temp_dev->dev == target_dev) 411 if (temp_dev->dev == target_dev)
412 break; 412 break;
413 } 413 }
414 414
415 if (temp_dev->dev != target_dev) { 415 if (temp_dev->dev != target_dev) {
416 dev_warn(target_dev, "%s: target_dev does not exist!\n", 416 dev_warn(target_dev, "%s: target_dev does not exist!\n",
417 __func__); 417 __func__);
418 return -EINVAL; 418 return -EINVAL;
419 } 419 }
420 420
421 spin_lock(&temp_dev->user_lock); 421 spin_lock(&temp_dev->user_lock);
422 plist_for_each_entry(tmp_user, &temp_dev->freq_user_list, node) { 422 plist_for_each_entry(tmp_user, &temp_dev->freq_user_list, node) {
423 if (tmp_user->dev == req_dev) { 423 if (tmp_user->dev == req_dev) {
424 dev_user = tmp_user; 424 dev_user = tmp_user;
425 break; 425 break;
426 } 426 }
427 } 427 }
428 428
429 if (!dev_user) { 429 if (!dev_user) {
430 dev_user = kzalloc(sizeof(struct omap_dev_user_list), 430 dev_user = kzalloc(sizeof(struct omap_dev_user_list),
431 GFP_ATOMIC); 431 GFP_ATOMIC);
432 if (!dev_user) { 432 if (!dev_user) {
433 dev_err(target_dev, 433 dev_err(target_dev,
434 "%s: Unable to creat a new user for vdd_%s\n", 434 "%s: Unable to creat a new user for vdd_%s\n",
435 __func__, dvfs_info->voltdm->name); 435 __func__, dvfs_info->voltdm->name);
436 spin_unlock(&temp_dev->user_lock); 436 spin_unlock(&temp_dev->user_lock);
437 return -ENOMEM; 437 return -ENOMEM;
438 } 438 }
439 dev_user->dev = req_dev; 439 dev_user->dev = req_dev;
440 } else { 440 } else {
441 plist_del(&dev_user->node, &temp_dev->freq_user_list); 441 plist_del(&dev_user->node, &temp_dev->freq_user_list);
442 } 442 }
443 443
444 plist_node_init(&dev_user->node, freq); 444 plist_node_init(&dev_user->node, freq);
445 plist_add(&dev_user->node, &temp_dev->freq_user_list); 445 plist_add(&dev_user->node, &temp_dev->freq_user_list);
446 spin_unlock(&temp_dev->user_lock); 446 spin_unlock(&temp_dev->user_lock);
447 return 0; 447 return 0;
448 } 448 }
449 449
450 /** 450 /**
451 * _remove_freq_request() - Remove the requested device frequency 451 * _remove_freq_request() - Remove the requested device frequency
452 * 452 *
453 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd 453 * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd
454 * @req_dev: device removing the request 454 * @req_dev: device removing the request
455 * @target_dev: target device from which frequency request is being removed 455 * @target_dev: target device from which frequency request is being removed
456 * 456 *
457 * This removes a requested frequency from target device's frequency list. 457 * This removes a requested frequency from target device's frequency list.
458 * 458 *
459 * Returns 0 on success. 459 * Returns 0 on success.
460 */ 460 */
461 static int _remove_freq_request(struct omap_vdd_dvfs_info *dvfs_info, 461 static int _remove_freq_request(struct omap_vdd_dvfs_info *dvfs_info,
462 struct device *req_dev, struct device *target_dev) 462 struct device *req_dev, struct device *target_dev)
463 { 463 {
464 struct omap_dev_user_list *dev_user = NULL, *tmp_user; 464 struct omap_dev_user_list *dev_user = NULL, *tmp_user;
465 int ret = 0; 465 int ret = 0;
466 struct omap_vdd_dev_list *temp_dev; 466 struct omap_vdd_dev_list *temp_dev;
467 467
468 if (!dvfs_info || IS_ERR(dvfs_info)) { 468 if (!dvfs_info || IS_ERR(dvfs_info)) {
469 dev_warn(target_dev, "%s: VDD specified does not exist!\n", 469 dev_warn(target_dev, "%s: VDD specified does not exist!\n",
470 __func__); 470 __func__);
471 return -EINVAL; 471 return -EINVAL;
472 } 472 }
473 473
474 474
475 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { 475 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) {
476 if (temp_dev->dev == target_dev) 476 if (temp_dev->dev == target_dev)
477 break; 477 break;
478 } 478 }
479 479
480 if (temp_dev->dev != target_dev) { 480 if (temp_dev->dev != target_dev) {
481 dev_warn(target_dev, "%s: target_dev does not exist!\n", 481 dev_warn(target_dev, "%s: target_dev does not exist!\n",
482 __func__); 482 __func__);
483 return -EINVAL; 483 return -EINVAL;
484 } 484 }
485 485
486 spin_lock(&temp_dev->user_lock); 486 spin_lock(&temp_dev->user_lock);
487 plist_for_each_entry(tmp_user, &temp_dev->freq_user_list, node) { 487 plist_for_each_entry(tmp_user, &temp_dev->freq_user_list, node) {
488 if (tmp_user->dev == req_dev) { 488 if (tmp_user->dev == req_dev) {
489 dev_user = tmp_user; 489 dev_user = tmp_user;
490 break; 490 break;
491 } 491 }
492 } 492 }
493 493
494 if (dev_user) { 494 if (dev_user) {
495 plist_del(&dev_user->node, &temp_dev->freq_user_list); 495 plist_del(&dev_user->node, &temp_dev->freq_user_list);
496 } else { 496 } else {
497 dev_err(target_dev, 497 dev_err(target_dev,
498 "%s: Unable to remove the user for vdd_%s\n", 498 "%s: Unable to remove the user for vdd_%s\n",
499 __func__, dvfs_info->voltdm->name); 499 __func__, dvfs_info->voltdm->name);
500 ret = -EINVAL; 500 ret = -EINVAL;
501 } 501 }
502 502
503 spin_unlock(&temp_dev->user_lock); 503 spin_unlock(&temp_dev->user_lock);
504 kfree(dev_user); 504 kfree(dev_user);
505 505
506 return ret; 506 return ret;
507 } 507 }
508 508
509 /** 509 /**
510 * _dep_scan_table() - Scan a dependency table and mark for scaling 510 * _dep_scan_table() - Scan a dependency table and mark for scaling
511 * @dev: device requesting the dependency scan (req_dev) 511 * @dev: device requesting the dependency scan (req_dev)
512 * @dep_info: dependency information (contains the table) 512 * @dep_info: dependency information (contains the table)
513 * @main_volt: voltage dependency to search for 513 * @main_volt: voltage dependency to search for
514 * 514 *
515 * This runs down the table provided to find the match for main_volt 515 * This runs down the table provided to find the match for main_volt
516 * provided and sets up a scale request for the dependent domain 516 * provided and sets up a scale request for the dependent domain
517 * for the dependent voltage. 517 * for the dependent voltage.
518 * 518 *
519 * Returns 0 if all went well. 519 * Returns 0 if all went well.
520 */ 520 */
521 static int _dep_scan_table(struct device *dev, 521 static int _dep_scan_table(struct device *dev,
522 struct omap_vdd_dep_info *dep_info, unsigned long main_volt) 522 struct omap_vdd_dep_info *dep_info, unsigned long main_volt)
523 { 523 {
524 struct omap_vdd_dep_volt *dep_table = dep_info->dep_table; 524 struct omap_vdd_dep_volt *dep_table = dep_info->dep_table;
525 int i; 525 int i;
526 unsigned long dep_volt = 0; 526 unsigned long dep_volt = 0;
527 527
528 if (!dep_table) { 528 if (!dep_table) {
529 dev_err(dev, "%s: deptable not present for vdd%s\n", 529 dev_err(dev, "%s: deptable not present for vdd%s\n",
530 __func__, dep_info->name); 530 __func__, dep_info->name);
531 return -EINVAL; 531 return -EINVAL;
532 } 532 }
533 533
534 /* Now scan through the the dep table for a match */ 534 /* Now scan through the the dep table for a match */
535 for (i = 0; i < dep_info->nr_dep_entries; i++) { 535 for (i = 0; i < dep_info->nr_dep_entries; i++) {
536 if (dep_table[i].main_vdd_volt == main_volt) { 536 if (dep_table[i].main_vdd_volt == main_volt) {
537 dep_volt = dep_table[i].dep_vdd_volt; 537 dep_volt = dep_table[i].dep_vdd_volt;
538 break; 538 break;
539 } 539 }
540 } 540 }
541 if (!dep_volt) { 541 if (!dep_volt) {
542 dev_warn(dev, "%s: %ld volt map missing in vdd_%s\n", 542 dev_warn(dev, "%s: %ld volt map missing in vdd_%s\n",
543 __func__, main_volt, dep_info->name); 543 __func__, main_volt, dep_info->name);
544 return -EINVAL; 544 return -EINVAL;
545 } 545 }
546 546
547 /* populate voltdm if it is not present */ 547 /* populate voltdm if it is not present */
548 if (!dep_info->_dep_voltdm) { 548 if (!dep_info->_dep_voltdm) {
549 dep_info->_dep_voltdm = voltdm_lookup(dep_info->name); 549 dep_info->_dep_voltdm = voltdm_lookup(dep_info->name);
550 if (!dep_info->_dep_voltdm) { 550 if (!dep_info->_dep_voltdm) {
551 dev_warn(dev, "%s: unable to get vdm%s\n", 551 dev_warn(dev, "%s: unable to get vdm%s\n",
552 __func__, dep_info->name); 552 __func__, dep_info->name);
553 return -ENODEV; 553 return -ENODEV;
554 } 554 }
555 } 555 }
556 556
557 /* See if dep_volt is possible for the vdd*/ 557 /* See if dep_volt is possible for the vdd*/
558 i = _add_vdd_user(_voltdm_to_dvfs_info(dep_info->_dep_voltdm), 558 i = _add_vdd_user(_voltdm_to_dvfs_info(dep_info->_dep_voltdm),
559 dev, dep_volt); 559 dev, dep_volt);
560 if (i) 560 if (i)
561 dev_err(dev, "%s: Failed to add dep to domain %s volt=%ld\n", 561 dev_err(dev, "%s: Failed to add dep to domain %s volt=%ld\n",
562 __func__, dep_info->name, dep_volt); 562 __func__, dep_info->name, dep_volt);
563 return i; 563 return i;
564 } 564 }
565 565
566 /** 566 /**
567 * _dep_scan_domains() - Scan dependency domains for a device 567 * _dep_scan_domains() - Scan dependency domains for a device
568 * @dev: device requesting the scan 568 * @dev: device requesting the scan
569 * @vdd: vdd_info corresponding to the device 569 * @vdd: vdd_info corresponding to the device
570 * @main_volt: voltage to scan for 570 * @main_volt: voltage to scan for
571 * 571 *
572 * Since each domain *may* have multiple dependent domains, we scan 572 * Since each domain *may* have multiple dependent domains, we scan
573 * through each of the dependent domains and invoke _dep_scan_table to 573 * through each of the dependent domains and invoke _dep_scan_table to
574 * scan each table for dependent domain for dependency scaling. 574 * scan each table for dependent domain for dependency scaling.
575 * 575 *
576 * This assumes that the dependent domain information is NULL entry terminated. 576 * This assumes that the dependent domain information is NULL entry terminated.
577 * Returns 0 if all went well. 577 * Returns 0 if all went well.
578 */ 578 */
579 static int _dep_scan_domains(struct device *dev, 579 static int _dep_scan_domains(struct device *dev,
580 struct omap_vdd_info *vdd, unsigned long main_volt) 580 struct omap_vdd_info *vdd, unsigned long main_volt)
581 { 581 {
582 struct omap_vdd_dep_info *dep_info = vdd->dep_vdd_info; 582 struct omap_vdd_dep_info *dep_info = vdd->dep_vdd_info;
583 int ret = 0, r; 583 int ret = 0, r;
584 584
585 if (!dep_info) { 585 if (!dep_info) {
586 dev_dbg(dev, "%s: No dependent VDD\n", __func__); 586 dev_dbg(dev, "%s: No dependent VDD\n", __func__);
587 return 0; 587 return 0;
588 } 588 }
589 589
590 /* First scan through the mydomain->dep_domain list */ 590 /* First scan through the mydomain->dep_domain list */
591 while (dep_info->nr_dep_entries) { 591 while (dep_info->nr_dep_entries) {
592 r = _dep_scan_table(dev, dep_info, main_volt); 592 r = _dep_scan_table(dev, dep_info, main_volt);
593 /* Store last failed value */ 593 /* Store last failed value */
594 ret = (r) ? r : ret; 594 ret = (r) ? r : ret;
595 dep_info++; 595 dep_info++;
596 } 596 }
597 597
598 return ret; 598 return ret;
599 } 599 }
600 600
601 /** 601 /**
602 * _dep_scale_domains() - Cause a scale of all dependent domains 602 * _dep_scale_domains() - Cause a scale of all dependent domains
603 * @req_dev: device requesting the scale 603 * @req_dev: device requesting the scale
604 * @req_vdd: vdd_info corresponding to the requesting device. 604 * @req_vdd: vdd_info corresponding to the requesting device.
605 * 605 *
606 * This walks through every dependent domain and triggers a scale 606 * This walks through every dependent domain and triggers a scale
607 * It is assumed that the corresponding scale handling for the 607 * It is assumed that the corresponding scale handling for the
608 * domain translates this to freq and voltage scale operations as 608 * domain translates this to freq and voltage scale operations as
609 * needed. 609 * needed.
610 * 610 *
611 * Note: This is uses _dvfs_scale and one should be careful not to 611 * Note: This is uses _dvfs_scale and one should be careful not to
612 * create a circular depedency (e.g. vdd_mpu->vdd_core->vdd->mpu) 612 * create a circular depedency (e.g. vdd_mpu->vdd_core->vdd->mpu)
613 * which can create deadlocks. No protection is provided to prevent 613 * which can create deadlocks. No protection is provided to prevent
614 * this condition and a tree organization is assumed. 614 * this condition and a tree organization is assumed.
615 * 615 *
616 * Returns 0 if all went fine. 616 * Returns 0 if all went fine.
617 */ 617 */
618 static int _dep_scale_domains(struct device *req_dev, 618 static int _dep_scale_domains(struct device *req_dev,
619 struct omap_vdd_info *req_vdd) 619 struct omap_vdd_info *req_vdd)
620 { 620 {
621 struct omap_vdd_dep_info *dep_info = req_vdd->dep_vdd_info; 621 struct omap_vdd_dep_info *dep_info = req_vdd->dep_vdd_info;
622 int ret = 0, r; 622 int ret = 0, r;
623 623
624 if (!dep_info) { 624 if (!dep_info) {
625 dev_dbg(req_dev, "%s: No dependent VDD\n", __func__); 625 dev_dbg(req_dev, "%s: No dependent VDD\n", __func__);
626 return 0; 626 return 0;
627 } 627 }
628 628
629 /* First scan through the mydomain->dep_domain list */ 629 /* First scan through the mydomain->dep_domain list */
630 while (dep_info->nr_dep_entries) { 630 while (dep_info->nr_dep_entries) {
631 struct voltagedomain *tvoltdm = dep_info->_dep_voltdm; 631 struct voltagedomain *tvoltdm = dep_info->_dep_voltdm;
632 632
633 r = 0; 633 r = 0;
634 /* Scale it only if I have a voltdm mapped up for the dep */ 634 /* Scale it only if I have a voltdm mapped up for the dep */
635 if (tvoltdm) { 635 if (tvoltdm) {
636 struct omap_vdd_dvfs_info *tdvfs_info; 636 struct omap_vdd_dvfs_info *tdvfs_info;
637 struct device *target_dev; 637 struct device *target_dev;
638 tdvfs_info = _voltdm_to_dvfs_info(tvoltdm); 638 tdvfs_info = _voltdm_to_dvfs_info(tvoltdm);
639 if (!tdvfs_info) { 639 if (!tdvfs_info) {
640 dev_warn(req_dev, "%s: no dvfs_info\n", 640 dev_warn(req_dev, "%s: no dvfs_info\n",
641 __func__); 641 __func__);
642 goto next; 642 goto next;
643 } 643 }
644 target_dev = _dvfs_info_to_dev(tdvfs_info); 644 target_dev = _dvfs_info_to_dev(tdvfs_info);
645 if (!target_dev) { 645 if (!target_dev) {
646 dev_warn(req_dev, "%s: no target_dev\n", 646 dev_warn(req_dev, "%s: no target_dev\n",
647 __func__); 647 __func__);
648 goto next; 648 goto next;
649 } 649 }
650 r = _dvfs_scale(req_dev, target_dev, tdvfs_info); 650 r = _dvfs_scale(req_dev, target_dev, tdvfs_info);
651 next: 651 next:
652 if (r) 652 if (r)
653 dev_err(req_dev, "%s: dvfs_scale to %s =%d\n", 653 dev_err(req_dev, "%s: dvfs_scale to %s =%d\n",
654 __func__, dev_name(target_dev), r); 654 __func__, dev_name(target_dev), r);
655 } 655 }
656 /* Store last failed value */ 656 /* Store last failed value */
657 ret = (r) ? r : ret; 657 ret = (r) ? r : ret;
658 dep_info++; 658 dep_info++;
659 } 659 }
660 660
661 return ret; 661 return ret;
662 } 662 }
663 663
664 /** 664 /**
665 * _dvfs_scale() : Scale the devices associated with a voltage domain 665 * _dvfs_scale() : Scale the devices associated with a voltage domain
666 * @req_dev: Device requesting the scale 666 * @req_dev: Device requesting the scale
667 * @target_dev: Device requesting to be scaled 667 * @target_dev: Device requesting to be scaled
668 * @tdvfs_info: omap_vdd_dvfs_info pointer for the target domain 668 * @tdvfs_info: omap_vdd_dvfs_info pointer for the target domain
669 * 669 *
670 * This runs through the list of devices associated with the 670 * This runs through the list of devices associated with the
671 * voltage domain and scales the device rates to the one requested 671 * voltage domain and scales the device rates to the one requested
672 * by the user or those corresponding to the new voltage of the 672 * by the user or those corresponding to the new voltage of the
673 * voltage domain. Target voltage is the highest voltage in the vdd_user_list. 673 * voltage domain. Target voltage is the highest voltage in the vdd_user_list.
674 * 674 *
675 * Returns 0 on success else the error value. 675 * Returns 0 on success else the error value.
676 */ 676 */
677 static int _dvfs_scale(struct device *req_dev, struct device *target_dev, 677 static int _dvfs_scale(struct device *req_dev, struct device *target_dev,
678 struct omap_vdd_dvfs_info *tdvfs_info) 678 struct omap_vdd_dvfs_info *tdvfs_info)
679 { 679 {
680 unsigned long curr_volt, new_volt; 680 unsigned long curr_volt, new_volt;
681 int volt_scale_dir = DVFS_VOLT_SCALE_DOWN; 681 int volt_scale_dir = DVFS_VOLT_SCALE_DOWN;
682 struct omap_vdd_dev_list *temp_dev; 682 struct omap_vdd_dev_list *temp_dev;
683 struct plist_node *node; 683 struct plist_node *node;
684 int ret = 0; 684 int ret = 0;
685 struct voltagedomain *voltdm; 685 struct voltagedomain *voltdm;
686 struct omap_vdd_info *vdd; 686 struct omap_vdd_info *vdd;
687 687
688 voltdm = tdvfs_info->voltdm; 688 voltdm = tdvfs_info->voltdm;
689 if (IS_ERR_OR_NULL(voltdm)) { 689 if (IS_ERR_OR_NULL(voltdm)) {
690 dev_err(target_dev, "%s: bad voltdm\n", __func__); 690 dev_err(target_dev, "%s: bad voltdm\n", __func__);
691 return -EINVAL; 691 return -EINVAL;
692 } 692 }
693 vdd = voltdm->vdd; 693 vdd = voltdm->vdd;
694 694
695 /* Find the highest voltage being requested */ 695 /* Find the highest voltage being requested */
696 node = plist_last(&tdvfs_info->vdd_user_list); 696 node = plist_last(&tdvfs_info->vdd_user_list);
697 new_volt = node->prio; 697 new_volt = node->prio;
698 698
699 curr_volt = voltdm_get_voltage(voltdm); 699 curr_volt = voltdm_get_voltage(voltdm);
700 700
701 /* Disable smartreflex module across voltage and frequency scaling */ 701 /* Disable smartreflex module across voltage and frequency scaling */
702 omap_sr_disable(voltdm); 702 omap_sr_disable(voltdm);
703 703
704 if (curr_volt == new_volt) { 704 if (curr_volt == new_volt) {
705 volt_scale_dir = DVFS_VOLT_SCALE_NONE; 705 volt_scale_dir = DVFS_VOLT_SCALE_NONE;
706 } else if (curr_volt < new_volt) { 706 } else if (curr_volt < new_volt) {
707 ret = voltdm_scale(voltdm, new_volt); 707 ret = voltdm_scale(voltdm, new_volt);
708 if (ret) { 708 if (ret) {
709 dev_err(target_dev, 709 dev_err(target_dev,
710 "%s: Unable to scale the %s to %ld volt\n", 710 "%s: Unable to scale the %s to %ld volt\n",
711 __func__, voltdm->name, new_volt); 711 __func__, voltdm->name, new_volt);
712 goto out; 712 goto out;
713 } 713 }
714 volt_scale_dir = DVFS_VOLT_SCALE_UP; 714 volt_scale_dir = DVFS_VOLT_SCALE_UP;
715 } 715 }
716 716
717 /* if we fail scale for dependent domains, go back to prev state */ 717 /* if we fail scale for dependent domains, go back to prev state */
718 ret = _dep_scan_domains(target_dev, vdd, new_volt); 718 ret = _dep_scan_domains(target_dev, vdd, new_volt);
719 if (ret) { 719 if (ret) {
720 dev_err(target_dev, 720 dev_err(target_dev,
721 "%s: Error in scan domains for vdd_%s\n", 721 "%s: Error in scan domains for vdd_%s\n",
722 __func__, voltdm->name); 722 __func__, voltdm->name);
723 goto fail; 723 goto fail;
724 } 724 }
725 725
726 /* unless we are moving down, scale dependents before we shift freq */ 726 /* unless we are moving down, scale dependents before we shift freq */
727 if (!(DVFS_VOLT_SCALE_DOWN == volt_scale_dir)) { 727 if (!(DVFS_VOLT_SCALE_DOWN == volt_scale_dir)) {
728 ret = _dep_scale_domains(target_dev, vdd); 728 ret = _dep_scale_domains(target_dev, vdd);
729 if (ret) { 729 if (ret) {
730 dev_err(target_dev, 730 dev_err(target_dev,
731 "%s: Error(%d)scale dependent with %ld volt\n", 731 "%s: Error(%d)scale dependent with %ld volt\n",
732 __func__, ret, new_volt); 732 __func__, ret, new_volt);
733 goto fail; 733 goto fail;
734 } 734 }
735 } 735 }
736 736
737 /* Move all devices in list to the required frequencies */ 737 /* Move all devices in list to the required frequencies */
738 list_for_each_entry(temp_dev, &tdvfs_info->dev_list, node) { 738 list_for_each_entry(temp_dev, &tdvfs_info->dev_list, node) {
739 struct device *dev; 739 struct device *dev;
740 struct opp *opp; 740 struct opp *opp;
741 unsigned long freq = 0; 741 unsigned long freq = 0;
742 int r; 742 int r;
743 743
744 dev = temp_dev->dev; 744 dev = temp_dev->dev;
745 if (!plist_head_empty(&temp_dev->freq_user_list)) { 745 if (!plist_head_empty(&temp_dev->freq_user_list)) {
746 node = plist_last(&temp_dev->freq_user_list); 746 node = plist_last(&temp_dev->freq_user_list);
747 freq = node->prio; 747 freq = node->prio;
748 } else { 748 } else {
749 /* dep domain? we'd probably have a voltage request */ 749 /* dep domain? we'd probably have a voltage request */
750 rcu_read_lock(); 750 rcu_read_lock();
751 opp = _volt_to_opp(dev, new_volt); 751 opp = _volt_to_opp(dev, new_volt);
752 if (!IS_ERR(opp)) 752 if (!IS_ERR(opp))
753 freq = opp_get_freq(opp); 753 freq = opp_get_freq(opp);
754 rcu_read_unlock(); 754 rcu_read_unlock();
755 if (!freq) 755 if (!freq)
756 continue; 756 continue;
757 } 757 }
758 758
759 if (freq == clk_get_rate(temp_dev->clk)) { 759 if (freq == clk_get_rate(temp_dev->clk)) {
760 dev_dbg(dev, "%s: Already at the requested" 760 dev_dbg(dev, "%s: Already at the requested"
761 "rate %ld\n", __func__, freq); 761 "rate %ld\n", __func__, freq);
762 continue; 762 continue;
763 } 763 }
764 764
765 r = clk_set_rate(temp_dev->clk, freq); 765 r = clk_set_rate(temp_dev->clk, freq);
766 if (r < 0) { 766 if (r < 0) {
767 dev_err(dev, "%s: clk set rate frq=%ld failed(%d)\n", 767 dev_err(dev, "%s: clk set rate frq=%ld failed(%d)\n",
768 __func__, freq, r); 768 __func__, freq, r);
769 ret = r; 769 ret = r;
770 } 770 }
771 } 771 }
772 772
773 if (ret) 773 if (ret)
774 goto fail; 774 goto fail;
775 775
776 if (DVFS_VOLT_SCALE_DOWN == volt_scale_dir) { 776 if (DVFS_VOLT_SCALE_DOWN == volt_scale_dir) {
777 voltdm_scale(voltdm, new_volt); 777 voltdm_scale(voltdm, new_volt);
778 _dep_scale_domains(target_dev, vdd); 778 _dep_scale_domains(target_dev, vdd);
779 } 779 }
780 780
781 /* All clear.. go out gracefully */ 781 /* All clear.. go out gracefully */
782 goto out; 782 goto out;
783 783
784 fail: 784 fail:
785 pr_warning("%s: domain%s: No clean recovery available! could be bad!\n", 785 pr_warning("%s: domain%s: No clean recovery available! could be bad!\n",
786 __func__, voltdm->name); 786 __func__, voltdm->name);
787 out: 787 out:
788 /* Re-enable Smartreflex module */ 788 /* Re-enable Smartreflex module */
789 omap_sr_enable(voltdm); 789 omap_sr_enable(voltdm);
790 790
791 return ret; 791 return ret;
792 } 792 }
793 793
794 /* Public functions */ 794 /* Public functions */
795 795
796 /** 796 /**
797 * omap_device_scale() - Set a new rate at which the device is to operate 797 * omap_device_scale() - Set a new rate at which the device is to operate
798 * @req_dev: pointer to the device requesting the scaling. 798 * @req_dev: pointer to the device requesting the scaling.
799 * @target_dev: pointer to the device that is to be scaled 799 * @target_dev: pointer to the device that is to be scaled
800 * @rate: the rnew rate for the device. 800 * @rate: the rnew rate for the device.
801 * 801 *
802 * This API gets the device opp table associated with this device and 802 * This API gets the device opp table associated with this device and
803 * tries putting the device to the requested rate and the voltage domain 803 * tries putting the device to the requested rate and the voltage domain
804 * associated with the device to the voltage corresponding to the 804 * associated with the device to the voltage corresponding to the
805 * requested rate. Since multiple devices can be assocciated with a 805 * requested rate. Since multiple devices can be assocciated with a
806 * voltage domain this API finds out the possible voltage the 806 * voltage domain this API finds out the possible voltage the
807 * voltage domain can enter and then decides on the final device 807 * voltage domain can enter and then decides on the final device
808 * rate. 808 * rate.
809 * 809 *
810 * Return 0 on success else the error value 810 * Return 0 on success else the error value
811 */ 811 */
812 int omap_device_scale(struct device *req_dev, struct device *target_dev, 812 int omap_device_scale(struct device *req_dev, struct device *target_dev,
813 unsigned long rate) 813 unsigned long rate)
814 { 814 {
815 struct opp *opp; 815 struct opp *opp;
816 unsigned long volt, freq = rate; 816 unsigned long volt, freq = rate;
817 struct omap_vdd_dvfs_info *tdvfs_info; 817 struct omap_vdd_dvfs_info *tdvfs_info;
818 struct platform_device *pdev; 818 struct platform_device *pdev;
819 int ret = 0; 819 int ret = 0;
820 820
821 pdev = container_of(target_dev, struct platform_device, dev); 821 pdev = container_of(target_dev, struct platform_device, dev);
822 if (IS_ERR_OR_NULL(pdev)) { 822 if (IS_ERR_OR_NULL(pdev)) {
823 pr_err("%s: pdev is null!\n", __func__); 823 pr_err("%s: pdev is null!\n", __func__);
824 return -EINVAL; 824 return -EINVAL;
825 } 825 }
826 826
827 /* Lock me to ensure cross domain scaling is secure */ 827 /* Lock me to ensure cross domain scaling is secure */
828 mutex_lock(&omap_dvfs_lock); 828 mutex_lock(&omap_dvfs_lock);
829 829
830 rcu_read_lock(); 830 rcu_read_lock();
831 opp = opp_find_freq_ceil(target_dev, &freq); 831 opp = opp_find_freq_ceil(target_dev, &freq);
832 if (IS_ERR(opp)) { 832 if (IS_ERR(opp)) {
833 rcu_read_unlock(); 833 rcu_read_unlock();
834 dev_err(target_dev, "%s: Unable to find OPP for freq%ld\n", 834 dev_err(target_dev, "%s: Unable to find OPP for freq%ld\n",
835 __func__, rate); 835 __func__, rate);
836 ret = -ENODEV; 836 ret = -ENODEV;
837 goto out; 837 goto out;
838 } 838 }
839 volt = opp_get_voltage(opp); 839 volt = opp_get_voltage(opp);
840 rcu_read_unlock(); 840 rcu_read_unlock();
841 841
842 tdvfs_info = _dev_to_dvfs_info(target_dev); 842 tdvfs_info = _dev_to_dvfs_info(target_dev);
843 if (IS_ERR_OR_NULL(tdvfs_info)) { 843 if (IS_ERR_OR_NULL(tdvfs_info)) {
844 dev_err(target_dev, "%s: (req=%s) no vdd![f=%ld, v=%ld]\n", 844 dev_err(target_dev, "%s: (req=%s) no vdd![f=%ld, v=%ld]\n",
845 __func__, dev_name(req_dev), freq, volt); 845 __func__, dev_name(req_dev), freq, volt);
846 ret = -ENODEV; 846 ret = -ENODEV;
847 goto out; 847 goto out;
848 } 848 }
849 849
850 ret = _add_freq_request(tdvfs_info, req_dev, target_dev, freq); 850 ret = _add_freq_request(tdvfs_info, req_dev, target_dev, freq);
851 if (ret) { 851 if (ret) {
852 dev_err(target_dev, "%s: freqadd(%s) failed %d[f=%ld, v=%ld]\n", 852 dev_err(target_dev, "%s: freqadd(%s) failed %d[f=%ld, v=%ld]\n",
853 __func__, dev_name(req_dev), ret, freq, volt); 853 __func__, dev_name(req_dev), ret, freq, volt);
854 goto out; 854 goto out;
855 } 855 }
856 856
857 ret = _add_vdd_user(tdvfs_info, req_dev, volt); 857 ret = _add_vdd_user(tdvfs_info, req_dev, volt);
858 if (ret) { 858 if (ret) {
859 dev_err(target_dev, "%s: vddadd(%s) failed %d[f=%ld, v=%ld]\n", 859 dev_err(target_dev, "%s: vddadd(%s) failed %d[f=%ld, v=%ld]\n",
860 __func__, dev_name(req_dev), ret, freq, volt); 860 __func__, dev_name(req_dev), ret, freq, volt);
861 _remove_freq_request(tdvfs_info, req_dev, 861 _remove_freq_request(tdvfs_info, req_dev,
862 target_dev); 862 target_dev);
863 goto out; 863 goto out;
864 } 864 }
865 865
866 /* Do the actual scaling */ 866 /* Do the actual scaling */
867 ret = _dvfs_scale(req_dev, target_dev, tdvfs_info); 867 ret = _dvfs_scale(req_dev, target_dev, tdvfs_info);
868 if (ret) { 868 if (ret) {
869 dev_err(target_dev, "%s: scale by %s failed %d[f=%ld, v=%ld]\n", 869 dev_err(target_dev, "%s: scale by %s failed %d[f=%ld, v=%ld]\n",
870 __func__, dev_name(req_dev), ret, freq, volt); 870 __func__, dev_name(req_dev), ret, freq, volt);
871 _remove_freq_request(tdvfs_info, req_dev, 871 _remove_freq_request(tdvfs_info, req_dev,
872 target_dev); 872 target_dev);
873 _remove_vdd_user(tdvfs_info, target_dev); 873 _remove_vdd_user(tdvfs_info, target_dev);
874 /* Fall through */ 874 /* Fall through */
875 } 875 }
876 /* Fall through */ 876 /* Fall through */
877 out: 877 out:
878 mutex_unlock(&omap_dvfs_lock); 878 mutex_unlock(&omap_dvfs_lock);
879 return ret; 879 return ret;
880 } 880 }
881 EXPORT_SYMBOL(omap_device_scale); 881 EXPORT_SYMBOL(omap_device_scale);
882 882
883 /** 883 /**
884 * omap_dvfs_register_device - Add a parent device into dvfs managed list 884 * omap_dvfs_register_device - Add a parent device into dvfs managed list
885 * @dev: Device to be added 885 * @dev: Device to be added
886 * @voltdm_name: Name of the voltage domain for the device 886 * @voltdm_name: Name of the voltage domain for the device
887 * @clk_name: Name of the clock for the device 887 * @clk_name: Name of the clock for the device
888 * 888 *
889 * This function adds a given device into user_list of corresponding 889 * This function adds a given device into user_list of corresponding
890 * vdd's omap_vdd_dvfs_info strucure. This list is traversed to scale 890 * vdd's omap_vdd_dvfs_info strucure. This list is traversed to scale
891 * frequencies of all the devices on a given vdd. 891 * frequencies of all the devices on a given vdd.
892 * 892 *
893 * Returns 0 on success. 893 * Returns 0 on success.
894 */ 894 */
895 int __init omap_dvfs_register_device(struct device *dev, char *voltdm_name, 895 int __init omap_dvfs_register_device(struct device *dev, char *voltdm_name,
896 char *clk_name) 896 char *clk_name)
897 { 897 {
898 struct omap_vdd_dev_list *temp_dev; 898 struct omap_vdd_dev_list *temp_dev;
899 struct omap_vdd_dvfs_info *dvfs_info; 899 struct omap_vdd_dvfs_info *dvfs_info;
900 struct clk *clk = NULL; 900 struct clk *clk = NULL;
901 int ret = 0; 901 int ret = 0;
902 902
903 if (!voltdm_name) { 903 if (!voltdm_name) {
904 dev_err(dev, "%s: Bad voltdm name!\n", __func__); 904 dev_err(dev, "%s: Bad voltdm name!\n", __func__);
905 return -EINVAL; 905 return -EINVAL;
906 } 906 }
907 if (!clk_name) { 907 if (!clk_name) {
908 dev_err(dev, "%s: Bad clk name!\n", __func__); 908 dev_err(dev, "%s: Bad clk name!\n", __func__);
909 return -EINVAL; 909 return -EINVAL;
910 } 910 }
911 911
912 /* Lock me to secure structure changes */ 912 /* Lock me to secure structure changes */
913 mutex_lock(&omap_dvfs_lock); 913 mutex_lock(&omap_dvfs_lock);
914 914
915 dvfs_info = _dev_to_dvfs_info(dev); 915 dvfs_info = _dev_to_dvfs_info(dev);
916 if (!dvfs_info) { 916 if (!dvfs_info) {
917 dvfs_info = kzalloc(sizeof(struct omap_vdd_dvfs_info), 917 dvfs_info = kzalloc(sizeof(struct omap_vdd_dvfs_info),
918 GFP_KERNEL); 918 GFP_KERNEL);
919 if (!dvfs_info) { 919 if (!dvfs_info) {
920 dev_warn(dev, "%s: unable to alloc memory!\n", 920 dev_warn(dev, "%s: unable to alloc memory!\n",
921 __func__); 921 __func__);
922 ret = -ENOMEM; 922 ret = -ENOMEM;
923 goto out; 923 goto out;
924 } 924 }
925 dvfs_info->voltdm = voltdm_lookup(voltdm_name); 925 dvfs_info->voltdm = voltdm_lookup(voltdm_name);
926 if (!dvfs_info->voltdm) { 926 if (!dvfs_info->voltdm) {
927 dev_warn(dev, "%s: unable to find voltdm %s!\n", 927 dev_warn(dev, "%s: unable to find voltdm %s!\n",
928 __func__, voltdm_name); 928 __func__, voltdm_name);
929 kfree(dvfs_info); 929 kfree(dvfs_info);
930 ret = -EINVAL; 930 ret = -EINVAL;
931 goto out; 931 goto out;
932 } 932 }
933 933
934 /* Init the plist */ 934 /* Init the plist */
935 spin_lock_init(&dvfs_info->user_lock); 935 spin_lock_init(&dvfs_info->user_lock);
936 plist_head_init(&dvfs_info->vdd_user_list); 936 plist_head_init(&dvfs_info->vdd_user_list);
937 937
938 /* Init the device list */ 938 /* Init the device list */
939 INIT_LIST_HEAD(&dvfs_info->dev_list); 939 INIT_LIST_HEAD(&dvfs_info->dev_list);
940 940
941 list_add(&dvfs_info->node, &omap_dvfs_info_list); 941 list_add(&dvfs_info->node, &omap_dvfs_info_list);
942 } 942 }
943 943
944 /* If device already added, we dont need to do more.. */ 944 /* If device already added, we dont need to do more.. */
945 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { 945 list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) {
946 if (temp_dev->dev == dev) 946 if (temp_dev->dev == dev)
947 goto out; 947 goto out;
948 } 948 }
949 949
950 temp_dev = kzalloc(sizeof(struct omap_vdd_dev_list), GFP_KERNEL); 950 temp_dev = kzalloc(sizeof(struct omap_vdd_dev_list), GFP_KERNEL);
951 if (!temp_dev) { 951 if (!temp_dev) {
952 dev_err(dev, "%s: Unable to creat a new device for vdd_%s\n", 952 dev_err(dev, "%s: Unable to creat a new device for vdd_%s\n",
953 __func__, dvfs_info->voltdm->name); 953 __func__, dvfs_info->voltdm->name);
954 ret = -ENOMEM; 954 ret = -ENOMEM;
955 goto out; 955 goto out;
956 } 956 }
957 957
958 clk = clk_get(dev, clk_name); 958 clk = clk_get(dev, clk_name);
959 if (IS_ERR_OR_NULL(clk)) { 959 if (IS_ERR_OR_NULL(clk)) {
960 dev_warn(dev, "%s: Bad clk pointer!\n", __func__); 960 dev_warn(dev, "%s: Bad clk pointer!\n", __func__);
961 kfree(temp_dev); 961 kfree(temp_dev);
962 ret = -EINVAL; 962 ret = -EINVAL;
963 goto out; 963 goto out;
964 } 964 }
965 965
966 /* Initialize priority ordered list */ 966 /* Initialize priority ordered list */
967 spin_lock_init(&temp_dev->user_lock); 967 spin_lock_init(&temp_dev->user_lock);
968 plist_head_init(&temp_dev->freq_user_list); 968 plist_head_init(&temp_dev->freq_user_list);
969 969
970 temp_dev->dev = dev; 970 temp_dev->dev = dev;
971 temp_dev->clk = clk; 971 temp_dev->clk = clk;
972 list_add_tail(&temp_dev->node, &dvfs_info->dev_list); 972 list_add_tail(&temp_dev->node, &dvfs_info->dev_list);
973 973
974 /* Fall through */ 974 /* Fall through */
975 out: 975 out:
976 mutex_unlock(&omap_dvfs_lock); 976 mutex_unlock(&omap_dvfs_lock);
977 return ret; 977 return ret;
978 } 978 }
979 979
arch/arm/mach-omap2/dvfs.h
1 /* File was deleted
2 * OMAP3/OMAP4 DVFS Management Routines
3 *
4 * Author: Vishwanath BS <vishwanath.bs@ti.com>
5 *
6 * Copyright (C) 2011 Texas Instruments, Inc.
7 * Vishwanath BS <vishwanath.bs@ti.com>
8 *
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
11 * published by the Free Software Foundation.
12 */
13
14 #ifndef __ARCH_ARM_MACH_OMAP2_DVFS_H
15 #define __ARCH_ARM_MACH_OMAP2_DVFS_H
16 #include <plat/omap_hwmod.h>
17 #include "voltage.h"
18
19 #ifdef CONFIG_PM
20 int omap_dvfs_register_device(struct device *dev, char *voltdm_name,
21 char *clk_name);
22 int omap_device_scale(struct device *req_dev, struct device *target_dev,
23 unsigned long rate);
24 #else
25 static inline int omap_dvfs_register_device(struct omap_hwmod *oh,
26 struct device *dev)
27 static inline int omap_dvfs_register_device(struct device *dev,
28 char *voltdm_name, char *clk_name)
29 {
30 return -EINVAL;
31 }
32 static inline int omap_device_scale(struct device *req_dev,
33 struct device *target_dev, unsigned long rate)
34 {
35 return -EINVAL;
36 }
37 #endif
38 #endif
39 1 /*
arch/arm/mach-omap2/io.c
1 /* 1 /*
2 * linux/arch/arm/mach-omap2/io.c 2 * linux/arch/arm/mach-omap2/io.c
3 * 3 *
4 * OMAP2 I/O mapping code 4 * OMAP2 I/O mapping code
5 * 5 *
6 * Copyright (C) 2005 Nokia Corporation 6 * Copyright (C) 2005 Nokia Corporation
7 * Copyright (C) 2007-2009 Texas Instruments 7 * Copyright (C) 2007-2009 Texas Instruments
8 * 8 *
9 * Author: 9 * Author:
10 * Juha Yrjola <juha.yrjola@nokia.com> 10 * Juha Yrjola <juha.yrjola@nokia.com>
11 * Syed Khasim <x0khasim@ti.com> 11 * Syed Khasim <x0khasim@ti.com>
12 * 12 *
13 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> 13 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
14 * 14 *
15 * This program is free software; you can redistribute it and/or modify 15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as 16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation. 17 * published by the Free Software Foundation.
18 */ 18 */
19 19
20 #include <linux/module.h> 20 #include <linux/module.h>
21 #include <linux/kernel.h> 21 #include <linux/kernel.h>
22 #include <linux/init.h> 22 #include <linux/init.h>
23 #include <linux/io.h> 23 #include <linux/io.h>
24 #include <linux/clk.h> 24 #include <linux/clk.h>
25 #include <linux/omapfb.h> 25 #include <linux/omapfb.h>
26 26
27 #include <asm/tlb.h> 27 #include <asm/tlb.h>
28 28
29 #include <asm/mach/map.h> 29 #include <asm/mach/map.h>
30 30
31 #include <plat/sram.h> 31 #include <plat/sram.h>
32 #include <plat/sdrc.h> 32 #include <plat/sdrc.h>
33 #include <plat/serial.h> 33 #include <plat/serial.h>
34 34
35 #include "clock2xxx.h" 35 #include "clock2xxx.h"
36 #include "clock3xxx.h" 36 #include "clock3xxx.h"
37 #include "clock44xx.h" 37 #include "clock44xx.h"
38 38
39 #include <plat/common.h> 39 #include <plat/common.h>
40 #include <plat/omap-pm.h> 40 #include <plat/omap-pm.h>
41 #include "voltage.h" 41 #include <plat/voltage.h>
42 #include "powerdomain.h" 42 #include "powerdomain.h"
43 43
44 #include "clockdomain.h" 44 #include "clockdomain.h"
45 #include <plat/omap_hwmod.h> 45 #include <plat/omap_hwmod.h>
46 #include <plat/multi.h> 46 #include <plat/multi.h>
47 #include <plat/common.h> 47 #include <plat/common.h>
48 48
49 /* 49 /*
50 * The machine specific code may provide the extra mapping besides the 50 * The machine specific code may provide the extra mapping besides the
51 * default mapping provided here. 51 * default mapping provided here.
52 */ 52 */
53 53
54 #ifdef CONFIG_ARCH_OMAP2 54 #ifdef CONFIG_ARCH_OMAP2
55 static struct map_desc omap24xx_io_desc[] __initdata = { 55 static struct map_desc omap24xx_io_desc[] __initdata = {
56 { 56 {
57 .virtual = L3_24XX_VIRT, 57 .virtual = L3_24XX_VIRT,
58 .pfn = __phys_to_pfn(L3_24XX_PHYS), 58 .pfn = __phys_to_pfn(L3_24XX_PHYS),
59 .length = L3_24XX_SIZE, 59 .length = L3_24XX_SIZE,
60 .type = MT_DEVICE 60 .type = MT_DEVICE
61 }, 61 },
62 { 62 {
63 .virtual = L4_24XX_VIRT, 63 .virtual = L4_24XX_VIRT,
64 .pfn = __phys_to_pfn(L4_24XX_PHYS), 64 .pfn = __phys_to_pfn(L4_24XX_PHYS),
65 .length = L4_24XX_SIZE, 65 .length = L4_24XX_SIZE,
66 .type = MT_DEVICE 66 .type = MT_DEVICE
67 }, 67 },
68 }; 68 };
69 69
70 #ifdef CONFIG_SOC_OMAP2420 70 #ifdef CONFIG_SOC_OMAP2420
71 static struct map_desc omap242x_io_desc[] __initdata = { 71 static struct map_desc omap242x_io_desc[] __initdata = {
72 { 72 {
73 .virtual = DSP_MEM_2420_VIRT, 73 .virtual = DSP_MEM_2420_VIRT,
74 .pfn = __phys_to_pfn(DSP_MEM_2420_PHYS), 74 .pfn = __phys_to_pfn(DSP_MEM_2420_PHYS),
75 .length = DSP_MEM_2420_SIZE, 75 .length = DSP_MEM_2420_SIZE,
76 .type = MT_DEVICE 76 .type = MT_DEVICE
77 }, 77 },
78 { 78 {
79 .virtual = DSP_IPI_2420_VIRT, 79 .virtual = DSP_IPI_2420_VIRT,
80 .pfn = __phys_to_pfn(DSP_IPI_2420_PHYS), 80 .pfn = __phys_to_pfn(DSP_IPI_2420_PHYS),
81 .length = DSP_IPI_2420_SIZE, 81 .length = DSP_IPI_2420_SIZE,
82 .type = MT_DEVICE 82 .type = MT_DEVICE
83 }, 83 },
84 { 84 {
85 .virtual = DSP_MMU_2420_VIRT, 85 .virtual = DSP_MMU_2420_VIRT,
86 .pfn = __phys_to_pfn(DSP_MMU_2420_PHYS), 86 .pfn = __phys_to_pfn(DSP_MMU_2420_PHYS),
87 .length = DSP_MMU_2420_SIZE, 87 .length = DSP_MMU_2420_SIZE,
88 .type = MT_DEVICE 88 .type = MT_DEVICE
89 }, 89 },
90 }; 90 };
91 91
92 #endif 92 #endif
93 93
94 #ifdef CONFIG_SOC_OMAP2430 94 #ifdef CONFIG_SOC_OMAP2430
95 static struct map_desc omap243x_io_desc[] __initdata = { 95 static struct map_desc omap243x_io_desc[] __initdata = {
96 { 96 {
97 .virtual = L4_WK_243X_VIRT, 97 .virtual = L4_WK_243X_VIRT,
98 .pfn = __phys_to_pfn(L4_WK_243X_PHYS), 98 .pfn = __phys_to_pfn(L4_WK_243X_PHYS),
99 .length = L4_WK_243X_SIZE, 99 .length = L4_WK_243X_SIZE,
100 .type = MT_DEVICE 100 .type = MT_DEVICE
101 }, 101 },
102 { 102 {
103 .virtual = OMAP243X_GPMC_VIRT, 103 .virtual = OMAP243X_GPMC_VIRT,
104 .pfn = __phys_to_pfn(OMAP243X_GPMC_PHYS), 104 .pfn = __phys_to_pfn(OMAP243X_GPMC_PHYS),
105 .length = OMAP243X_GPMC_SIZE, 105 .length = OMAP243X_GPMC_SIZE,
106 .type = MT_DEVICE 106 .type = MT_DEVICE
107 }, 107 },
108 { 108 {
109 .virtual = OMAP243X_SDRC_VIRT, 109 .virtual = OMAP243X_SDRC_VIRT,
110 .pfn = __phys_to_pfn(OMAP243X_SDRC_PHYS), 110 .pfn = __phys_to_pfn(OMAP243X_SDRC_PHYS),
111 .length = OMAP243X_SDRC_SIZE, 111 .length = OMAP243X_SDRC_SIZE,
112 .type = MT_DEVICE 112 .type = MT_DEVICE
113 }, 113 },
114 { 114 {
115 .virtual = OMAP243X_SMS_VIRT, 115 .virtual = OMAP243X_SMS_VIRT,
116 .pfn = __phys_to_pfn(OMAP243X_SMS_PHYS), 116 .pfn = __phys_to_pfn(OMAP243X_SMS_PHYS),
117 .length = OMAP243X_SMS_SIZE, 117 .length = OMAP243X_SMS_SIZE,
118 .type = MT_DEVICE 118 .type = MT_DEVICE
119 }, 119 },
120 }; 120 };
121 #endif 121 #endif
122 #endif 122 #endif
123 123
124 #ifdef CONFIG_ARCH_OMAP3 124 #ifdef CONFIG_ARCH_OMAP3
125 static struct map_desc omap34xx_io_desc[] __initdata = { 125 static struct map_desc omap34xx_io_desc[] __initdata = {
126 { 126 {
127 .virtual = L3_34XX_VIRT, 127 .virtual = L3_34XX_VIRT,
128 .pfn = __phys_to_pfn(L3_34XX_PHYS), 128 .pfn = __phys_to_pfn(L3_34XX_PHYS),
129 .length = L3_34XX_SIZE, 129 .length = L3_34XX_SIZE,
130 .type = MT_DEVICE 130 .type = MT_DEVICE
131 }, 131 },
132 { 132 {
133 .virtual = L4_34XX_VIRT, 133 .virtual = L4_34XX_VIRT,
134 .pfn = __phys_to_pfn(L4_34XX_PHYS), 134 .pfn = __phys_to_pfn(L4_34XX_PHYS),
135 .length = L4_34XX_SIZE, 135 .length = L4_34XX_SIZE,
136 .type = MT_DEVICE 136 .type = MT_DEVICE
137 }, 137 },
138 { 138 {
139 .virtual = OMAP34XX_GPMC_VIRT, 139 .virtual = OMAP34XX_GPMC_VIRT,
140 .pfn = __phys_to_pfn(OMAP34XX_GPMC_PHYS), 140 .pfn = __phys_to_pfn(OMAP34XX_GPMC_PHYS),
141 .length = OMAP34XX_GPMC_SIZE, 141 .length = OMAP34XX_GPMC_SIZE,
142 .type = MT_DEVICE 142 .type = MT_DEVICE
143 }, 143 },
144 { 144 {
145 .virtual = OMAP343X_SMS_VIRT, 145 .virtual = OMAP343X_SMS_VIRT,
146 .pfn = __phys_to_pfn(OMAP343X_SMS_PHYS), 146 .pfn = __phys_to_pfn(OMAP343X_SMS_PHYS),
147 .length = OMAP343X_SMS_SIZE, 147 .length = OMAP343X_SMS_SIZE,
148 .type = MT_DEVICE 148 .type = MT_DEVICE
149 }, 149 },
150 { 150 {
151 .virtual = OMAP343X_SDRC_VIRT, 151 .virtual = OMAP343X_SDRC_VIRT,
152 .pfn = __phys_to_pfn(OMAP343X_SDRC_PHYS), 152 .pfn = __phys_to_pfn(OMAP343X_SDRC_PHYS),
153 .length = OMAP343X_SDRC_SIZE, 153 .length = OMAP343X_SDRC_SIZE,
154 .type = MT_DEVICE 154 .type = MT_DEVICE
155 }, 155 },
156 { 156 {
157 .virtual = L4_PER_34XX_VIRT, 157 .virtual = L4_PER_34XX_VIRT,
158 .pfn = __phys_to_pfn(L4_PER_34XX_PHYS), 158 .pfn = __phys_to_pfn(L4_PER_34XX_PHYS),
159 .length = L4_PER_34XX_SIZE, 159 .length = L4_PER_34XX_SIZE,
160 .type = MT_DEVICE 160 .type = MT_DEVICE
161 }, 161 },
162 { 162 {
163 .virtual = L4_EMU_34XX_VIRT, 163 .virtual = L4_EMU_34XX_VIRT,
164 .pfn = __phys_to_pfn(L4_EMU_34XX_PHYS), 164 .pfn = __phys_to_pfn(L4_EMU_34XX_PHYS),
165 .length = L4_EMU_34XX_SIZE, 165 .length = L4_EMU_34XX_SIZE,
166 .type = MT_DEVICE 166 .type = MT_DEVICE
167 }, 167 },
168 #if defined(CONFIG_DEBUG_LL) && \ 168 #if defined(CONFIG_DEBUG_LL) && \
169 (defined(CONFIG_MACH_OMAP_ZOOM2) || defined(CONFIG_MACH_OMAP_ZOOM3)) 169 (defined(CONFIG_MACH_OMAP_ZOOM2) || defined(CONFIG_MACH_OMAP_ZOOM3))
170 { 170 {
171 .virtual = ZOOM_UART_VIRT, 171 .virtual = ZOOM_UART_VIRT,
172 .pfn = __phys_to_pfn(ZOOM_UART_BASE), 172 .pfn = __phys_to_pfn(ZOOM_UART_BASE),
173 .length = SZ_1M, 173 .length = SZ_1M,
174 .type = MT_DEVICE 174 .type = MT_DEVICE
175 }, 175 },
176 #endif 176 #endif
177 }; 177 };
178 #endif 178 #endif
179 179
180 #ifdef CONFIG_SOC_OMAPTI816X 180 #ifdef CONFIG_SOC_OMAPTI816X
181 static struct map_desc omapti816x_io_desc[] __initdata = { 181 static struct map_desc omapti816x_io_desc[] __initdata = {
182 { 182 {
183 .virtual = L4_34XX_VIRT, 183 .virtual = L4_34XX_VIRT,
184 .pfn = __phys_to_pfn(L4_34XX_PHYS), 184 .pfn = __phys_to_pfn(L4_34XX_PHYS),
185 .length = L4_34XX_SIZE, 185 .length = L4_34XX_SIZE,
186 .type = MT_DEVICE 186 .type = MT_DEVICE
187 } 187 }
188 }; 188 };
189 #endif 189 #endif
190 190
191 #ifdef CONFIG_SOC_OMAPAM33XX 191 #ifdef CONFIG_SOC_OMAPAM33XX
192 static struct map_desc omapam33xx_io_desc[] __initdata = { 192 static struct map_desc omapam33xx_io_desc[] __initdata = {
193 { 193 {
194 .virtual = L4_34XX_VIRT, 194 .virtual = L4_34XX_VIRT,
195 .pfn = __phys_to_pfn(L4_34XX_PHYS), 195 .pfn = __phys_to_pfn(L4_34XX_PHYS),
196 .length = L4_34XX_SIZE, 196 .length = L4_34XX_SIZE,
197 .type = MT_DEVICE 197 .type = MT_DEVICE
198 }, 198 },
199 { 199 {
200 .virtual = L4_WK_AM33XX_VIRT, 200 .virtual = L4_WK_AM33XX_VIRT,
201 .pfn = __phys_to_pfn(L4_WK_AM33XX_PHYS), 201 .pfn = __phys_to_pfn(L4_WK_AM33XX_PHYS),
202 .length = L4_WK_AM33XX_SIZE, 202 .length = L4_WK_AM33XX_SIZE,
203 .type = MT_DEVICE 203 .type = MT_DEVICE
204 } 204 }
205 }; 205 };
206 #endif 206 #endif
207 207
208 #ifdef CONFIG_ARCH_OMAP4 208 #ifdef CONFIG_ARCH_OMAP4
209 static struct map_desc omap44xx_io_desc[] __initdata = { 209 static struct map_desc omap44xx_io_desc[] __initdata = {
210 { 210 {
211 .virtual = L3_44XX_VIRT, 211 .virtual = L3_44XX_VIRT,
212 .pfn = __phys_to_pfn(L3_44XX_PHYS), 212 .pfn = __phys_to_pfn(L3_44XX_PHYS),
213 .length = L3_44XX_SIZE, 213 .length = L3_44XX_SIZE,
214 .type = MT_DEVICE, 214 .type = MT_DEVICE,
215 }, 215 },
216 { 216 {
217 .virtual = L4_44XX_VIRT, 217 .virtual = L4_44XX_VIRT,
218 .pfn = __phys_to_pfn(L4_44XX_PHYS), 218 .pfn = __phys_to_pfn(L4_44XX_PHYS),
219 .length = L4_44XX_SIZE, 219 .length = L4_44XX_SIZE,
220 .type = MT_DEVICE, 220 .type = MT_DEVICE,
221 }, 221 },
222 { 222 {
223 .virtual = OMAP44XX_GPMC_VIRT, 223 .virtual = OMAP44XX_GPMC_VIRT,
224 .pfn = __phys_to_pfn(OMAP44XX_GPMC_PHYS), 224 .pfn = __phys_to_pfn(OMAP44XX_GPMC_PHYS),
225 .length = OMAP44XX_GPMC_SIZE, 225 .length = OMAP44XX_GPMC_SIZE,
226 .type = MT_DEVICE, 226 .type = MT_DEVICE,
227 }, 227 },
228 { 228 {
229 .virtual = OMAP44XX_EMIF1_VIRT, 229 .virtual = OMAP44XX_EMIF1_VIRT,
230 .pfn = __phys_to_pfn(OMAP44XX_EMIF1_PHYS), 230 .pfn = __phys_to_pfn(OMAP44XX_EMIF1_PHYS),
231 .length = OMAP44XX_EMIF1_SIZE, 231 .length = OMAP44XX_EMIF1_SIZE,
232 .type = MT_DEVICE, 232 .type = MT_DEVICE,
233 }, 233 },
234 { 234 {
235 .virtual = OMAP44XX_EMIF2_VIRT, 235 .virtual = OMAP44XX_EMIF2_VIRT,
236 .pfn = __phys_to_pfn(OMAP44XX_EMIF2_PHYS), 236 .pfn = __phys_to_pfn(OMAP44XX_EMIF2_PHYS),
237 .length = OMAP44XX_EMIF2_SIZE, 237 .length = OMAP44XX_EMIF2_SIZE,
238 .type = MT_DEVICE, 238 .type = MT_DEVICE,
239 }, 239 },
240 { 240 {
241 .virtual = OMAP44XX_DMM_VIRT, 241 .virtual = OMAP44XX_DMM_VIRT,
242 .pfn = __phys_to_pfn(OMAP44XX_DMM_PHYS), 242 .pfn = __phys_to_pfn(OMAP44XX_DMM_PHYS),
243 .length = OMAP44XX_DMM_SIZE, 243 .length = OMAP44XX_DMM_SIZE,
244 .type = MT_DEVICE, 244 .type = MT_DEVICE,
245 }, 245 },
246 { 246 {
247 .virtual = L4_PER_44XX_VIRT, 247 .virtual = L4_PER_44XX_VIRT,
248 .pfn = __phys_to_pfn(L4_PER_44XX_PHYS), 248 .pfn = __phys_to_pfn(L4_PER_44XX_PHYS),
249 .length = L4_PER_44XX_SIZE, 249 .length = L4_PER_44XX_SIZE,
250 .type = MT_DEVICE, 250 .type = MT_DEVICE,
251 }, 251 },
252 { 252 {
253 .virtual = L4_EMU_44XX_VIRT, 253 .virtual = L4_EMU_44XX_VIRT,
254 .pfn = __phys_to_pfn(L4_EMU_44XX_PHYS), 254 .pfn = __phys_to_pfn(L4_EMU_44XX_PHYS),
255 .length = L4_EMU_44XX_SIZE, 255 .length = L4_EMU_44XX_SIZE,
256 .type = MT_DEVICE, 256 .type = MT_DEVICE,
257 }, 257 },
258 }; 258 };
259 #endif 259 #endif
260 260
261 #ifdef CONFIG_SOC_OMAP2420 261 #ifdef CONFIG_SOC_OMAP2420
262 void __init omap242x_map_common_io(void) 262 void __init omap242x_map_common_io(void)
263 { 263 {
264 iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc)); 264 iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
265 iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc)); 265 iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc));
266 } 266 }
267 #endif 267 #endif
268 268
269 #ifdef CONFIG_SOC_OMAP2430 269 #ifdef CONFIG_SOC_OMAP2430
270 void __init omap243x_map_common_io(void) 270 void __init omap243x_map_common_io(void)
271 { 271 {
272 iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc)); 272 iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
273 iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc)); 273 iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc));
274 } 274 }
275 #endif 275 #endif
276 276
277 #ifdef CONFIG_ARCH_OMAP3 277 #ifdef CONFIG_ARCH_OMAP3
278 void __init omap34xx_map_common_io(void) 278 void __init omap34xx_map_common_io(void)
279 { 279 {
280 iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc)); 280 iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc));
281 } 281 }
282 #endif 282 #endif
283 283
284 #ifdef CONFIG_SOC_OMAPTI816X 284 #ifdef CONFIG_SOC_OMAPTI816X
285 void __init omapti816x_map_common_io(void) 285 void __init omapti816x_map_common_io(void)
286 { 286 {
287 iotable_init(omapti816x_io_desc, ARRAY_SIZE(omapti816x_io_desc)); 287 iotable_init(omapti816x_io_desc, ARRAY_SIZE(omapti816x_io_desc));
288 } 288 }
289 #endif 289 #endif
290 290
291 #ifdef CONFIG_SOC_OMAPAM33XX 291 #ifdef CONFIG_SOC_OMAPAM33XX
292 void __init omapam33xx_map_common_io(void) 292 void __init omapam33xx_map_common_io(void)
293 { 293 {
294 iotable_init(omapam33xx_io_desc, ARRAY_SIZE(omapam33xx_io_desc)); 294 iotable_init(omapam33xx_io_desc, ARRAY_SIZE(omapam33xx_io_desc));
295 } 295 }
296 #endif 296 #endif
297 297
298 #ifdef CONFIG_ARCH_OMAP4 298 #ifdef CONFIG_ARCH_OMAP4
299 void __init omap44xx_map_common_io(void) 299 void __init omap44xx_map_common_io(void)
300 { 300 {
301 iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc)); 301 iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc));
302 } 302 }
303 #endif 303 #endif
304 304
305 /* 305 /*
306 * omap2_init_reprogram_sdrc - reprogram SDRC timing parameters 306 * omap2_init_reprogram_sdrc - reprogram SDRC timing parameters
307 * 307 *
308 * Sets the CORE DPLL3 M2 divider to the same value that it's at 308 * Sets the CORE DPLL3 M2 divider to the same value that it's at
309 * currently. This has the effect of setting the SDRC SDRAM AC timing 309 * currently. This has the effect of setting the SDRC SDRAM AC timing
310 * registers to the values currently defined by the kernel. Currently 310 * registers to the values currently defined by the kernel. Currently
311 * only defined for OMAP3; will return 0 if called on OMAP2. Returns 311 * only defined for OMAP3; will return 0 if called on OMAP2. Returns
312 * -EINVAL if the dpll3_m2_ck cannot be found, 0 if called on OMAP2, 312 * -EINVAL if the dpll3_m2_ck cannot be found, 0 if called on OMAP2,
313 * or passes along the return value of clk_set_rate(). 313 * or passes along the return value of clk_set_rate().
314 */ 314 */
315 static int __init _omap2_init_reprogram_sdrc(void) 315 static int __init _omap2_init_reprogram_sdrc(void)
316 { 316 {
317 struct clk *dpll3_m2_ck; 317 struct clk *dpll3_m2_ck;
318 int v = -EINVAL; 318 int v = -EINVAL;
319 long rate; 319 long rate;
320 320
321 if (!cpu_is_omap34xx()) 321 if (!cpu_is_omap34xx())
322 return 0; 322 return 0;
323 323
324 dpll3_m2_ck = clk_get(NULL, "dpll3_m2_ck"); 324 dpll3_m2_ck = clk_get(NULL, "dpll3_m2_ck");
325 if (IS_ERR(dpll3_m2_ck)) 325 if (IS_ERR(dpll3_m2_ck))
326 return -EINVAL; 326 return -EINVAL;
327 327
328 rate = clk_get_rate(dpll3_m2_ck); 328 rate = clk_get_rate(dpll3_m2_ck);
329 pr_info("Reprogramming SDRC clock to %ld Hz\n", rate); 329 pr_info("Reprogramming SDRC clock to %ld Hz\n", rate);
330 v = clk_set_rate(dpll3_m2_ck, rate); 330 v = clk_set_rate(dpll3_m2_ck, rate);
331 if (v) 331 if (v)
332 pr_err("dpll3_m2_clk rate change failed: %d\n", v); 332 pr_err("dpll3_m2_clk rate change failed: %d\n", v);
333 333
334 clk_put(dpll3_m2_ck); 334 clk_put(dpll3_m2_ck);
335 335
336 return v; 336 return v;
337 } 337 }
338 338
339 static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data) 339 static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
340 { 340 {
341 return omap_hwmod_set_postsetup_state(oh, *(u8 *)data); 341 return omap_hwmod_set_postsetup_state(oh, *(u8 *)data);
342 } 342 }
343 343
344 /* See irq.c, omap4-common.c and entry-macro.S */ 344 /* See irq.c, omap4-common.c and entry-macro.S */
345 void __iomem *omap_irq_base; 345 void __iomem *omap_irq_base;
346 346
347 static void __init omap_common_init_early(void) 347 static void __init omap_common_init_early(void)
348 { 348 {
349 omap2_check_revision(); 349 omap2_check_revision();
350 omap_ioremap_init(); 350 omap_ioremap_init();
351 } 351 }
352 352
353 static void __init omap_hwmod_init_postsetup(void) 353 static void __init omap_hwmod_init_postsetup(void)
354 { 354 {
355 u8 postsetup_state; 355 u8 postsetup_state;
356 356
357 /* Set the default postsetup state for all hwmods */ 357 /* Set the default postsetup state for all hwmods */
358 #ifdef CONFIG_PM_RUNTIME 358 #ifdef CONFIG_PM_RUNTIME
359 postsetup_state = _HWMOD_STATE_IDLE; 359 postsetup_state = _HWMOD_STATE_IDLE;
360 #else 360 #else
361 postsetup_state = _HWMOD_STATE_ENABLED; 361 postsetup_state = _HWMOD_STATE_ENABLED;
362 #endif 362 #endif
363 omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state); 363 omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);
364 364
365 /* 365 /*
366 * Set the default postsetup state for unusual modules (like 366 * Set the default postsetup state for unusual modules (like
367 * MPU WDT). 367 * MPU WDT).
368 * 368 *
369 * The postsetup_state is not actually used until 369 * The postsetup_state is not actually used until
370 * omap_hwmod_late_init(), so boards that desire full watchdog 370 * omap_hwmod_late_init(), so boards that desire full watchdog
371 * coverage of kernel initialization can reprogram the 371 * coverage of kernel initialization can reprogram the
372 * postsetup_state between the calls to 372 * postsetup_state between the calls to
373 * omap2_init_common_infra() and omap_sdrc_init(). 373 * omap2_init_common_infra() and omap_sdrc_init().
374 * 374 *
375 * XXX ideally we could detect whether the MPU WDT was currently 375 * XXX ideally we could detect whether the MPU WDT was currently
376 * enabled here and make this conditional 376 * enabled here and make this conditional
377 */ 377 */
378 postsetup_state = _HWMOD_STATE_DISABLED; 378 postsetup_state = _HWMOD_STATE_DISABLED;
379 omap_hwmod_for_each_by_class("wd_timer", 379 omap_hwmod_for_each_by_class("wd_timer",
380 _set_hwmod_postsetup_state, 380 _set_hwmod_postsetup_state,
381 &postsetup_state); 381 &postsetup_state);
382 382
383 omap_pm_if_early_init(); 383 omap_pm_if_early_init();
384 } 384 }
385 385
386 #ifdef CONFIG_SOC_OMAP2420 386 #ifdef CONFIG_SOC_OMAP2420
387 void __init omap2420_init_early(void) 387 void __init omap2420_init_early(void)
388 { 388 {
389 omap2_set_globals_242x(); 389 omap2_set_globals_242x();
390 omap_common_init_early(); 390 omap_common_init_early();
391 omap2xxx_voltagedomains_init(); 391 omap2xxx_voltagedomains_init();
392 omap242x_powerdomains_init(); 392 omap242x_powerdomains_init();
393 omap242x_clockdomains_init(); 393 omap242x_clockdomains_init();
394 omap2420_hwmod_init(); 394 omap2420_hwmod_init();
395 omap_hwmod_init_postsetup(); 395 omap_hwmod_init_postsetup();
396 omap2420_clk_init(); 396 omap2420_clk_init();
397 } 397 }
398 #endif 398 #endif
399 399
400 #ifdef CONFIG_SOC_OMAP2430 400 #ifdef CONFIG_SOC_OMAP2430
401 void __init omap2430_init_early(void) 401 void __init omap2430_init_early(void)
402 { 402 {
403 omap2_set_globals_243x(); 403 omap2_set_globals_243x();
404 omap_common_init_early(); 404 omap_common_init_early();
405 omap2xxx_voltagedomains_init(); 405 omap2xxx_voltagedomains_init();
406 omap243x_powerdomains_init(); 406 omap243x_powerdomains_init();
407 omap243x_clockdomains_init(); 407 omap243x_clockdomains_init();
408 omap2430_hwmod_init(); 408 omap2430_hwmod_init();
409 omap_hwmod_init_postsetup(); 409 omap_hwmod_init_postsetup();
410 omap2430_clk_init(); 410 omap2430_clk_init();
411 } 411 }
412 #endif 412 #endif
413 413
414 #ifdef CONFIG_ARCH_OMAP3 414 #ifdef CONFIG_ARCH_OMAP3
415 /* 415 /*
416 * Currently only board-omap3beagle.c should call this because of the 416 * Currently only board-omap3beagle.c should call this because of the
417 * same machine_id for 34xx and 36xx beagle.. Will get fixed with DT. 417 * same machine_id for 34xx and 36xx beagle.. Will get fixed with DT.
418 */ 418 */
419 void __init omap3_init_early(void) 419 void __init omap3_init_early(void)
420 { 420 {
421 omap2_set_globals_3xxx(); 421 omap2_set_globals_3xxx();
422 omap_common_init_early(); 422 omap_common_init_early();
423 omap3xxx_voltagedomains_init(); 423 omap3xxx_voltagedomains_init();
424 omap3xxx_powerdomains_init(); 424 omap3xxx_powerdomains_init();
425 omap3xxx_clockdomains_init(); 425 omap3xxx_clockdomains_init();
426 omap3xxx_hwmod_init(); 426 omap3xxx_hwmod_init();
427 omap_hwmod_init_postsetup(); 427 omap_hwmod_init_postsetup();
428 omap3xxx_clk_init(); 428 omap3xxx_clk_init();
429 } 429 }
430 430
431 void __init omap3430_init_early(void) 431 void __init omap3430_init_early(void)
432 { 432 {
433 omap3_init_early(); 433 omap3_init_early();
434 } 434 }
435 435
436 void __init omap35xx_init_early(void) 436 void __init omap35xx_init_early(void)
437 { 437 {
438 omap3_init_early(); 438 omap3_init_early();
439 } 439 }
440 440
441 void __init omap3630_init_early(void) 441 void __init omap3630_init_early(void)
442 { 442 {
443 omap3_init_early(); 443 omap3_init_early();
444 } 444 }
445 445
446 void __init am35xx_init_early(void) 446 void __init am35xx_init_early(void)
447 { 447 {
448 omap3_init_early(); 448 omap3_init_early();
449 } 449 }
450 450
451 void __init ti816x_init_early(void) 451 void __init ti816x_init_early(void)
452 { 452 {
453 omap2_set_globals_ti816x(); 453 omap2_set_globals_ti816x();
454 omap_common_init_early(); 454 omap_common_init_early();
455 omap3xxx_voltagedomains_init(); 455 omap3xxx_voltagedomains_init();
456 omap3xxx_powerdomains_init(); 456 omap3xxx_powerdomains_init();
457 omap3xxx_clockdomains_init(); 457 omap3xxx_clockdomains_init();
458 omap3xxx_hwmod_init(); 458 omap3xxx_hwmod_init();
459 omap_hwmod_init_postsetup(); 459 omap_hwmod_init_postsetup();
460 omap3xxx_clk_init(); 460 omap3xxx_clk_init();
461 } 461 }
462 #endif 462 #endif
463 463
464 #ifdef CONFIG_ARCH_OMAP4 464 #ifdef CONFIG_ARCH_OMAP4
465 void __init omap4430_init_early(void) 465 void __init omap4430_init_early(void)
466 { 466 {
467 omap2_set_globals_443x(); 467 omap2_set_globals_443x();
468 omap_common_init_early(); 468 omap_common_init_early();
469 omap44xx_voltagedomains_init(); 469 omap44xx_voltagedomains_init();
470 omap44xx_powerdomains_init(); 470 omap44xx_powerdomains_init();
471 omap44xx_clockdomains_init(); 471 omap44xx_clockdomains_init();
472 omap44xx_hwmod_init(); 472 omap44xx_hwmod_init();
473 omap_hwmod_init_postsetup(); 473 omap_hwmod_init_postsetup();
474 omap4xxx_clk_init(); 474 omap4xxx_clk_init();
475 } 475 }
476 #endif 476 #endif
477 477
478 void __init am335x_init_early(void) 478 void __init am335x_init_early(void)
479 { 479 {
480 omap2_set_globals_am33xx(); 480 omap2_set_globals_am33xx();
481 omap_common_init_early(); 481 omap_common_init_early();
482 am33xx_voltagedomains_init(); 482 am33xx_voltagedomains_init();
483 am33xx_powerdomains_init(); 483 am33xx_powerdomains_init();
484 am33xx_clockdomains_init(); 484 am33xx_clockdomains_init();
485 am33xx_hwmod_init(); 485 am33xx_hwmod_init();
486 omap_hwmod_init_postsetup(); 486 omap_hwmod_init_postsetup();
487 omap3xxx_clk_init(); 487 omap3xxx_clk_init();
488 } 488 }
489 489
490 void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0, 490 void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
491 struct omap_sdrc_params *sdrc_cs1) 491 struct omap_sdrc_params *sdrc_cs1)
492 { 492 {
493 omap_sram_init(); 493 omap_sram_init();
494 494
495 if (cpu_is_omap24xx() || omap3_has_sdrc()) { 495 if (cpu_is_omap24xx() || omap3_has_sdrc()) {
496 omap2_sdrc_init(sdrc_cs0, sdrc_cs1); 496 omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
497 _omap2_init_reprogram_sdrc(); 497 _omap2_init_reprogram_sdrc();
498 } 498 }
499 } 499 }
500 500
501 /* 501 /*
502 * NOTE: Please use ioremap + __raw_read/write where possible instead of these 502 * NOTE: Please use ioremap + __raw_read/write where possible instead of these
503 */ 503 */
504 504
505 u8 omap_readb(u32 pa) 505 u8 omap_readb(u32 pa)
506 { 506 {
507 return __raw_readb(OMAP2_L4_IO_ADDRESS(pa)); 507 return __raw_readb(OMAP2_L4_IO_ADDRESS(pa));
508 } 508 }
509 EXPORT_SYMBOL(omap_readb); 509 EXPORT_SYMBOL(omap_readb);
510 510
511 u16 omap_readw(u32 pa) 511 u16 omap_readw(u32 pa)
512 { 512 {
513 return __raw_readw(OMAP2_L4_IO_ADDRESS(pa)); 513 return __raw_readw(OMAP2_L4_IO_ADDRESS(pa));
514 } 514 }
515 EXPORT_SYMBOL(omap_readw); 515 EXPORT_SYMBOL(omap_readw);
516 516
517 u32 omap_readl(u32 pa) 517 u32 omap_readl(u32 pa)
518 { 518 {
519 return __raw_readl(OMAP2_L4_IO_ADDRESS(pa)); 519 return __raw_readl(OMAP2_L4_IO_ADDRESS(pa));
520 } 520 }
521 EXPORT_SYMBOL(omap_readl); 521 EXPORT_SYMBOL(omap_readl);
522 522
523 void omap_writeb(u8 v, u32 pa) 523 void omap_writeb(u8 v, u32 pa)
524 { 524 {
525 __raw_writeb(v, OMAP2_L4_IO_ADDRESS(pa)); 525 __raw_writeb(v, OMAP2_L4_IO_ADDRESS(pa));
526 } 526 }
527 EXPORT_SYMBOL(omap_writeb); 527 EXPORT_SYMBOL(omap_writeb);
528 528
529 void omap_writew(u16 v, u32 pa) 529 void omap_writew(u16 v, u32 pa)
530 { 530 {
531 __raw_writew(v, OMAP2_L4_IO_ADDRESS(pa)); 531 __raw_writew(v, OMAP2_L4_IO_ADDRESS(pa));
532 } 532 }
533 EXPORT_SYMBOL(omap_writew); 533 EXPORT_SYMBOL(omap_writew);
534 534
535 void omap_writel(u32 v, u32 pa) 535 void omap_writel(u32 v, u32 pa)
536 { 536 {
537 __raw_writel(v, OMAP2_L4_IO_ADDRESS(pa)); 537 __raw_writel(v, OMAP2_L4_IO_ADDRESS(pa));
538 } 538 }
539 EXPORT_SYMBOL(omap_writel); 539 EXPORT_SYMBOL(omap_writel);
540 540
arch/arm/mach-omap2/omap_opp_data.h
1 /* 1 /*
2 * OMAP SoC specific OPP Data helpers 2 * OMAP SoC specific OPP Data helpers
3 * 3 *
4 * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ 4 * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
5 * Nishanth Menon 5 * Nishanth Menon
6 * Kevin Hilman 6 * Kevin Hilman
7 * Copyright (C) 2010 Nokia Corporation. 7 * Copyright (C) 2010 Nokia Corporation.
8 * Eduardo Valentin 8 * Eduardo Valentin
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 * 13 *
14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
15 * kind, whether express or implied; without even the implied warranty 15 * kind, whether express or implied; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details. 17 * GNU General Public License for more details.
18 */ 18 */
19 #ifndef __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H 19 #ifndef __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H
20 #define __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H 20 #define __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H
21 21
22 #include <plat/omap_hwmod.h> 22 #include <plat/omap_hwmod.h>
23 #include <plat/voltage.h>
23 24
24 #include "voltage.h"
25 25
26 /* 26 /*
27 * *BIG FAT WARNING*: 27 * *BIG FAT WARNING*:
28 * USE the following ONLY in opp data initialization common to an SoC. 28 * USE the following ONLY in opp data initialization common to an SoC.
29 * DO NOT USE these in board files/pm core etc. 29 * DO NOT USE these in board files/pm core etc.
30 */ 30 */
31 31
32 /** 32 /**
33 * struct omap_opp_def - OMAP OPP Definition 33 * struct omap_opp_def - OMAP OPP Definition
34 * @hwmod_name: Name of the hwmod for this domain 34 * @hwmod_name: Name of the hwmod for this domain
35 * @freq: Frequency in hertz corresponding to this OPP 35 * @freq: Frequency in hertz corresponding to this OPP
36 * @u_volt: Nominal voltage in microvolts corresponding to this OPP 36 * @u_volt: Nominal voltage in microvolts corresponding to this OPP
37 * @default_available: True/false - is this OPP available by default 37 * @default_available: True/false - is this OPP available by default
38 * 38 *
39 * OMAP SOCs have a standard set of tuples consisting of frequency and voltage 39 * OMAP SOCs have a standard set of tuples consisting of frequency and voltage
40 * pairs that the device will support per voltage domain. This is called 40 * pairs that the device will support per voltage domain. This is called
41 * Operating Points or OPP. The actual definitions of OMAP Operating Points 41 * Operating Points or OPP. The actual definitions of OMAP Operating Points
42 * varies over silicon within the same family of devices. For a specific 42 * varies over silicon within the same family of devices. For a specific
43 * domain, you can have a set of {frequency, voltage} pairs and this is denoted 43 * domain, you can have a set of {frequency, voltage} pairs and this is denoted
44 * by an array of omap_opp_def. As the kernel boots and more information is 44 * by an array of omap_opp_def. As the kernel boots and more information is
45 * available, a set of these are activated based on the precise nature of 45 * available, a set of these are activated based on the precise nature of
46 * device the kernel boots up on. It is interesting to remember that each IP 46 * device the kernel boots up on. It is interesting to remember that each IP
47 * which belongs to a voltage domain may define their own set of OPPs on top 47 * which belongs to a voltage domain may define their own set of OPPs on top
48 * of this - but this is handled by the appropriate driver. 48 * of this - but this is handled by the appropriate driver.
49 */ 49 */
50 struct omap_opp_def { 50 struct omap_opp_def {
51 char *hwmod_name; 51 char *hwmod_name;
52 char *voltdm_name; 52 char *voltdm_name;
53 char *clk_name; 53 char *clk_name;
54 54
55 unsigned long freq; 55 unsigned long freq;
56 unsigned long u_volt; 56 unsigned long u_volt;
57 57
58 bool default_available; 58 bool default_available;
59 }; 59 };
60 60
61 /* 61 /*
62 * Initialization wrapper used to define an OPP for OMAP variants. 62 * Initialization wrapper used to define an OPP for OMAP variants.
63 */ 63 */
64 #define OPP_INITIALIZER(_hwmod_name, _clk_name, _voltdm_name, _enabled, _freq, _uv) \ 64 #define OPP_INITIALIZER(_hwmod_name, _clk_name, _voltdm_name, _enabled, _freq, _uv) \
65 { \ 65 { \
66 .hwmod_name = _hwmod_name, \ 66 .hwmod_name = _hwmod_name, \
67 .clk_name = _clk_name, \ 67 .clk_name = _clk_name, \
68 .voltdm_name = _voltdm_name, \ 68 .voltdm_name = _voltdm_name, \
69 .default_available = _enabled, \ 69 .default_available = _enabled, \
70 .freq = _freq, \ 70 .freq = _freq, \
71 .u_volt = _uv, \ 71 .u_volt = _uv, \
72 } 72 }
73 73
74 /* 74 /*
75 * Initialization wrapper used to define SmartReflex process data 75 * Initialization wrapper used to define SmartReflex process data
76 * XXX Is this needed? Just use C99 initializers in data files? 76 * XXX Is this needed? Just use C99 initializers in data files?
77 */ 77 */
78 #define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain) \ 78 #define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain) \
79 { \ 79 { \
80 .volt_nominal = _v_nom, \ 80 .volt_nominal = _v_nom, \
81 .sr_efuse_offs = _efuse_offs, \ 81 .sr_efuse_offs = _efuse_offs, \
82 .sr_errminlimit = _errminlimit, \ 82 .sr_errminlimit = _errminlimit, \
83 .vp_errgain = _errgain \ 83 .vp_errgain = _errgain \
84 } 84 }
85 85
86 /* Use this to initialize the default table */ 86 /* Use this to initialize the default table */
87 extern int __init omap_init_opp_table(struct omap_opp_def *opp_def, 87 extern int __init omap_init_opp_table(struct omap_opp_def *opp_def,
88 u32 opp_def_size); 88 u32 opp_def_size);
89 89
90 90
91 extern struct omap_volt_data omap34xx_vddmpu_volt_data[]; 91 extern struct omap_volt_data omap34xx_vddmpu_volt_data[];
92 extern struct omap_volt_data omap34xx_vddcore_volt_data[]; 92 extern struct omap_volt_data omap34xx_vddcore_volt_data[];
93 extern struct omap_vdd_dep_info omap34xx_vddmpu_dep_info[]; 93 extern struct omap_vdd_dep_info omap34xx_vddmpu_dep_info[];
94 extern struct omap_volt_data omap36xx_vddmpu_volt_data[]; 94 extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
95 extern struct omap_volt_data omap36xx_vddcore_volt_data[]; 95 extern struct omap_volt_data omap36xx_vddcore_volt_data[];
96 extern struct omap_vdd_dep_info omap36xx_vddmpu_dep_info[]; 96 extern struct omap_vdd_dep_info omap36xx_vddmpu_dep_info[];
97 97
98 extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[]; 98 extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[];
99 extern struct omap_volt_data omap44xx_vdd_iva_volt_data[]; 99 extern struct omap_volt_data omap44xx_vdd_iva_volt_data[];
100 extern struct omap_volt_data omap44xx_vdd_core_volt_data[]; 100 extern struct omap_volt_data omap44xx_vdd_core_volt_data[];
101 101
102 extern struct omap_vdd_dep_info omap443x_vddmpu_dep_info[]; 102 extern struct omap_vdd_dep_info omap443x_vddmpu_dep_info[];
103 extern struct omap_vdd_dep_info omap443x_vddiva_dep_info[]; 103 extern struct omap_vdd_dep_info omap443x_vddiva_dep_info[];
104 104
105 #endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */ 105 #endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
arch/arm/mach-omap2/omap_twl.c
1 /** 1 /**
2 * OMAP and TWL PMIC specific intializations. 2 * OMAP and TWL PMIC specific intializations.
3 * 3 *
4 * Copyright (C) 2010 Texas Instruments Incorporated. 4 * Copyright (C) 2010 Texas Instruments Incorporated.
5 * Thara Gopinath 5 * Thara Gopinath
6 * Copyright (C) 2009 Texas Instruments Incorporated. 6 * Copyright (C) 2009 Texas Instruments Incorporated.
7 * Nishanth Menon 7 * Nishanth Menon
8 * Copyright (C) 2009 Nokia Corporation 8 * Copyright (C) 2009 Nokia Corporation
9 * Paul Walmsley 9 * Paul Walmsley
10 * 10 *
11 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation. 13 * published by the Free Software Foundation.
14 */ 14 */
15 15
16 #include <linux/err.h> 16 #include <linux/err.h>
17 #include <linux/io.h> 17 #include <linux/io.h>
18 #include <linux/kernel.h> 18 #include <linux/kernel.h>
19 #include <linux/i2c/twl.h> 19 #include <linux/i2c/twl.h>
20 #include <plat/voltage.h>
20 21
21 #include "voltage.h"
22 22
23 #include "pm.h" 23 #include "pm.h"
24 24
25 #define OMAP3_SRI2C_SLAVE_ADDR 0x12 25 #define OMAP3_SRI2C_SLAVE_ADDR 0x12
26 #define OMAP3_VDD_MPU_SR_CONTROL_REG 0x00 26 #define OMAP3_VDD_MPU_SR_CONTROL_REG 0x00
27 #define OMAP3_VDD_CORE_SR_CONTROL_REG 0x01 27 #define OMAP3_VDD_CORE_SR_CONTROL_REG 0x01
28 #define OMAP3_VP_CONFIG_ERROROFFSET 0x00 28 #define OMAP3_VP_CONFIG_ERROROFFSET 0x00
29 #define OMAP3_VP_VSTEPMIN_VSTEPMIN 0x1 29 #define OMAP3_VP_VSTEPMIN_VSTEPMIN 0x1
30 #define OMAP3_VP_VSTEPMAX_VSTEPMAX 0x04 30 #define OMAP3_VP_VSTEPMAX_VSTEPMAX 0x04
31 #define OMAP3_VP_VLIMITTO_TIMEOUT_US 200 31 #define OMAP3_VP_VLIMITTO_TIMEOUT_US 200
32 32
33 #define OMAP3430_VP1_VLIMITTO_VDDMIN 0x14 33 #define OMAP3430_VP1_VLIMITTO_VDDMIN 0x14
34 #define OMAP3430_VP1_VLIMITTO_VDDMAX 0x42 34 #define OMAP3430_VP1_VLIMITTO_VDDMAX 0x42
35 #define OMAP3430_VP2_VLIMITTO_VDDMIN 0x18 35 #define OMAP3430_VP2_VLIMITTO_VDDMIN 0x18
36 #define OMAP3430_VP2_VLIMITTO_VDDMAX 0x2c 36 #define OMAP3430_VP2_VLIMITTO_VDDMAX 0x2c
37 37
38 #define OMAP3630_VP1_VLIMITTO_VDDMIN 0x18 38 #define OMAP3630_VP1_VLIMITTO_VDDMIN 0x18
39 #define OMAP3630_VP1_VLIMITTO_VDDMAX 0x3c 39 #define OMAP3630_VP1_VLIMITTO_VDDMAX 0x3c
40 #define OMAP3630_VP2_VLIMITTO_VDDMIN 0x18 40 #define OMAP3630_VP2_VLIMITTO_VDDMIN 0x18
41 #define OMAP3630_VP2_VLIMITTO_VDDMAX 0x30 41 #define OMAP3630_VP2_VLIMITTO_VDDMAX 0x30
42 42
43 #define OMAP4_SRI2C_SLAVE_ADDR 0x12 43 #define OMAP4_SRI2C_SLAVE_ADDR 0x12
44 #define OMAP4_VDD_MPU_SR_VOLT_REG 0x55 44 #define OMAP4_VDD_MPU_SR_VOLT_REG 0x55
45 #define OMAP4_VDD_MPU_SR_CMD_REG 0x56 45 #define OMAP4_VDD_MPU_SR_CMD_REG 0x56
46 #define OMAP4_VDD_IVA_SR_VOLT_REG 0x5B 46 #define OMAP4_VDD_IVA_SR_VOLT_REG 0x5B
47 #define OMAP4_VDD_IVA_SR_CMD_REG 0x5C 47 #define OMAP4_VDD_IVA_SR_CMD_REG 0x5C
48 #define OMAP4_VDD_CORE_SR_VOLT_REG 0x61 48 #define OMAP4_VDD_CORE_SR_VOLT_REG 0x61
49 #define OMAP4_VDD_CORE_SR_CMD_REG 0x62 49 #define OMAP4_VDD_CORE_SR_CMD_REG 0x62
50 50
51 #define OMAP4_VP_CONFIG_ERROROFFSET 0x00 51 #define OMAP4_VP_CONFIG_ERROROFFSET 0x00
52 #define OMAP4_VP_VSTEPMIN_VSTEPMIN 0x01 52 #define OMAP4_VP_VSTEPMIN_VSTEPMIN 0x01
53 #define OMAP4_VP_VSTEPMAX_VSTEPMAX 0x04 53 #define OMAP4_VP_VSTEPMAX_VSTEPMAX 0x04
54 #define OMAP4_VP_VLIMITTO_TIMEOUT_US 200 54 #define OMAP4_VP_VLIMITTO_TIMEOUT_US 200
55 55
56 #define OMAP4_VP_MPU_VLIMITTO_VDDMIN 0xA 56 #define OMAP4_VP_MPU_VLIMITTO_VDDMIN 0xA
57 #define OMAP4_VP_MPU_VLIMITTO_VDDMAX 0x39 57 #define OMAP4_VP_MPU_VLIMITTO_VDDMAX 0x39
58 #define OMAP4_VP_IVA_VLIMITTO_VDDMIN 0xA 58 #define OMAP4_VP_IVA_VLIMITTO_VDDMIN 0xA
59 #define OMAP4_VP_IVA_VLIMITTO_VDDMAX 0x2D 59 #define OMAP4_VP_IVA_VLIMITTO_VDDMAX 0x2D
60 #define OMAP4_VP_CORE_VLIMITTO_VDDMIN 0xA 60 #define OMAP4_VP_CORE_VLIMITTO_VDDMIN 0xA
61 #define OMAP4_VP_CORE_VLIMITTO_VDDMAX 0x28 61 #define OMAP4_VP_CORE_VLIMITTO_VDDMAX 0x28
62 62
63 static bool is_offset_valid; 63 static bool is_offset_valid;
64 static u8 smps_offset; 64 static u8 smps_offset;
65 /* 65 /*
66 * Flag to ensure Smartreflex bit in TWL 66 * Flag to ensure Smartreflex bit in TWL
67 * being cleared in board file is not overwritten. 67 * being cleared in board file is not overwritten.
68 */ 68 */
69 static bool __initdata twl_sr_enable_autoinit; 69 static bool __initdata twl_sr_enable_autoinit;
70 70
71 #define TWL4030_DCDC_GLOBAL_CFG 0x06 71 #define TWL4030_DCDC_GLOBAL_CFG 0x06
72 #define REG_SMPS_OFFSET 0xE0 72 #define REG_SMPS_OFFSET 0xE0
73 #define SMARTREFLEX_ENABLE BIT(3) 73 #define SMARTREFLEX_ENABLE BIT(3)
74 74
75 static unsigned long twl4030_vsel_to_uv(const u8 vsel) 75 static unsigned long twl4030_vsel_to_uv(const u8 vsel)
76 { 76 {
77 return (((vsel * 125) + 6000)) * 100; 77 return (((vsel * 125) + 6000)) * 100;
78 } 78 }
79 79
80 static u8 twl4030_uv_to_vsel(unsigned long uv) 80 static u8 twl4030_uv_to_vsel(unsigned long uv)
81 { 81 {
82 return DIV_ROUND_UP(uv - 600000, 12500); 82 return DIV_ROUND_UP(uv - 600000, 12500);
83 } 83 }
84 84
85 static unsigned long twl6030_vsel_to_uv(const u8 vsel) 85 static unsigned long twl6030_vsel_to_uv(const u8 vsel)
86 { 86 {
87 /* 87 /*
88 * In TWL6030 depending on the value of SMPS_OFFSET 88 * In TWL6030 depending on the value of SMPS_OFFSET
89 * efuse register the voltage range supported in 89 * efuse register the voltage range supported in
90 * standard mode can be either between 0.6V - 1.3V or 90 * standard mode can be either between 0.6V - 1.3V or
91 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse 91 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse
92 * is programmed to all 0's where as starting from 92 * is programmed to all 0's where as starting from
93 * TWL6030 ES1.1 the efuse is programmed to 1 93 * TWL6030 ES1.1 the efuse is programmed to 1
94 */ 94 */
95 if (!is_offset_valid) { 95 if (!is_offset_valid) {
96 twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset, 96 twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
97 REG_SMPS_OFFSET); 97 REG_SMPS_OFFSET);
98 is_offset_valid = true; 98 is_offset_valid = true;
99 } 99 }
100 100
101 if (!vsel) 101 if (!vsel)
102 return 0; 102 return 0;
103 /* 103 /*
104 * There is no specific formula for voltage to vsel 104 * There is no specific formula for voltage to vsel
105 * conversion above 1.3V. There are special hardcoded 105 * conversion above 1.3V. There are special hardcoded
106 * values for voltages above 1.3V. Currently we are 106 * values for voltages above 1.3V. Currently we are
107 * hardcoding only for 1.35 V which is used for 1GH OPP for 107 * hardcoding only for 1.35 V which is used for 1GH OPP for
108 * OMAP4430. 108 * OMAP4430.
109 */ 109 */
110 if (vsel == 0x3A) 110 if (vsel == 0x3A)
111 return 1350000; 111 return 1350000;
112 112
113 if (smps_offset & 0x8) 113 if (smps_offset & 0x8)
114 return ((((vsel - 1) * 1266) + 70900)) * 10; 114 return ((((vsel - 1) * 1266) + 70900)) * 10;
115 else 115 else
116 return ((((vsel - 1) * 1266) + 60770)) * 10; 116 return ((((vsel - 1) * 1266) + 60770)) * 10;
117 } 117 }
118 118
119 static u8 twl6030_uv_to_vsel(unsigned long uv) 119 static u8 twl6030_uv_to_vsel(unsigned long uv)
120 { 120 {
121 /* 121 /*
122 * In TWL6030 depending on the value of SMPS_OFFSET 122 * In TWL6030 depending on the value of SMPS_OFFSET
123 * efuse register the voltage range supported in 123 * efuse register the voltage range supported in
124 * standard mode can be either between 0.6V - 1.3V or 124 * standard mode can be either between 0.6V - 1.3V or
125 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse 125 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse
126 * is programmed to all 0's where as starting from 126 * is programmed to all 0's where as starting from
127 * TWL6030 ES1.1 the efuse is programmed to 1 127 * TWL6030 ES1.1 the efuse is programmed to 1
128 */ 128 */
129 if (!is_offset_valid) { 129 if (!is_offset_valid) {
130 twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset, 130 twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
131 REG_SMPS_OFFSET); 131 REG_SMPS_OFFSET);
132 is_offset_valid = true; 132 is_offset_valid = true;
133 } 133 }
134 134
135 if (!uv) 135 if (!uv)
136 return 0x00; 136 return 0x00;
137 /* 137 /*
138 * There is no specific formula for voltage to vsel 138 * There is no specific formula for voltage to vsel
139 * conversion above 1.3V. There are special hardcoded 139 * conversion above 1.3V. There are special hardcoded
140 * values for voltages above 1.3V. Currently we are 140 * values for voltages above 1.3V. Currently we are
141 * hardcoding only for 1.35 V which is used for 1GH OPP for 141 * hardcoding only for 1.35 V which is used for 1GH OPP for
142 * OMAP4430. 142 * OMAP4430.
143 */ 143 */
144 if (uv > twl6030_vsel_to_uv(0x39)) { 144 if (uv > twl6030_vsel_to_uv(0x39)) {
145 if (uv == 1350000) 145 if (uv == 1350000)
146 return 0x3A; 146 return 0x3A;
147 pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n", 147 pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n",
148 __func__, uv, twl6030_vsel_to_uv(0x39)); 148 __func__, uv, twl6030_vsel_to_uv(0x39));
149 return 0x3A; 149 return 0x3A;
150 } 150 }
151 151
152 if (smps_offset & 0x8) 152 if (smps_offset & 0x8)
153 return DIV_ROUND_UP(uv - 709000, 12660) + 1; 153 return DIV_ROUND_UP(uv - 709000, 12660) + 1;
154 else 154 else
155 return DIV_ROUND_UP(uv - 607700, 12660) + 1; 155 return DIV_ROUND_UP(uv - 607700, 12660) + 1;
156 } 156 }
157 157
158 static struct omap_voltdm_pmic omap3_mpu_pmic = { 158 static struct omap_voltdm_pmic omap3_mpu_pmic = {
159 .slew_rate = 4000, 159 .slew_rate = 4000,
160 .step_size = 12500, 160 .step_size = 12500,
161 .on_volt = 1200000, 161 .on_volt = 1200000,
162 .onlp_volt = 1000000, 162 .onlp_volt = 1000000,
163 .ret_volt = 975000, 163 .ret_volt = 975000,
164 .off_volt = 600000, 164 .off_volt = 600000,
165 .volt_setup_time = 0xfff, 165 .volt_setup_time = 0xfff,
166 .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET, 166 .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
167 .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN, 167 .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
168 .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX, 168 .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
169 .vp_vddmin = OMAP3430_VP1_VLIMITTO_VDDMIN, 169 .vp_vddmin = OMAP3430_VP1_VLIMITTO_VDDMIN,
170 .vp_vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX, 170 .vp_vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX,
171 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, 171 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
172 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, 172 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
173 .volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG, 173 .volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG,
174 .i2c_high_speed = true, 174 .i2c_high_speed = true,
175 .vsel_to_uv = twl4030_vsel_to_uv, 175 .vsel_to_uv = twl4030_vsel_to_uv,
176 .uv_to_vsel = twl4030_uv_to_vsel, 176 .uv_to_vsel = twl4030_uv_to_vsel,
177 }; 177 };
178 178
179 static struct omap_voltdm_pmic omap3_core_pmic = { 179 static struct omap_voltdm_pmic omap3_core_pmic = {
180 .slew_rate = 4000, 180 .slew_rate = 4000,
181 .step_size = 12500, 181 .step_size = 12500,
182 .on_volt = 1200000, 182 .on_volt = 1200000,
183 .onlp_volt = 1000000, 183 .onlp_volt = 1000000,
184 .ret_volt = 975000, 184 .ret_volt = 975000,
185 .off_volt = 600000, 185 .off_volt = 600000,
186 .volt_setup_time = 0xfff, 186 .volt_setup_time = 0xfff,
187 .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET, 187 .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
188 .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN, 188 .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
189 .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX, 189 .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
190 .vp_vddmin = OMAP3430_VP2_VLIMITTO_VDDMIN, 190 .vp_vddmin = OMAP3430_VP2_VLIMITTO_VDDMIN,
191 .vp_vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX, 191 .vp_vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX,
192 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, 192 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
193 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, 193 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
194 .volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG, 194 .volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG,
195 .i2c_high_speed = true, 195 .i2c_high_speed = true,
196 .vsel_to_uv = twl4030_vsel_to_uv, 196 .vsel_to_uv = twl4030_vsel_to_uv,
197 .uv_to_vsel = twl4030_uv_to_vsel, 197 .uv_to_vsel = twl4030_uv_to_vsel,
198 }; 198 };
199 199
200 static struct omap_voltdm_pmic omap4_mpu_pmic = { 200 static struct omap_voltdm_pmic omap4_mpu_pmic = {
201 .slew_rate = 4000, 201 .slew_rate = 4000,
202 .step_size = 12660, 202 .step_size = 12660,
203 .on_volt = 1375000, 203 .on_volt = 1375000,
204 .onlp_volt = 1375000, 204 .onlp_volt = 1375000,
205 .ret_volt = 830000, 205 .ret_volt = 830000,
206 .off_volt = 0, 206 .off_volt = 0,
207 .volt_setup_time = 0, 207 .volt_setup_time = 0,
208 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, 208 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
209 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, 209 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
210 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, 210 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
211 .vp_vddmin = OMAP4_VP_MPU_VLIMITTO_VDDMIN, 211 .vp_vddmin = OMAP4_VP_MPU_VLIMITTO_VDDMIN,
212 .vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX, 212 .vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX,
213 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, 213 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
214 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, 214 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
215 .volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG, 215 .volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG,
216 .cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG, 216 .cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG,
217 .i2c_high_speed = true, 217 .i2c_high_speed = true,
218 .vsel_to_uv = twl6030_vsel_to_uv, 218 .vsel_to_uv = twl6030_vsel_to_uv,
219 .uv_to_vsel = twl6030_uv_to_vsel, 219 .uv_to_vsel = twl6030_uv_to_vsel,
220 }; 220 };
221 221
222 static struct omap_voltdm_pmic omap4_iva_pmic = { 222 static struct omap_voltdm_pmic omap4_iva_pmic = {
223 .slew_rate = 4000, 223 .slew_rate = 4000,
224 .step_size = 12660, 224 .step_size = 12660,
225 .on_volt = 1188000, 225 .on_volt = 1188000,
226 .onlp_volt = 1188000, 226 .onlp_volt = 1188000,
227 .ret_volt = 830000, 227 .ret_volt = 830000,
228 .off_volt = 0, 228 .off_volt = 0,
229 .volt_setup_time = 0, 229 .volt_setup_time = 0,
230 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, 230 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
231 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, 231 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
232 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, 232 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
233 .vp_vddmin = OMAP4_VP_IVA_VLIMITTO_VDDMIN, 233 .vp_vddmin = OMAP4_VP_IVA_VLIMITTO_VDDMIN,
234 .vp_vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX, 234 .vp_vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX,
235 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, 235 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
236 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, 236 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
237 .volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG, 237 .volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG,
238 .cmd_reg_addr = OMAP4_VDD_IVA_SR_CMD_REG, 238 .cmd_reg_addr = OMAP4_VDD_IVA_SR_CMD_REG,
239 .i2c_high_speed = true, 239 .i2c_high_speed = true,
240 .vsel_to_uv = twl6030_vsel_to_uv, 240 .vsel_to_uv = twl6030_vsel_to_uv,
241 .uv_to_vsel = twl6030_uv_to_vsel, 241 .uv_to_vsel = twl6030_uv_to_vsel,
242 }; 242 };
243 243
244 static struct omap_voltdm_pmic omap4_core_pmic = { 244 static struct omap_voltdm_pmic omap4_core_pmic = {
245 .slew_rate = 4000, 245 .slew_rate = 4000,
246 .step_size = 12660, 246 .step_size = 12660,
247 .on_volt = 1200000, 247 .on_volt = 1200000,
248 .onlp_volt = 1200000, 248 .onlp_volt = 1200000,
249 .ret_volt = 830000, 249 .ret_volt = 830000,
250 .off_volt = 0, 250 .off_volt = 0,
251 .volt_setup_time = 0, 251 .volt_setup_time = 0,
252 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, 252 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
253 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, 253 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
254 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, 254 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
255 .vp_vddmin = OMAP4_VP_CORE_VLIMITTO_VDDMIN, 255 .vp_vddmin = OMAP4_VP_CORE_VLIMITTO_VDDMIN,
256 .vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX, 256 .vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX,
257 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, 257 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
258 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, 258 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
259 .volt_reg_addr = OMAP4_VDD_CORE_SR_VOLT_REG, 259 .volt_reg_addr = OMAP4_VDD_CORE_SR_VOLT_REG,
260 .cmd_reg_addr = OMAP4_VDD_CORE_SR_CMD_REG, 260 .cmd_reg_addr = OMAP4_VDD_CORE_SR_CMD_REG,
261 .vsel_to_uv = twl6030_vsel_to_uv, 261 .vsel_to_uv = twl6030_vsel_to_uv,
262 .uv_to_vsel = twl6030_uv_to_vsel, 262 .uv_to_vsel = twl6030_uv_to_vsel,
263 }; 263 };
264 264
265 int __init omap4_twl_init(void) 265 int __init omap4_twl_init(void)
266 { 266 {
267 struct voltagedomain *voltdm; 267 struct voltagedomain *voltdm;
268 268
269 if (!cpu_is_omap44xx()) 269 if (!cpu_is_omap44xx())
270 return -ENODEV; 270 return -ENODEV;
271 271
272 voltdm = voltdm_lookup("mpu"); 272 voltdm = voltdm_lookup("mpu");
273 omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic); 273 omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic);
274 274
275 voltdm = voltdm_lookup("iva"); 275 voltdm = voltdm_lookup("iva");
276 omap_voltage_register_pmic(voltdm, &omap4_iva_pmic); 276 omap_voltage_register_pmic(voltdm, &omap4_iva_pmic);
277 277
278 voltdm = voltdm_lookup("core"); 278 voltdm = voltdm_lookup("core");
279 omap_voltage_register_pmic(voltdm, &omap4_core_pmic); 279 omap_voltage_register_pmic(voltdm, &omap4_core_pmic);
280 280
281 return 0; 281 return 0;
282 } 282 }
283 283
284 int __init omap3_twl_init(void) 284 int __init omap3_twl_init(void)
285 { 285 {
286 struct voltagedomain *voltdm; 286 struct voltagedomain *voltdm;
287 287
288 if (!cpu_is_omap34xx() || cpu_is_am33xx()) 288 if (!cpu_is_omap34xx() || cpu_is_am33xx())
289 return -ENODEV; 289 return -ENODEV;
290 290
291 if (cpu_is_omap3630()) { 291 if (cpu_is_omap3630()) {
292 omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN; 292 omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
293 omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX; 293 omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
294 omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN; 294 omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
295 omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX; 295 omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
296 } 296 }
297 297
298 /* 298 /*
299 * The smartreflex bit on twl4030 specifies if the setting of voltage 299 * The smartreflex bit on twl4030 specifies if the setting of voltage
300 * is done over the I2C_SR path. Since this setting is independent of 300 * is done over the I2C_SR path. Since this setting is independent of
301 * the actual usage of smartreflex AVS module, we enable TWL SR bit 301 * the actual usage of smartreflex AVS module, we enable TWL SR bit
302 * by default irrespective of whether smartreflex AVS module is enabled 302 * by default irrespective of whether smartreflex AVS module is enabled
303 * on the OMAP side or not. This is because without this bit enabled, 303 * on the OMAP side or not. This is because without this bit enabled,
304 * the voltage scaling through vp forceupdate/bypass mechanism of 304 * the voltage scaling through vp forceupdate/bypass mechanism of
305 * voltage scaling will not function on TWL over I2C_SR. 305 * voltage scaling will not function on TWL over I2C_SR.
306 */ 306 */
307 if (!twl_sr_enable_autoinit) 307 if (!twl_sr_enable_autoinit)
308 omap3_twl_set_sr_bit(true); 308 omap3_twl_set_sr_bit(true);
309 309
310 voltdm = voltdm_lookup("mpu_iva"); 310 voltdm = voltdm_lookup("mpu_iva");
311 omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic); 311 omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
312 312
313 voltdm = voltdm_lookup("core"); 313 voltdm = voltdm_lookup("core");
314 omap_voltage_register_pmic(voltdm, &omap3_core_pmic); 314 omap_voltage_register_pmic(voltdm, &omap3_core_pmic);
315 315
316 return 0; 316 return 0;
317 } 317 }
318 318
319 /** 319 /**
320 * omap3_twl_set_sr_bit() - Set/Clear SR bit on TWL 320 * omap3_twl_set_sr_bit() - Set/Clear SR bit on TWL
321 * @enable: enable SR mode in twl or not 321 * @enable: enable SR mode in twl or not
322 * 322 *
323 * If 'enable' is true, enables Smartreflex bit on TWL 4030 to make sure 323 * If 'enable' is true, enables Smartreflex bit on TWL 4030 to make sure
324 * voltage scaling through OMAP SR works. Else, the smartreflex bit 324 * voltage scaling through OMAP SR works. Else, the smartreflex bit
325 * on twl4030 is cleared as there are platforms which use OMAP3 and T2 but 325 * on twl4030 is cleared as there are platforms which use OMAP3 and T2 but
326 * use Synchronized Scaling Hardware Strategy (ENABLE_VMODE=1) and Direct 326 * use Synchronized Scaling Hardware Strategy (ENABLE_VMODE=1) and Direct
327 * Strategy Software Scaling Mode (ENABLE_VMODE=0), for setting the voltages, 327 * Strategy Software Scaling Mode (ENABLE_VMODE=0), for setting the voltages,
328 * in those scenarios this bit is to be cleared (enable = false). 328 * in those scenarios this bit is to be cleared (enable = false).
329 * 329 *
330 * Returns 0 on success, error is returned if I2C read/write fails. 330 * Returns 0 on success, error is returned if I2C read/write fails.
331 */ 331 */
332 int __init omap3_twl_set_sr_bit(bool enable) 332 int __init omap3_twl_set_sr_bit(bool enable)
333 { 333 {
334 u8 temp; 334 u8 temp;
335 int ret; 335 int ret;
336 if (twl_sr_enable_autoinit) 336 if (twl_sr_enable_autoinit)
337 pr_warning("%s: unexpected multiple calls\n", __func__); 337 pr_warning("%s: unexpected multiple calls\n", __func__);
338 338
339 ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &temp, 339 ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &temp,
340 TWL4030_DCDC_GLOBAL_CFG); 340 TWL4030_DCDC_GLOBAL_CFG);
341 if (ret) 341 if (ret)
342 goto err; 342 goto err;
343 343
344 if (enable) 344 if (enable)
345 temp |= SMARTREFLEX_ENABLE; 345 temp |= SMARTREFLEX_ENABLE;
346 else 346 else
347 temp &= ~SMARTREFLEX_ENABLE; 347 temp &= ~SMARTREFLEX_ENABLE;
348 348
349 ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, temp, 349 ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, temp,
350 TWL4030_DCDC_GLOBAL_CFG); 350 TWL4030_DCDC_GLOBAL_CFG);
351 if (!ret) { 351 if (!ret) {
352 twl_sr_enable_autoinit = true; 352 twl_sr_enable_autoinit = true;
353 return 0; 353 return 0;
354 } 354 }
355 err: 355 err:
356 pr_err("%s: Error access to TWL4030 (%d)\n", __func__, ret); 356 pr_err("%s: Error access to TWL4030 (%d)\n", __func__, ret);
357 return ret; 357 return ret;
358 } 358 }
arch/arm/mach-omap2/opp.c
1 /* 1 /*
2 * OMAP SoC specific OPP wrapper function 2 * OMAP SoC specific OPP wrapper function
3 * 3 *
4 * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ 4 * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
5 * Nishanth Menon 5 * Nishanth Menon
6 * Kevin Hilman 6 * Kevin Hilman
7 * Copyright (C) 2010 Nokia Corporation. 7 * Copyright (C) 2010 Nokia Corporation.
8 * Eduardo Valentin 8 * Eduardo Valentin
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 * 13 *
14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
15 * kind, whether express or implied; without even the implied warranty 15 * kind, whether express or implied; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details. 17 * GNU General Public License for more details.
18 */ 18 */
19 #include <linux/module.h> 19 #include <linux/module.h>
20 #include <linux/opp.h> 20 #include <linux/opp.h>
21 21
22 #include <plat/omap_device.h> 22 #include <plat/omap_device.h>
23 #include <plat/dvfs.h>
23 24
24 #include "omap_opp_data.h" 25 #include "omap_opp_data.h"
25 #include "dvfs.h"
26 26
27 /* Temp variable to allow multiple calls */ 27 /* Temp variable to allow multiple calls */
28 static u8 __initdata omap_table_init; 28 static u8 __initdata omap_table_init;
29 29
30 /** 30 /**
31 * omap_init_opp_table() - Initialize opp table as per the CPU type 31 * omap_init_opp_table() - Initialize opp table as per the CPU type
32 * @opp_def: opp default list for this silicon 32 * @opp_def: opp default list for this silicon
33 * @opp_def_size: number of opp entries for this silicon 33 * @opp_def_size: number of opp entries for this silicon
34 * 34 *
35 * Register the initial OPP table with the OPP library based on the CPU 35 * Register the initial OPP table with the OPP library based on the CPU
36 * type. This is meant to be used only by SoC specific registration. 36 * type. This is meant to be used only by SoC specific registration.
37 */ 37 */
38 int __init omap_init_opp_table(struct omap_opp_def *opp_def, 38 int __init omap_init_opp_table(struct omap_opp_def *opp_def,
39 u32 opp_def_size) 39 u32 opp_def_size)
40 { 40 {
41 int i, r; 41 int i, r;
42 42
43 if (!opp_def || !opp_def_size) { 43 if (!opp_def || !opp_def_size) {
44 pr_err("%s: invalid params!\n", __func__); 44 pr_err("%s: invalid params!\n", __func__);
45 return -EINVAL; 45 return -EINVAL;
46 } 46 }
47 47
48 /* 48 /*
49 * Initialize only if not already initialized even if the previous 49 * Initialize only if not already initialized even if the previous
50 * call failed, because, no reason we'd succeed again. 50 * call failed, because, no reason we'd succeed again.
51 */ 51 */
52 if (omap_table_init) 52 if (omap_table_init)
53 return -EEXIST; 53 return -EEXIST;
54 omap_table_init = 1; 54 omap_table_init = 1;
55 55
56 /* Lets now register with OPP library */ 56 /* Lets now register with OPP library */
57 for (i = 0; i < opp_def_size; i++) { 57 for (i = 0; i < opp_def_size; i++) {
58 struct omap_hwmod *oh; 58 struct omap_hwmod *oh;
59 struct device *dev; 59 struct device *dev;
60 60
61 if (!opp_def->hwmod_name) { 61 if (!opp_def->hwmod_name) {
62 pr_err("%s: NULL name of omap_hwmod, failing [%d].\n", 62 pr_err("%s: NULL name of omap_hwmod, failing [%d].\n",
63 __func__, i); 63 __func__, i);
64 return -EINVAL; 64 return -EINVAL;
65 } 65 }
66 oh = omap_hwmod_lookup(opp_def->hwmod_name); 66 oh = omap_hwmod_lookup(opp_def->hwmod_name);
67 if (!oh || !oh->od) { 67 if (!oh || !oh->od) {
68 pr_warn("%s: no hwmod or odev for %s, [%d] " 68 pr_warn("%s: no hwmod or odev for %s, [%d] "
69 "cannot add OPPs.\n", __func__, 69 "cannot add OPPs.\n", __func__,
70 opp_def->hwmod_name, i); 70 opp_def->hwmod_name, i);
71 return -EINVAL; 71 return -EINVAL;
72 } 72 }
73 dev = &oh->od->pdev->dev; 73 dev = &oh->od->pdev->dev;
74 74
75 r = opp_add(dev, opp_def->freq, opp_def->u_volt); 75 r = opp_add(dev, opp_def->freq, opp_def->u_volt);
76 if (r) { 76 if (r) {
77 dev_err(dev, "%s: add OPP %ld failed for %s [%d] " 77 dev_err(dev, "%s: add OPP %ld failed for %s [%d] "
78 "result=%d\n", 78 "result=%d\n",
79 __func__, opp_def->freq, 79 __func__, opp_def->freq,
80 opp_def->hwmod_name, i, r); 80 opp_def->hwmod_name, i, r);
81 } else { 81 } else {
82 if (!opp_def->default_available) 82 if (!opp_def->default_available)
83 r = opp_disable(dev, opp_def->freq); 83 r = opp_disable(dev, opp_def->freq);
84 if (r) 84 if (r)
85 dev_err(dev, "%s: disable %ld failed for %s " 85 dev_err(dev, "%s: disable %ld failed for %s "
86 "[%d] result=%d\n", 86 "[%d] result=%d\n",
87 __func__, opp_def->freq, 87 __func__, opp_def->freq,
88 opp_def->hwmod_name, i, r); 88 opp_def->hwmod_name, i, r);
89 89
90 r = omap_dvfs_register_device(dev, 90 r = omap_dvfs_register_device(dev,
91 opp_def->voltdm_name, opp_def->clk_name); 91 opp_def->voltdm_name, opp_def->clk_name);
92 if (r) 92 if (r)
93 dev_err(dev, "%s:%s:err dvfs register %d %d\n", 93 dev_err(dev, "%s:%s:err dvfs register %d %d\n",
94 __func__, opp_def->hwmod_name, r, i); 94 __func__, opp_def->hwmod_name, r, i);
95 } 95 }
96 opp_def++; 96 opp_def++;
97 } 97 }
98 98
99 return 0; 99 return 0;
100 } 100 }
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 22
22 #include "voltage.h"
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) 29 static int _init_omap_device(char *name)
30 { 30 {
31 struct omap_hwmod *oh; 31 struct omap_hwmod *oh;
32 struct platform_device *pdev; 32 struct platform_device *pdev;
33 33
34 oh = omap_hwmod_lookup(name); 34 oh = omap_hwmod_lookup(name);
35 if (WARN(!oh, "%s: could not find omap_hwmod for %s\n", 35 if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
36 __func__, name)) 36 __func__, name))
37 return -ENODEV; 37 return -ENODEV;
38 38
39 pdev = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false); 39 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", 40 if (WARN(IS_ERR(pdev), "%s: could not build omap_device for %s\n",
41 __func__, name)) 41 __func__, name))
42 return -ENODEV; 42 return -ENODEV;
43 43
44 return 0; 44 return 0;
45 } 45 }
46 46
47 /* 47 /*
48 * Build omap_devices for processors and bus. 48 * Build omap_devices for processors and bus.
49 */ 49 */
50 static void omap2_init_processor_devices(void) 50 static void omap2_init_processor_devices(void)
51 { 51 {
52 _init_omap_device("mpu"); 52 _init_omap_device("mpu");
53 if (omap3_has_iva()) 53 if (omap3_has_iva())
54 _init_omap_device("iva"); 54 _init_omap_device("iva");
55 55
56 if (cpu_is_omap44xx()) { 56 if (cpu_is_omap44xx()) {
57 _init_omap_device("l3_main_1"); 57 _init_omap_device("l3_main_1");
58 _init_omap_device("dsp"); 58 _init_omap_device("dsp");
59 _init_omap_device("iva"); 59 _init_omap_device("iva");
60 } else { 60 } else {
61 _init_omap_device("l3_main"); 61 _init_omap_device("l3_main");
62 } 62 }
63 } 63 }
64 64
65 /* Types of sleep_switch used in omap_set_pwrdm_state */ 65 /* Types of sleep_switch used in omap_set_pwrdm_state */
66 #define FORCEWAKEUP_SWITCH 0 66 #define FORCEWAKEUP_SWITCH 0
67 #define LOWPOWERSTATE_SWITCH 1 67 #define LOWPOWERSTATE_SWITCH 1
68 68
69 /* 69 /*
70 * This sets pwrdm state (other than mpu & core. Currently only ON & 70 * This sets pwrdm state (other than mpu & core. Currently only ON &
71 * RET are supported. 71 * RET are supported.
72 */ 72 */
73 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) 73 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
74 { 74 {
75 u32 cur_state; 75 u32 cur_state;
76 int sleep_switch = -1; 76 int sleep_switch = -1;
77 int ret = 0; 77 int ret = 0;
78 int hwsup = 0; 78 int hwsup = 0;
79 79
80 if (pwrdm == NULL || IS_ERR(pwrdm)) 80 if (pwrdm == NULL || IS_ERR(pwrdm))
81 return -EINVAL; 81 return -EINVAL;
82 82
83 while (!(pwrdm->pwrsts & (1 << state))) { 83 while (!(pwrdm->pwrsts & (1 << state))) {
84 if (state == PWRDM_POWER_OFF) 84 if (state == PWRDM_POWER_OFF)
85 return ret; 85 return ret;
86 state--; 86 state--;
87 } 87 }
88 88
89 cur_state = pwrdm_read_next_pwrst(pwrdm); 89 cur_state = pwrdm_read_next_pwrst(pwrdm);
90 if (cur_state == state) 90 if (cur_state == state)
91 return ret; 91 return ret;
92 92
93 if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) { 93 if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
94 if ((pwrdm_read_pwrst(pwrdm) > state) && 94 if ((pwrdm_read_pwrst(pwrdm) > state) &&
95 (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { 95 (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
96 sleep_switch = LOWPOWERSTATE_SWITCH; 96 sleep_switch = LOWPOWERSTATE_SWITCH;
97 } else { 97 } else {
98 hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]); 98 hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
99 clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); 99 clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
100 sleep_switch = FORCEWAKEUP_SWITCH; 100 sleep_switch = FORCEWAKEUP_SWITCH;
101 } 101 }
102 } 102 }
103 103
104 ret = pwrdm_set_next_pwrst(pwrdm, state); 104 ret = pwrdm_set_next_pwrst(pwrdm, state);
105 if (ret) { 105 if (ret) {
106 pr_err("%s: unable to set state of powerdomain: %s\n", 106 pr_err("%s: unable to set state of powerdomain: %s\n",
107 __func__, pwrdm->name); 107 __func__, pwrdm->name);
108 goto err; 108 goto err;
109 } 109 }
110 110
111 switch (sleep_switch) { 111 switch (sleep_switch) {
112 case FORCEWAKEUP_SWITCH: 112 case FORCEWAKEUP_SWITCH:
113 if (hwsup) 113 if (hwsup)
114 clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); 114 clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
115 else 115 else
116 clkdm_sleep(pwrdm->pwrdm_clkdms[0]); 116 clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
117 break; 117 break;
118 case LOWPOWERSTATE_SWITCH: 118 case LOWPOWERSTATE_SWITCH:
119 pwrdm_set_lowpwrstchange(pwrdm); 119 pwrdm_set_lowpwrstchange(pwrdm);
120 break; 120 break;
121 default: 121 default:
122 return ret; 122 return ret;
123 } 123 }
124 124
125 pwrdm_state_switch(pwrdm); 125 pwrdm_state_switch(pwrdm);
126 err: 126 err:
127 return ret; 127 return ret;
128 } 128 }
129 129
130 /* 130 /*
131 * This API is to be called during init to set the various voltage 131 * 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 132 * 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 133 * at the nominal voltage. So this function finds out the rate of
134 * the clock associated with the voltage domain, finds out the correct 134 * the clock associated with the voltage domain, finds out the correct
135 * opp entry and sets the voltage domain to the voltage specified 135 * opp entry and sets the voltage domain to the voltage specified
136 * in the opp entry 136 * in the opp entry
137 */ 137 */
138 static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, 138 static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
139 const char *oh_name) 139 const char *oh_name)
140 { 140 {
141 struct voltagedomain *voltdm; 141 struct voltagedomain *voltdm;
142 struct clk *clk; 142 struct clk *clk;
143 struct opp *opp; 143 struct opp *opp;
144 struct device *dev; 144 struct device *dev;
145 unsigned long freq_cur, freq_valid, bootup_volt; 145 unsigned long freq_cur, freq_valid, bootup_volt;
146 int ret = -EINVAL; 146 int ret = -EINVAL;
147 147
148 dev = omap_device_get_by_hwmod_name(oh_name); 148 dev = omap_device_get_by_hwmod_name(oh_name);
149 if (IS_ERR(dev)) { 149 if (IS_ERR(dev)) {
150 pr_err("%s: Unable to get dev pointer for hwmod %s\n", 150 pr_err("%s: Unable to get dev pointer for hwmod %s\n",
151 __func__, oh_name); 151 __func__, oh_name);
152 goto exit; 152 goto exit;
153 } 153 }
154 154
155 voltdm = voltdm_lookup(vdd_name); 155 voltdm = voltdm_lookup(vdd_name);
156 if (IS_ERR(voltdm)) { 156 if (IS_ERR(voltdm)) {
157 pr_err("%s: unable to get vdd pointer for vdd_%s\n", 157 pr_err("%s: unable to get vdd pointer for vdd_%s\n",
158 __func__, vdd_name); 158 __func__, vdd_name);
159 goto exit; 159 goto exit;
160 } 160 }
161 161
162 clk = clk_get(NULL, clk_name); 162 clk = clk_get(NULL, clk_name);
163 if (IS_ERR(clk)) { 163 if (IS_ERR(clk)) {
164 pr_err("%s: unable to get clk %s\n", __func__, clk_name); 164 pr_err("%s: unable to get clk %s\n", __func__, clk_name);
165 goto exit; 165 goto exit;
166 } 166 }
167 167
168 freq_cur = clk->rate; 168 freq_cur = clk->rate;
169 freq_valid = freq_cur; 169 freq_valid = freq_cur;
170 170
171 rcu_read_lock(); 171 rcu_read_lock();
172 opp = opp_find_freq_ceil(dev, &freq_valid); 172 opp = opp_find_freq_ceil(dev, &freq_valid);
173 if (IS_ERR(opp)) { 173 if (IS_ERR(opp)) {
174 opp = opp_find_freq_floor(dev, &freq_valid); 174 opp = opp_find_freq_floor(dev, &freq_valid);
175 if (IS_ERR(opp)) { 175 if (IS_ERR(opp)) {
176 rcu_read_unlock(); 176 rcu_read_unlock();
177 pr_err("%s: no boot OPP match for %ld on vdd_%s\n", 177 pr_err("%s: no boot OPP match for %ld on vdd_%s\n",
178 __func__, freq_cur, vdd_name); 178 __func__, freq_cur, vdd_name);
179 ret = -ENOENT; 179 ret = -ENOENT;
180 goto exit_ck; 180 goto exit_ck;
181 } 181 }
182 } 182 }
183 183
184 bootup_volt = opp_get_voltage(opp); 184 bootup_volt = opp_get_voltage(opp);
185 rcu_read_unlock(); 185 rcu_read_unlock();
186 if (!bootup_volt) { 186 if (!bootup_volt) {
187 pr_err("%s: unable to find voltage corresponding " 187 pr_err("%s: unable to find voltage corresponding "
188 "to the bootup OPP for vdd_%s\n", __func__, vdd_name); 188 "to the bootup OPP for vdd_%s\n", __func__, vdd_name);
189 ret = -ENOENT; 189 ret = -ENOENT;
190 goto exit_ck; 190 goto exit_ck;
191 } 191 }
192 192
193 /* 193 /*
194 * Frequency and Voltage have to be sequenced: if we move from 194 * Frequency and Voltage have to be sequenced: if we move from
195 * a lower frequency to higher frequency, raise voltage, followed by 195 * a lower frequency to higher frequency, raise voltage, followed by
196 * frequency, and vice versa. we assume that the voltage at boot 196 * frequency, and vice versa. we assume that the voltage at boot
197 * is the required voltage for the frequency it was set for. 197 * is the required voltage for the frequency it was set for.
198 * NOTE: 198 * NOTE:
199 * we can check the frequency, but there is numerous ways to set 199 * we can check the frequency, but there is numerous ways to set
200 * voltage. We play the safe path and just set the voltage. 200 * voltage. We play the safe path and just set the voltage.
201 */ 201 */
202 202
203 if (freq_cur < freq_valid) { 203 if (freq_cur < freq_valid) {
204 ret = voltdm_scale(voltdm, bootup_volt); 204 ret = voltdm_scale(voltdm, bootup_volt);
205 if (ret) { 205 if (ret) {
206 pr_err("%s: Fail set voltage-%s(f=%ld v=%ld)on vdd%s\n", 206 pr_err("%s: Fail set voltage-%s(f=%ld v=%ld)on vdd%s\n",
207 __func__, vdd_name, freq_valid, 207 __func__, vdd_name, freq_valid,
208 bootup_volt, vdd_name); 208 bootup_volt, vdd_name);
209 goto exit_ck; 209 goto exit_ck;
210 } 210 }
211 } 211 }
212 212
213 /* Set freq only if there is a difference in freq */ 213 /* Set freq only if there is a difference in freq */
214 if (freq_valid != freq_cur) { 214 if (freq_valid != freq_cur) {
215 ret = clk_set_rate(clk, freq_valid); 215 ret = clk_set_rate(clk, freq_valid);
216 if (ret) { 216 if (ret) {
217 pr_err("%s: Fail set clk-%s(f=%ld v=%ld)on vdd%s\n", 217 pr_err("%s: Fail set clk-%s(f=%ld v=%ld)on vdd%s\n",
218 __func__, clk_name, freq_valid, 218 __func__, clk_name, freq_valid,
219 bootup_volt, vdd_name); 219 bootup_volt, vdd_name);
220 goto exit_ck; 220 goto exit_ck;
221 } 221 }
222 } 222 }
223 223
224 if (freq_cur >= freq_valid) { 224 if (freq_cur >= freq_valid) {
225 ret = voltdm_scale(voltdm, bootup_volt); 225 ret = voltdm_scale(voltdm, bootup_volt);
226 if (ret) { 226 if (ret) {
227 pr_err("%s: Fail set voltage-%s(f=%ld v=%ld)on vdd%s\n", 227 pr_err("%s: Fail set voltage-%s(f=%ld v=%ld)on vdd%s\n",
228 __func__, clk_name, freq_valid, 228 __func__, clk_name, freq_valid,
229 bootup_volt, vdd_name); 229 bootup_volt, vdd_name);
230 goto exit_ck; 230 goto exit_ck;
231 } 231 }
232 } 232 }
233 233
234 ret = 0; 234 ret = 0;
235 exit_ck: 235 exit_ck:
236 clk_put(clk); 236 clk_put(clk);
237 237
238 if (!ret) 238 if (!ret)
239 return 0; 239 return 0;
240 240
241 exit: 241 exit:
242 pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name); 242 pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name);
243 return -EINVAL; 243 return -EINVAL;
244 } 244 }
245 245
246 static void __init omap3_init_voltages(void) 246 static void __init omap3_init_voltages(void)
247 { 247 {
248 if (!cpu_is_omap34xx()) 248 if (!cpu_is_omap34xx())
249 return; 249 return;
250 250
251 omap2_set_init_voltage("mpu_iva", "dpll1_ck", "mpu"); 251 omap2_set_init_voltage("mpu_iva", "dpll1_ck", "mpu");
252 omap2_set_init_voltage("core", "l3_ick", "l3_main"); 252 omap2_set_init_voltage("core", "l3_ick", "l3_main");
253 } 253 }
254 254
255 static void __init omap4_init_voltages(void) 255 static void __init omap4_init_voltages(void)
256 { 256 {
257 if (!cpu_is_omap44xx()) 257 if (!cpu_is_omap44xx())
258 return; 258 return;
259 259
260 omap2_set_init_voltage("mpu", "dpll_mpu_ck", "mpu"); 260 omap2_set_init_voltage("mpu", "dpll_mpu_ck", "mpu");
261 omap2_set_init_voltage("core", "l3_div_ck", "l3_main_1"); 261 omap2_set_init_voltage("core", "l3_div_ck", "l3_main_1");
262 omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva"); 262 omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva");
263 } 263 }
264 264
265 static int __init omap2_common_pm_init(void) 265 static int __init omap2_common_pm_init(void)
266 { 266 {
267 if (!of_have_populated_dt()) 267 if (!of_have_populated_dt())
268 omap2_init_processor_devices(); 268 omap2_init_processor_devices();
269 omap_pm_if_init(); 269 omap_pm_if_init();
270 270
271 return 0; 271 return 0;
272 } 272 }
273 postcore_initcall(omap2_common_pm_init); 273 postcore_initcall(omap2_common_pm_init);
274 274
275 static int __init omap2_common_pm_late_init(void) 275 static int __init omap2_common_pm_late_init(void)
276 { 276 {
277 /* Init the OMAP TWL parameters */ 277 /* Init the OMAP TWL parameters */
278 omap3_twl_init(); 278 omap3_twl_init();
279 omap4_twl_init(); 279 omap4_twl_init();
280 280
281 /* Init the voltage layer */ 281 /* Init the voltage layer */
282 omap_voltage_late_init(); 282 omap_voltage_late_init();
283 283
284 /* Initialize the voltages */ 284 /* Initialize the voltages */
285 omap3_init_voltages(); 285 omap3_init_voltages();
286 omap4_init_voltages(); 286 omap4_init_voltages();
287 287
288 /* Smartreflex device init */ 288 /* Smartreflex device init */
289 omap_devinit_smartreflex(); 289 omap_devinit_smartreflex();
290 290
291 return 0; 291 return 0;
292 } 292 }
293 late_initcall(omap2_common_pm_late_init); 293 late_initcall(omap2_common_pm_late_init);
arch/arm/mach-omap2/powerdomain.h
1 /* 1 /*
2 * OMAP2/3/4 powerdomain control 2 * OMAP2/3/4 powerdomain control
3 * 3 *
4 * Copyright (C) 2007-2008, 2010 Texas Instruments, Inc. 4 * Copyright (C) 2007-2008, 2010 Texas Instruments, Inc.
5 * Copyright (C) 2007-2011 Nokia Corporation 5 * Copyright (C) 2007-2011 Nokia Corporation
6 * 6 *
7 * Paul Walmsley 7 * Paul Walmsley
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 * XXX This should be moved to the mach-omap2/ directory at the earliest 13 * XXX This should be moved to the mach-omap2/ directory at the earliest
14 * opportunity. 14 * opportunity.
15 */ 15 */
16 16
17 #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H 17 #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
18 #define __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H 18 #define __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
19 19
20 #include <linux/types.h> 20 #include <linux/types.h>
21 #include <linux/list.h> 21 #include <linux/list.h>
22 22
23 #include <linux/atomic.h> 23 #include <linux/atomic.h>
24 24
25 #include <plat/cpu.h> 25 #include <plat/cpu.h>
26 #include <plat/voltage.h>
26 27
27 #include "voltage.h"
28 28
29 /* Powerdomain basic power states */ 29 /* Powerdomain basic power states */
30 #define PWRDM_POWER_OFF 0x0 30 #define PWRDM_POWER_OFF 0x0
31 #define PWRDM_POWER_RET 0x1 31 #define PWRDM_POWER_RET 0x1
32 #define PWRDM_POWER_INACTIVE 0x2 32 #define PWRDM_POWER_INACTIVE 0x2
33 #define PWRDM_POWER_ON 0x3 33 #define PWRDM_POWER_ON 0x3
34 34
35 #define PWRDM_MAX_PWRSTS 4 35 #define PWRDM_MAX_PWRSTS 4
36 36
37 /* Powerdomain allowable state bitfields */ 37 /* Powerdomain allowable state bitfields */
38 #define PWRSTS_ON (1 << PWRDM_POWER_ON) 38 #define PWRSTS_ON (1 << PWRDM_POWER_ON)
39 #define PWRSTS_INACTIVE (1 << PWRDM_POWER_INACTIVE) 39 #define PWRSTS_INACTIVE (1 << PWRDM_POWER_INACTIVE)
40 #define PWRSTS_RET (1 << PWRDM_POWER_RET) 40 #define PWRSTS_RET (1 << PWRDM_POWER_RET)
41 #define PWRSTS_OFF (1 << PWRDM_POWER_OFF) 41 #define PWRSTS_OFF (1 << PWRDM_POWER_OFF)
42 42
43 #define PWRSTS_OFF_ON (PWRSTS_OFF | PWRSTS_ON) 43 #define PWRSTS_OFF_ON (PWRSTS_OFF | PWRSTS_ON)
44 #define PWRSTS_OFF_RET (PWRSTS_OFF | PWRSTS_RET) 44 #define PWRSTS_OFF_RET (PWRSTS_OFF | PWRSTS_RET)
45 #define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON) 45 #define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON)
46 #define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | PWRSTS_ON) 46 #define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | PWRSTS_ON)
47 47
48 48
49 /* Powerdomain flags */ 49 /* Powerdomain flags */
50 #define PWRDM_HAS_HDWR_SAR (1 << 0) /* hardware save-and-restore support */ 50 #define PWRDM_HAS_HDWR_SAR (1 << 0) /* hardware save-and-restore support */
51 #define PWRDM_HAS_MPU_QUIRK (1 << 1) /* MPU pwr domain has MEM bank 0 bits 51 #define PWRDM_HAS_MPU_QUIRK (1 << 1) /* MPU pwr domain has MEM bank 0 bits
52 * in MEM bank 1 position. This is 52 * in MEM bank 1 position. This is
53 * true for OMAP3430 53 * true for OMAP3430
54 */ 54 */
55 #define PWRDM_HAS_LOWPOWERSTATECHANGE (1 << 2) /* 55 #define PWRDM_HAS_LOWPOWERSTATECHANGE (1 << 2) /*
56 * support to transition from a 56 * support to transition from a
57 * sleep state to a lower sleep 57 * sleep state to a lower sleep
58 * state without waking up the 58 * state without waking up the
59 * powerdomain 59 * powerdomain
60 */ 60 */
61 61
62 /* 62 /*
63 * Number of memory banks that are power-controllable. On OMAP4430, the 63 * Number of memory banks that are power-controllable. On OMAP4430, the
64 * maximum is 5. 64 * maximum is 5.
65 */ 65 */
66 #define PWRDM_MAX_MEM_BANKS 5 66 #define PWRDM_MAX_MEM_BANKS 5
67 67
68 /* 68 /*
69 * Maximum number of clockdomains that can be associated with a powerdomain. 69 * Maximum number of clockdomains that can be associated with a powerdomain.
70 * CORE powerdomain on OMAP4 is the worst case 70 * CORE powerdomain on OMAP4 is the worst case
71 */ 71 */
72 #define PWRDM_MAX_CLKDMS 11 72 #define PWRDM_MAX_CLKDMS 11
73 73
74 /* XXX A completely arbitrary number. What is reasonable here? */ 74 /* XXX A completely arbitrary number. What is reasonable here? */
75 #define PWRDM_TRANSITION_BAILOUT 100000 75 #define PWRDM_TRANSITION_BAILOUT 100000
76 76
77 struct clockdomain; 77 struct clockdomain;
78 struct powerdomain; 78 struct powerdomain;
79 79
80 /** 80 /**
81 * struct powerdomain - OMAP powerdomain 81 * struct powerdomain - OMAP powerdomain
82 * @name: Powerdomain name 82 * @name: Powerdomain name
83 * @voltdm: voltagedomain containing this powerdomain 83 * @voltdm: voltagedomain containing this powerdomain
84 * @prcm_offs: the address offset from CM_BASE/PRM_BASE 84 * @prcm_offs: the address offset from CM_BASE/PRM_BASE
85 * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs 85 * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs
86 * @pwrsts: Possible powerdomain power states 86 * @pwrsts: Possible powerdomain power states
87 * @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION 87 * @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION
88 * @flags: Powerdomain flags 88 * @flags: Powerdomain flags
89 * @banks: Number of software-controllable memory banks in this powerdomain 89 * @banks: Number of software-controllable memory banks in this powerdomain
90 * @pwrsts_mem_ret: Possible memory bank pwrstates when pwrdm in RETENTION 90 * @pwrsts_mem_ret: Possible memory bank pwrstates when pwrdm in RETENTION
91 * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON 91 * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
92 * @pwrdm_clkdms: Clockdomains in this powerdomain 92 * @pwrdm_clkdms: Clockdomains in this powerdomain
93 * @node: list_head linking all powerdomains 93 * @node: list_head linking all powerdomains
94 * @voltdm_node: list_head linking all powerdomains in a voltagedomain 94 * @voltdm_node: list_head linking all powerdomains in a voltagedomain
95 * @state: 95 * @state:
96 * @state_counter: 96 * @state_counter:
97 * @timer: 97 * @timer:
98 * @state_timer: 98 * @state_timer:
99 * 99 *
100 * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h. 100 * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
101 */ 101 */
102 struct powerdomain { 102 struct powerdomain {
103 const char *name; 103 const char *name;
104 union { 104 union {
105 const char *name; 105 const char *name;
106 struct voltagedomain *ptr; 106 struct voltagedomain *ptr;
107 } voltdm; 107 } voltdm;
108 const s16 prcm_offs; 108 const s16 prcm_offs;
109 const u8 pwrsts; 109 const u8 pwrsts;
110 const u8 pwrsts_logic_ret; 110 const u8 pwrsts_logic_ret;
111 const u8 flags; 111 const u8 flags;
112 const u8 banks; 112 const u8 banks;
113 const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS]; 113 const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS];
114 const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS]; 114 const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
115 const u8 prcm_partition; 115 const u8 prcm_partition;
116 struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS]; 116 struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
117 struct list_head node; 117 struct list_head node;
118 struct list_head voltdm_node; 118 struct list_head voltdm_node;
119 int state; 119 int state;
120 unsigned state_counter[PWRDM_MAX_PWRSTS]; 120 unsigned state_counter[PWRDM_MAX_PWRSTS];
121 unsigned ret_logic_off_counter; 121 unsigned ret_logic_off_counter;
122 unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS]; 122 unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
123 123
124 #ifdef CONFIG_PM_DEBUG 124 #ifdef CONFIG_PM_DEBUG
125 s64 timer; 125 s64 timer;
126 s64 state_timer[PWRDM_MAX_PWRSTS]; 126 s64 state_timer[PWRDM_MAX_PWRSTS];
127 #endif 127 #endif
128 }; 128 };
129 129
130 /** 130 /**
131 * struct pwrdm_ops - Arch specific function implementations 131 * struct pwrdm_ops - Arch specific function implementations
132 * @pwrdm_set_next_pwrst: Set the target power state for a pd 132 * @pwrdm_set_next_pwrst: Set the target power state for a pd
133 * @pwrdm_read_next_pwrst: Read the target power state set for a pd 133 * @pwrdm_read_next_pwrst: Read the target power state set for a pd
134 * @pwrdm_read_pwrst: Read the current power state of a pd 134 * @pwrdm_read_pwrst: Read the current power state of a pd
135 * @pwrdm_read_prev_pwrst: Read the prev power state entered by the pd 135 * @pwrdm_read_prev_pwrst: Read the prev power state entered by the pd
136 * @pwrdm_set_logic_retst: Set the logic state in RET for a pd 136 * @pwrdm_set_logic_retst: Set the logic state in RET for a pd
137 * @pwrdm_set_mem_onst: Set the Memory state in ON for a pd 137 * @pwrdm_set_mem_onst: Set the Memory state in ON for a pd
138 * @pwrdm_set_mem_retst: Set the Memory state in RET for a pd 138 * @pwrdm_set_mem_retst: Set the Memory state in RET for a pd
139 * @pwrdm_read_logic_pwrst: Read the current logic state of a pd 139 * @pwrdm_read_logic_pwrst: Read the current logic state of a pd
140 * @pwrdm_read_prev_logic_pwrst: Read the previous logic state entered by a pd 140 * @pwrdm_read_prev_logic_pwrst: Read the previous logic state entered by a pd
141 * @pwrdm_read_logic_retst: Read the logic state in RET for a pd 141 * @pwrdm_read_logic_retst: Read the logic state in RET for a pd
142 * @pwrdm_read_mem_pwrst: Read the current memory state of a pd 142 * @pwrdm_read_mem_pwrst: Read the current memory state of a pd
143 * @pwrdm_read_prev_mem_pwrst: Read the previous memory state entered by a pd 143 * @pwrdm_read_prev_mem_pwrst: Read the previous memory state entered by a pd
144 * @pwrdm_read_mem_retst: Read the memory state in RET for a pd 144 * @pwrdm_read_mem_retst: Read the memory state in RET for a pd
145 * @pwrdm_clear_all_prev_pwrst: Clear all previous power states logged for a pd 145 * @pwrdm_clear_all_prev_pwrst: Clear all previous power states logged for a pd
146 * @pwrdm_enable_hdwr_sar: Enable Hardware Save-Restore feature for the pd 146 * @pwrdm_enable_hdwr_sar: Enable Hardware Save-Restore feature for the pd
147 * @pwrdm_disable_hdwr_sar: Disable Hardware Save-Restore feature for a pd 147 * @pwrdm_disable_hdwr_sar: Disable Hardware Save-Restore feature for a pd
148 * @pwrdm_set_lowpwrstchange: Enable pd transitions from a shallow to deep sleep 148 * @pwrdm_set_lowpwrstchange: Enable pd transitions from a shallow to deep sleep
149 * @pwrdm_wait_transition: Wait for a pd state transition to complete 149 * @pwrdm_wait_transition: Wait for a pd state transition to complete
150 */ 150 */
151 struct pwrdm_ops { 151 struct pwrdm_ops {
152 int (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst); 152 int (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
153 int (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm); 153 int (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
154 int (*pwrdm_read_pwrst)(struct powerdomain *pwrdm); 154 int (*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
155 int (*pwrdm_read_prev_pwrst)(struct powerdomain *pwrdm); 155 int (*pwrdm_read_prev_pwrst)(struct powerdomain *pwrdm);
156 int (*pwrdm_set_logic_retst)(struct powerdomain *pwrdm, u8 pwrst); 156 int (*pwrdm_set_logic_retst)(struct powerdomain *pwrdm, u8 pwrst);
157 int (*pwrdm_set_mem_onst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst); 157 int (*pwrdm_set_mem_onst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
158 int (*pwrdm_set_mem_retst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst); 158 int (*pwrdm_set_mem_retst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
159 int (*pwrdm_read_logic_pwrst)(struct powerdomain *pwrdm); 159 int (*pwrdm_read_logic_pwrst)(struct powerdomain *pwrdm);
160 int (*pwrdm_read_prev_logic_pwrst)(struct powerdomain *pwrdm); 160 int (*pwrdm_read_prev_logic_pwrst)(struct powerdomain *pwrdm);
161 int (*pwrdm_read_logic_retst)(struct powerdomain *pwrdm); 161 int (*pwrdm_read_logic_retst)(struct powerdomain *pwrdm);
162 int (*pwrdm_read_mem_pwrst)(struct powerdomain *pwrdm, u8 bank); 162 int (*pwrdm_read_mem_pwrst)(struct powerdomain *pwrdm, u8 bank);
163 int (*pwrdm_read_prev_mem_pwrst)(struct powerdomain *pwrdm, u8 bank); 163 int (*pwrdm_read_prev_mem_pwrst)(struct powerdomain *pwrdm, u8 bank);
164 int (*pwrdm_read_mem_retst)(struct powerdomain *pwrdm, u8 bank); 164 int (*pwrdm_read_mem_retst)(struct powerdomain *pwrdm, u8 bank);
165 int (*pwrdm_clear_all_prev_pwrst)(struct powerdomain *pwrdm); 165 int (*pwrdm_clear_all_prev_pwrst)(struct powerdomain *pwrdm);
166 int (*pwrdm_enable_hdwr_sar)(struct powerdomain *pwrdm); 166 int (*pwrdm_enable_hdwr_sar)(struct powerdomain *pwrdm);
167 int (*pwrdm_disable_hdwr_sar)(struct powerdomain *pwrdm); 167 int (*pwrdm_disable_hdwr_sar)(struct powerdomain *pwrdm);
168 int (*pwrdm_set_lowpwrstchange)(struct powerdomain *pwrdm); 168 int (*pwrdm_set_lowpwrstchange)(struct powerdomain *pwrdm);
169 int (*pwrdm_wait_transition)(struct powerdomain *pwrdm); 169 int (*pwrdm_wait_transition)(struct powerdomain *pwrdm);
170 }; 170 };
171 171
172 int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs); 172 int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
173 int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list); 173 int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
174 int pwrdm_complete_init(void); 174 int pwrdm_complete_init(void);
175 175
176 struct powerdomain *pwrdm_lookup(const char *name); 176 struct powerdomain *pwrdm_lookup(const char *name);
177 177
178 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), 178 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
179 void *user); 179 void *user);
180 int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user), 180 int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
181 void *user); 181 void *user);
182 182
183 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); 183 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
184 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); 184 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
185 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, 185 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
186 int (*fn)(struct powerdomain *pwrdm, 186 int (*fn)(struct powerdomain *pwrdm,
187 struct clockdomain *clkdm)); 187 struct clockdomain *clkdm));
188 struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm); 188 struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
189 189
190 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm); 190 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
191 191
192 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst); 192 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
193 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm); 193 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
194 int pwrdm_read_pwrst(struct powerdomain *pwrdm); 194 int pwrdm_read_pwrst(struct powerdomain *pwrdm);
195 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm); 195 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
196 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm); 196 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
197 197
198 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst); 198 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
199 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst); 199 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
200 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst); 200 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
201 201
202 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm); 202 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm);
203 int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm); 203 int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm);
204 int pwrdm_read_logic_retst(struct powerdomain *pwrdm); 204 int pwrdm_read_logic_retst(struct powerdomain *pwrdm);
205 int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank); 205 int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
206 int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank); 206 int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
207 int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank); 207 int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank);
208 208
209 int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm); 209 int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm);
210 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm); 210 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
211 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm); 211 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
212 212
213 int pwrdm_wait_transition(struct powerdomain *pwrdm); 213 int pwrdm_wait_transition(struct powerdomain *pwrdm);
214 214
215 int pwrdm_state_switch(struct powerdomain *pwrdm); 215 int pwrdm_state_switch(struct powerdomain *pwrdm);
216 int pwrdm_clkdm_state_switch(struct clockdomain *clkdm); 216 int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
217 int pwrdm_pre_transition(void); 217 int pwrdm_pre_transition(void);
218 int pwrdm_post_transition(void); 218 int pwrdm_post_transition(void);
219 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); 219 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
220 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); 220 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
221 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); 221 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
222 222
223 extern void omap242x_powerdomains_init(void); 223 extern void omap242x_powerdomains_init(void);
224 extern void omap243x_powerdomains_init(void); 224 extern void omap243x_powerdomains_init(void);
225 extern void omap3xxx_powerdomains_init(void); 225 extern void omap3xxx_powerdomains_init(void);
226 extern void am33xx_powerdomains_init(void); 226 extern void am33xx_powerdomains_init(void);
227 extern void omap44xx_powerdomains_init(void); 227 extern void omap44xx_powerdomains_init(void);
228 228
229 extern struct pwrdm_ops omap2_pwrdm_operations; 229 extern struct pwrdm_ops omap2_pwrdm_operations;
230 extern struct pwrdm_ops omap3_pwrdm_operations; 230 extern struct pwrdm_ops omap3_pwrdm_operations;
231 extern struct pwrdm_ops am33xx_pwrdm_operations; 231 extern struct pwrdm_ops am33xx_pwrdm_operations;
232 extern struct pwrdm_ops omap4_pwrdm_operations; 232 extern struct pwrdm_ops omap4_pwrdm_operations;
233 233
234 /* Common Internal functions used across OMAP rev's */ 234 /* Common Internal functions used across OMAP rev's */
235 extern u32 omap2_pwrdm_get_mem_bank_onstate_mask(u8 bank); 235 extern u32 omap2_pwrdm_get_mem_bank_onstate_mask(u8 bank);
236 extern u32 omap2_pwrdm_get_mem_bank_retst_mask(u8 bank); 236 extern u32 omap2_pwrdm_get_mem_bank_retst_mask(u8 bank);
237 extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank); 237 extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank);
238 238
239 extern struct powerdomain wkup_omap2_pwrdm; 239 extern struct powerdomain wkup_omap2_pwrdm;
240 extern struct powerdomain gfx_omap2_pwrdm; 240 extern struct powerdomain gfx_omap2_pwrdm;
241 241
242 242
243 #endif 243 #endif
arch/arm/mach-omap2/prm2xxx_3xxx.c
1 /* 1 /*
2 * OMAP2/3 PRM module functions 2 * OMAP2/3 PRM module functions
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 * Benoรฎt Cousson 6 * Benoรฎt Cousson
7 * Paul Walmsley 7 * Paul Walmsley
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/kernel.h> 14 #include <linux/kernel.h>
15 #include <linux/errno.h> 15 #include <linux/errno.h>
16 #include <linux/err.h> 16 #include <linux/err.h>
17 #include <linux/io.h> 17 #include <linux/io.h>
18 18
19 #include <plat/common.h> 19 #include <plat/common.h>
20 #include <plat/cpu.h> 20 #include <plat/cpu.h>
21 #include <plat/prcm.h> 21 #include <plat/prcm.h>
22 22 #include <plat/vp.h>
23 #include "vp.h"
24 23
25 #include "prm2xxx_3xxx.h" 24 #include "prm2xxx_3xxx.h"
26 #include "cm2xxx_3xxx.h" 25 #include "cm2xxx_3xxx.h"
27 #include "prm-regbits-24xx.h" 26 #include "prm-regbits-24xx.h"
28 #include "prm-regbits-34xx.h" 27 #include "prm-regbits-34xx.h"
29 28
30 u32 omap2_prm_read_mod_reg(s16 module, u16 idx) 29 u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
31 { 30 {
32 return __raw_readl(prm_base + module + idx); 31 return __raw_readl(prm_base + module + idx);
33 } 32 }
34 33
35 void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx) 34 void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
36 { 35 {
37 __raw_writel(val, prm_base + module + idx); 36 __raw_writel(val, prm_base + module + idx);
38 } 37 }
39 38
40 /* Read-modify-write a register in a PRM module. Caller must lock */ 39 /* Read-modify-write a register in a PRM module. Caller must lock */
41 u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx) 40 u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
42 { 41 {
43 u32 v; 42 u32 v;
44 43
45 v = omap2_prm_read_mod_reg(module, idx); 44 v = omap2_prm_read_mod_reg(module, idx);
46 v &= ~mask; 45 v &= ~mask;
47 v |= bits; 46 v |= bits;
48 omap2_prm_write_mod_reg(v, module, idx); 47 omap2_prm_write_mod_reg(v, module, idx);
49 48
50 return v; 49 return v;
51 } 50 }
52 51
53 /* Read a PRM register, AND it, and shift the result down to bit 0 */ 52 /* Read a PRM register, AND it, and shift the result down to bit 0 */
54 u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask) 53 u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
55 { 54 {
56 u32 v; 55 u32 v;
57 56
58 v = omap2_prm_read_mod_reg(domain, idx); 57 v = omap2_prm_read_mod_reg(domain, idx);
59 v &= mask; 58 v &= mask;
60 v >>= __ffs(mask); 59 v >>= __ffs(mask);
61 60
62 return v; 61 return v;
63 } 62 }
64 63
65 u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx) 64 u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
66 { 65 {
67 return omap2_prm_rmw_mod_reg_bits(bits, bits, module, idx); 66 return omap2_prm_rmw_mod_reg_bits(bits, bits, module, idx);
68 } 67 }
69 68
70 u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx) 69 u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
71 { 70 {
72 return omap2_prm_rmw_mod_reg_bits(bits, 0x0, module, idx); 71 return omap2_prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
73 } 72 }
74 73
75 74
76 /** 75 /**
77 * omap2_prm_is_hardreset_asserted - read the HW reset line state of 76 * omap2_prm_is_hardreset_asserted - read the HW reset line state of
78 * submodules contained in the hwmod module 77 * submodules contained in the hwmod module
79 * @prm_mod: PRM submodule base (e.g. CORE_MOD) 78 * @prm_mod: PRM submodule base (e.g. CORE_MOD)
80 * @shift: register bit shift corresponding to the reset line to check 79 * @shift: register bit shift corresponding to the reset line to check
81 * 80 *
82 * Returns 1 if the (sub)module hardreset line is currently asserted, 81 * Returns 1 if the (sub)module hardreset line is currently asserted,
83 * 0 if the (sub)module hardreset line is not currently asserted, or 82 * 0 if the (sub)module hardreset line is not currently asserted, or
84 * -EINVAL if called while running on a non-OMAP2/3 chip. 83 * -EINVAL if called while running on a non-OMAP2/3 chip.
85 */ 84 */
86 int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift) 85 int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
87 { 86 {
88 if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) 87 if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
89 return -EINVAL; 88 return -EINVAL;
90 89
91 return omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, 90 return omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
92 (1 << shift)); 91 (1 << shift));
93 } 92 }
94 93
95 /** 94 /**
96 * omap2_prm_assert_hardreset - assert the HW reset line of a submodule 95 * omap2_prm_assert_hardreset - assert the HW reset line of a submodule
97 * @prm_mod: PRM submodule base (e.g. CORE_MOD) 96 * @prm_mod: PRM submodule base (e.g. CORE_MOD)
98 * @shift: register bit shift corresponding to the reset line to assert 97 * @shift: register bit shift corresponding to the reset line to assert
99 * 98 *
100 * Some IPs like dsp or iva contain processors that require an HW 99 * Some IPs like dsp or iva contain processors that require an HW
101 * reset line to be asserted / deasserted in order to fully enable the 100 * reset line to be asserted / deasserted in order to fully enable the
102 * IP. These modules may have multiple hard-reset lines that reset 101 * IP. These modules may have multiple hard-reset lines that reset
103 * different 'submodules' inside the IP block. This function will 102 * different 'submodules' inside the IP block. This function will
104 * place the submodule into reset. Returns 0 upon success or -EINVAL 103 * place the submodule into reset. Returns 0 upon success or -EINVAL
105 * upon an argument error. 104 * upon an argument error.
106 */ 105 */
107 int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift) 106 int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
108 { 107 {
109 u32 mask; 108 u32 mask;
110 109
111 if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) 110 if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
112 return -EINVAL; 111 return -EINVAL;
113 112
114 mask = 1 << shift; 113 mask = 1 << shift;
115 omap2_prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL); 114 omap2_prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
116 115
117 return 0; 116 return 0;
118 } 117 }
119 118
120 /** 119 /**
121 * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait 120 * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait
122 * @prm_mod: PRM submodule base (e.g. CORE_MOD) 121 * @prm_mod: PRM submodule base (e.g. CORE_MOD)
123 * @rst_shift: register bit shift corresponding to the reset line to deassert 122 * @rst_shift: register bit shift corresponding to the reset line to deassert
124 * @st_shift: register bit shift for the status of the deasserted submodule 123 * @st_shift: register bit shift for the status of the deasserted submodule
125 * 124 *
126 * Some IPs like dsp or iva contain processors that require an HW 125 * Some IPs like dsp or iva contain processors that require an HW
127 * reset line to be asserted / deasserted in order to fully enable the 126 * reset line to be asserted / deasserted in order to fully enable the
128 * IP. These modules may have multiple hard-reset lines that reset 127 * IP. These modules may have multiple hard-reset lines that reset
129 * different 'submodules' inside the IP block. This function will 128 * different 'submodules' inside the IP block. This function will
130 * take the submodule out of reset and wait until the PRCM indicates 129 * take the submodule out of reset and wait until the PRCM indicates
131 * that the reset has completed before returning. Returns 0 upon success or 130 * that the reset has completed before returning. Returns 0 upon success or
132 * -EINVAL upon an argument error, -EEXIST if the submodule was already out 131 * -EINVAL upon an argument error, -EEXIST if the submodule was already out
133 * of reset, or -EBUSY if the submodule did not exit reset promptly. 132 * of reset, or -EBUSY if the submodule did not exit reset promptly.
134 */ 133 */
135 int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift) 134 int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
136 { 135 {
137 u32 rst, st; 136 u32 rst, st;
138 int c; 137 int c;
139 138
140 if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) 139 if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
141 return -EINVAL; 140 return -EINVAL;
142 141
143 rst = 1 << rst_shift; 142 rst = 1 << rst_shift;
144 st = 1 << st_shift; 143 st = 1 << st_shift;
145 144
146 /* Check the current status to avoid de-asserting the line twice */ 145 /* Check the current status to avoid de-asserting the line twice */
147 if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, rst) == 0) 146 if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, rst) == 0)
148 return -EEXIST; 147 return -EEXIST;
149 148
150 /* Clear the reset status by writing 1 to the status bit */ 149 /* Clear the reset status by writing 1 to the status bit */
151 omap2_prm_rmw_mod_reg_bits(0xffffffff, st, prm_mod, OMAP2_RM_RSTST); 150 omap2_prm_rmw_mod_reg_bits(0xffffffff, st, prm_mod, OMAP2_RM_RSTST);
152 /* de-assert the reset control line */ 151 /* de-assert the reset control line */
153 omap2_prm_rmw_mod_reg_bits(rst, 0, prm_mod, OMAP2_RM_RSTCTRL); 152 omap2_prm_rmw_mod_reg_bits(rst, 0, prm_mod, OMAP2_RM_RSTCTRL);
154 /* wait the status to be set */ 153 /* wait the status to be set */
155 omap_test_timeout(omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST, 154 omap_test_timeout(omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
156 st), 155 st),
157 MAX_MODULE_HARDRESET_WAIT, c); 156 MAX_MODULE_HARDRESET_WAIT, c);
158 157
159 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; 158 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
160 } 159 }
161 160
162 /* PRM VP */ 161 /* PRM VP */
163 162
164 /* 163 /*
165 * struct omap3_vp - OMAP3 VP register access description. 164 * struct omap3_vp - OMAP3 VP register access description.
166 * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg 165 * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
167 */ 166 */
168 struct omap3_vp { 167 struct omap3_vp {
169 u32 tranxdone_status; 168 u32 tranxdone_status;
170 }; 169 };
171 170
172 static struct omap3_vp omap3_vp[] = { 171 static struct omap3_vp omap3_vp[] = {
173 [OMAP3_VP_VDD_MPU_ID] = { 172 [OMAP3_VP_VDD_MPU_ID] = {
174 .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK, 173 .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
175 }, 174 },
176 [OMAP3_VP_VDD_CORE_ID] = { 175 [OMAP3_VP_VDD_CORE_ID] = {
177 .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK, 176 .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
178 }, 177 },
179 }; 178 };
180 179
181 #define MAX_VP_ID ARRAY_SIZE(omap3_vp); 180 #define MAX_VP_ID ARRAY_SIZE(omap3_vp);
182 181
183 u32 omap3_prm_vp_check_txdone(u8 vp_id) 182 u32 omap3_prm_vp_check_txdone(u8 vp_id)
184 { 183 {
185 struct omap3_vp *vp = &omap3_vp[vp_id]; 184 struct omap3_vp *vp = &omap3_vp[vp_id];
186 u32 irqstatus; 185 u32 irqstatus;
187 186
188 irqstatus = omap2_prm_read_mod_reg(OCP_MOD, 187 irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
189 OMAP3_PRM_IRQSTATUS_MPU_OFFSET); 188 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
190 return irqstatus & vp->tranxdone_status; 189 return irqstatus & vp->tranxdone_status;
191 } 190 }
192 191
193 void omap3_prm_vp_clear_txdone(u8 vp_id) 192 void omap3_prm_vp_clear_txdone(u8 vp_id)
194 { 193 {
195 struct omap3_vp *vp = &omap3_vp[vp_id]; 194 struct omap3_vp *vp = &omap3_vp[vp_id];
196 195
197 omap2_prm_write_mod_reg(vp->tranxdone_status, 196 omap2_prm_write_mod_reg(vp->tranxdone_status,
198 OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); 197 OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
199 } 198 }
200 199
201 u32 omap3_prm_vcvp_read(u8 offset) 200 u32 omap3_prm_vcvp_read(u8 offset)
202 { 201 {
203 return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset); 202 return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
204 } 203 }
205 204
206 void omap3_prm_vcvp_write(u32 val, u8 offset) 205 void omap3_prm_vcvp_write(u32 val, u8 offset)
207 { 206 {
208 omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset); 207 omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
209 } 208 }
210 209
211 u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset) 210 u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
212 { 211 {
213 return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset); 212 return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
214 } 213 }
215 214
arch/arm/mach-omap2/prm44xx.c
1 /* 1 /*
2 * OMAP4 PRM module functions 2 * OMAP4 PRM module functions
3 * 3 *
4 * Copyright (C) 2011 Texas Instruments, Inc. 4 * Copyright (C) 2011 Texas Instruments, Inc.
5 * Copyright (C) 2010 Nokia Corporation 5 * Copyright (C) 2010 Nokia Corporation
6 * Benoรฎt Cousson 6 * Benoรฎt Cousson
7 * Paul Walmsley 7 * Paul Walmsley
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/kernel.h> 14 #include <linux/kernel.h>
15 #include <linux/delay.h> 15 #include <linux/delay.h>
16 #include <linux/errno.h> 16 #include <linux/errno.h>
17 #include <linux/err.h> 17 #include <linux/err.h>
18 #include <linux/io.h> 18 #include <linux/io.h>
19 19
20 #include <plat/common.h> 20 #include <plat/common.h>
21 #include <plat/cpu.h> 21 #include <plat/cpu.h>
22 #include <plat/prcm.h> 22 #include <plat/prcm.h>
23 #include <plat/vp.h>
23 24
24 #include "vp.h"
25 #include "prm44xx.h" 25 #include "prm44xx.h"
26 #include "prm-regbits-44xx.h" 26 #include "prm-regbits-44xx.h"
27 #include "prcm44xx.h" 27 #include "prcm44xx.h"
28 #include "prminst44xx.h" 28 #include "prminst44xx.h"
29 29
30 /* PRM low-level functions */ 30 /* PRM low-level functions */
31 31
32 /* Read a register in a CM/PRM instance in the PRM module */ 32 /* Read a register in a CM/PRM instance in the PRM module */
33 u32 omap4_prm_read_inst_reg(s16 inst, u16 reg) 33 u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
34 { 34 {
35 return __raw_readl(OMAP44XX_PRM_REGADDR(inst, reg)); 35 return __raw_readl(OMAP44XX_PRM_REGADDR(inst, reg));
36 } 36 }
37 37
38 /* Write into a register in a CM/PRM instance in the PRM module */ 38 /* Write into a register in a CM/PRM instance in the PRM module */
39 void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg) 39 void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
40 { 40 {
41 __raw_writel(val, OMAP44XX_PRM_REGADDR(inst, reg)); 41 __raw_writel(val, OMAP44XX_PRM_REGADDR(inst, reg));
42 } 42 }
43 43
44 /* Read-modify-write a register in a PRM module. Caller must lock */ 44 /* Read-modify-write a register in a PRM module. Caller must lock */
45 u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg) 45 u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
46 { 46 {
47 u32 v; 47 u32 v;
48 48
49 v = omap4_prm_read_inst_reg(inst, reg); 49 v = omap4_prm_read_inst_reg(inst, reg);
50 v &= ~mask; 50 v &= ~mask;
51 v |= bits; 51 v |= bits;
52 omap4_prm_write_inst_reg(v, inst, reg); 52 omap4_prm_write_inst_reg(v, inst, reg);
53 53
54 return v; 54 return v;
55 } 55 }
56 56
57 /* PRM VP */ 57 /* PRM VP */
58 58
59 /* 59 /*
60 * struct omap4_vp - OMAP4 VP register access description. 60 * struct omap4_vp - OMAP4 VP register access description.
61 * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP 61 * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP
62 * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg 62 * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
63 */ 63 */
64 struct omap4_vp { 64 struct omap4_vp {
65 u32 irqstatus_mpu; 65 u32 irqstatus_mpu;
66 u32 tranxdone_status; 66 u32 tranxdone_status;
67 }; 67 };
68 68
69 static struct omap4_vp omap4_vp[] = { 69 static struct omap4_vp omap4_vp[] = {
70 [OMAP4_VP_VDD_MPU_ID] = { 70 [OMAP4_VP_VDD_MPU_ID] = {
71 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET, 71 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
72 .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK, 72 .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
73 }, 73 },
74 [OMAP4_VP_VDD_IVA_ID] = { 74 [OMAP4_VP_VDD_IVA_ID] = {
75 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET, 75 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
76 .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK, 76 .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
77 }, 77 },
78 [OMAP4_VP_VDD_CORE_ID] = { 78 [OMAP4_VP_VDD_CORE_ID] = {
79 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET, 79 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
80 .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK, 80 .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
81 }, 81 },
82 }; 82 };
83 83
84 u32 omap4_prm_vp_check_txdone(u8 vp_id) 84 u32 omap4_prm_vp_check_txdone(u8 vp_id)
85 { 85 {
86 struct omap4_vp *vp = &omap4_vp[vp_id]; 86 struct omap4_vp *vp = &omap4_vp[vp_id];
87 u32 irqstatus; 87 u32 irqstatus;
88 88
89 irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, 89 irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
90 OMAP4430_PRM_OCP_SOCKET_INST, 90 OMAP4430_PRM_OCP_SOCKET_INST,
91 vp->irqstatus_mpu); 91 vp->irqstatus_mpu);
92 return irqstatus & vp->tranxdone_status; 92 return irqstatus & vp->tranxdone_status;
93 } 93 }
94 94
95 void omap4_prm_vp_clear_txdone(u8 vp_id) 95 void omap4_prm_vp_clear_txdone(u8 vp_id)
96 { 96 {
97 struct omap4_vp *vp = &omap4_vp[vp_id]; 97 struct omap4_vp *vp = &omap4_vp[vp_id];
98 98
99 omap4_prminst_write_inst_reg(vp->tranxdone_status, 99 omap4_prminst_write_inst_reg(vp->tranxdone_status,
100 OMAP4430_PRM_PARTITION, 100 OMAP4430_PRM_PARTITION,
101 OMAP4430_PRM_OCP_SOCKET_INST, 101 OMAP4430_PRM_OCP_SOCKET_INST,
102 vp->irqstatus_mpu); 102 vp->irqstatus_mpu);
103 }; 103 };
104 104
105 u32 omap4_prm_vcvp_read(u8 offset) 105 u32 omap4_prm_vcvp_read(u8 offset)
106 { 106 {
107 return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, 107 return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
108 OMAP4430_PRM_DEVICE_INST, offset); 108 OMAP4430_PRM_DEVICE_INST, offset);
109 } 109 }
110 110
111 void omap4_prm_vcvp_write(u32 val, u8 offset) 111 void omap4_prm_vcvp_write(u32 val, u8 offset)
112 { 112 {
113 omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, 113 omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
114 OMAP4430_PRM_DEVICE_INST, offset); 114 OMAP4430_PRM_DEVICE_INST, offset);
115 } 115 }
116 116
117 u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset) 117 u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
118 { 118 {
119 return omap4_prminst_rmw_inst_reg_bits(mask, bits, 119 return omap4_prminst_rmw_inst_reg_bits(mask, bits,
120 OMAP4430_PRM_PARTITION, 120 OMAP4430_PRM_PARTITION,
121 OMAP4430_PRM_DEVICE_INST, 121 OMAP4430_PRM_DEVICE_INST,
122 offset); 122 offset);
123 } 123 }
arch/arm/mach-omap2/smartreflex.h
1 /* 1 /*
2 * OMAP Smartreflex Defines and Routines 2 * OMAP Smartreflex Defines and Routines
3 * 3 *
4 * Author: Thara Gopinath <thara@ti.com> 4 * Author: Thara Gopinath <thara@ti.com>
5 * 5 *
6 * Copyright (C) 2010 Texas Instruments, Inc. 6 * Copyright (C) 2010 Texas Instruments, Inc.
7 * Thara Gopinath <thara@ti.com> 7 * Thara Gopinath <thara@ti.com>
8 * 8 *
9 * Copyright (C) 2008 Nokia Corporation 9 * Copyright (C) 2008 Nokia Corporation
10 * Kalle Jokiniemi 10 * Kalle Jokiniemi
11 * 11 *
12 * Copyright (C) 2007 Texas Instruments, Inc. 12 * Copyright (C) 2007 Texas Instruments, Inc.
13 * Lesly A M <x0080970@ti.com> 13 * Lesly A M <x0080970@ti.com>
14 * 14 *
15 * This program is free software; you can redistribute it and/or modify 15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as 16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation. 17 * published by the Free Software Foundation.
18 */ 18 */
19 19
20 #ifndef __ASM_ARM_OMAP_SMARTREFLEX_H 20 #ifndef __ASM_ARM_OMAP_SMARTREFLEX_H
21 #define __ASM_ARM_OMAP_SMARTREFLEX_H 21 #define __ASM_ARM_OMAP_SMARTREFLEX_H
22 22
23 #include <linux/platform_device.h> 23 #include <linux/platform_device.h>
24 #include <plat/voltage.h>
24 25
25 #include "voltage.h"
26 26
27 /* 27 /*
28 * Different Smartreflex IPs version. The v1 is the 65nm version used in 28 * Different Smartreflex IPs version. The v1 is the 65nm version used in
29 * OMAP3430. The v2 is the update for the 45nm version of the IP 29 * OMAP3430. The v2 is the update for the 45nm version of the IP
30 * used in OMAP3630 and OMAP4430 30 * used in OMAP3630 and OMAP4430
31 */ 31 */
32 #define SR_TYPE_V1 1 32 #define SR_TYPE_V1 1
33 #define SR_TYPE_V2 2 33 #define SR_TYPE_V2 2
34 34
35 /* SMART REFLEX REG ADDRESS OFFSET */ 35 /* SMART REFLEX REG ADDRESS OFFSET */
36 #define SRCONFIG 0x00 36 #define SRCONFIG 0x00
37 #define SRSTATUS 0x04 37 #define SRSTATUS 0x04
38 #define SENVAL 0x08 38 #define SENVAL 0x08
39 #define SENMIN 0x0C 39 #define SENMIN 0x0C
40 #define SENMAX 0x10 40 #define SENMAX 0x10
41 #define SENAVG 0x14 41 #define SENAVG 0x14
42 #define AVGWEIGHT 0x18 42 #define AVGWEIGHT 0x18
43 #define NVALUERECIPROCAL 0x1c 43 #define NVALUERECIPROCAL 0x1c
44 #define SENERROR_V1 0x20 44 #define SENERROR_V1 0x20
45 #define ERRCONFIG_V1 0x24 45 #define ERRCONFIG_V1 0x24
46 #define IRQ_EOI 0x20 46 #define IRQ_EOI 0x20
47 #define IRQSTATUS_RAW 0x24 47 #define IRQSTATUS_RAW 0x24
48 #define IRQSTATUS 0x28 48 #define IRQSTATUS 0x28
49 #define IRQENABLE_SET 0x2C 49 #define IRQENABLE_SET 0x2C
50 #define IRQENABLE_CLR 0x30 50 #define IRQENABLE_CLR 0x30
51 #define SENERROR_V2 0x34 51 #define SENERROR_V2 0x34
52 #define ERRCONFIG_V2 0x38 52 #define ERRCONFIG_V2 0x38
53 53
54 /* Bit/Shift Positions */ 54 /* Bit/Shift Positions */
55 55
56 /* SRCONFIG */ 56 /* SRCONFIG */
57 #define SRCONFIG_ACCUMDATA_SHIFT 22 57 #define SRCONFIG_ACCUMDATA_SHIFT 22
58 #define SRCONFIG_SRCLKLENGTH_SHIFT 12 58 #define SRCONFIG_SRCLKLENGTH_SHIFT 12
59 #define SRCONFIG_SENNENABLE_V1_SHIFT 5 59 #define SRCONFIG_SENNENABLE_V1_SHIFT 5
60 #define SRCONFIG_SENPENABLE_V1_SHIFT 3 60 #define SRCONFIG_SENPENABLE_V1_SHIFT 3
61 #define SRCONFIG_SENNENABLE_V2_SHIFT 1 61 #define SRCONFIG_SENNENABLE_V2_SHIFT 1
62 #define SRCONFIG_SENPENABLE_V2_SHIFT 0 62 #define SRCONFIG_SENPENABLE_V2_SHIFT 0
63 #define SRCONFIG_CLKCTRL_SHIFT 0 63 #define SRCONFIG_CLKCTRL_SHIFT 0
64 64
65 #define SRCONFIG_ACCUMDATA_MASK (0x3ff << 22) 65 #define SRCONFIG_ACCUMDATA_MASK (0x3ff << 22)
66 66
67 #define SRCONFIG_SRENABLE BIT(11) 67 #define SRCONFIG_SRENABLE BIT(11)
68 #define SRCONFIG_SENENABLE BIT(10) 68 #define SRCONFIG_SENENABLE BIT(10)
69 #define SRCONFIG_ERRGEN_EN BIT(9) 69 #define SRCONFIG_ERRGEN_EN BIT(9)
70 #define SRCONFIG_MINMAXAVG_EN BIT(8) 70 #define SRCONFIG_MINMAXAVG_EN BIT(8)
71 #define SRCONFIG_DELAYCTRL BIT(2) 71 #define SRCONFIG_DELAYCTRL BIT(2)
72 72
73 /* AVGWEIGHT */ 73 /* AVGWEIGHT */
74 #define AVGWEIGHT_SENPAVGWEIGHT_SHIFT 2 74 #define AVGWEIGHT_SENPAVGWEIGHT_SHIFT 2
75 #define AVGWEIGHT_SENNAVGWEIGHT_SHIFT 0 75 #define AVGWEIGHT_SENNAVGWEIGHT_SHIFT 0
76 76
77 /* NVALUERECIPROCAL */ 77 /* NVALUERECIPROCAL */
78 #define NVALUERECIPROCAL_SENPGAIN_SHIFT 20 78 #define NVALUERECIPROCAL_SENPGAIN_SHIFT 20
79 #define NVALUERECIPROCAL_SENNGAIN_SHIFT 16 79 #define NVALUERECIPROCAL_SENNGAIN_SHIFT 16
80 #define NVALUERECIPROCAL_RNSENP_SHIFT 8 80 #define NVALUERECIPROCAL_RNSENP_SHIFT 8
81 #define NVALUERECIPROCAL_RNSENN_SHIFT 0 81 #define NVALUERECIPROCAL_RNSENN_SHIFT 0
82 82
83 /* ERRCONFIG */ 83 /* ERRCONFIG */
84 #define ERRCONFIG_ERRWEIGHT_SHIFT 16 84 #define ERRCONFIG_ERRWEIGHT_SHIFT 16
85 #define ERRCONFIG_ERRMAXLIMIT_SHIFT 8 85 #define ERRCONFIG_ERRMAXLIMIT_SHIFT 8
86 #define ERRCONFIG_ERRMINLIMIT_SHIFT 0 86 #define ERRCONFIG_ERRMINLIMIT_SHIFT 0
87 87
88 #define SR_ERRWEIGHT_MASK (0x07 << 16) 88 #define SR_ERRWEIGHT_MASK (0x07 << 16)
89 #define SR_ERRMAXLIMIT_MASK (0xff << 8) 89 #define SR_ERRMAXLIMIT_MASK (0xff << 8)
90 #define SR_ERRMINLIMIT_MASK (0xff << 0) 90 #define SR_ERRMINLIMIT_MASK (0xff << 0)
91 91
92 #define ERRCONFIG_VPBOUNDINTEN_V1 BIT(31) 92 #define ERRCONFIG_VPBOUNDINTEN_V1 BIT(31)
93 #define ERRCONFIG_VPBOUNDINTST_V1 BIT(30) 93 #define ERRCONFIG_VPBOUNDINTST_V1 BIT(30)
94 #define ERRCONFIG_MCUACCUMINTEN BIT(29) 94 #define ERRCONFIG_MCUACCUMINTEN BIT(29)
95 #define ERRCONFIG_MCUACCUMINTST BIT(28) 95 #define ERRCONFIG_MCUACCUMINTST BIT(28)
96 #define ERRCONFIG_MCUVALIDINTEN BIT(27) 96 #define ERRCONFIG_MCUVALIDINTEN BIT(27)
97 #define ERRCONFIG_MCUVALIDINTST BIT(26) 97 #define ERRCONFIG_MCUVALIDINTST BIT(26)
98 #define ERRCONFIG_MCUBOUNDINTEN BIT(25) 98 #define ERRCONFIG_MCUBOUNDINTEN BIT(25)
99 #define ERRCONFIG_MCUBOUNDINTST BIT(24) 99 #define ERRCONFIG_MCUBOUNDINTST BIT(24)
100 #define ERRCONFIG_MCUDISACKINTEN BIT(23) 100 #define ERRCONFIG_MCUDISACKINTEN BIT(23)
101 #define ERRCONFIG_VPBOUNDINTST_V2 BIT(23) 101 #define ERRCONFIG_VPBOUNDINTST_V2 BIT(23)
102 #define ERRCONFIG_MCUDISACKINTST BIT(22) 102 #define ERRCONFIG_MCUDISACKINTST BIT(22)
103 #define ERRCONFIG_VPBOUNDINTEN_V2 BIT(22) 103 #define ERRCONFIG_VPBOUNDINTEN_V2 BIT(22)
104 104
105 #define ERRCONFIG_STATUS_V1_MASK (ERRCONFIG_VPBOUNDINTST_V1 | \ 105 #define ERRCONFIG_STATUS_V1_MASK (ERRCONFIG_VPBOUNDINTST_V1 | \
106 ERRCONFIG_MCUACCUMINTST | \ 106 ERRCONFIG_MCUACCUMINTST | \
107 ERRCONFIG_MCUVALIDINTST | \ 107 ERRCONFIG_MCUVALIDINTST | \
108 ERRCONFIG_MCUBOUNDINTST | \ 108 ERRCONFIG_MCUBOUNDINTST | \
109 ERRCONFIG_MCUDISACKINTST) 109 ERRCONFIG_MCUDISACKINTST)
110 /* IRQSTATUS */ 110 /* IRQSTATUS */
111 #define IRQSTATUS_MCUACCUMINT BIT(3) 111 #define IRQSTATUS_MCUACCUMINT BIT(3)
112 #define IRQSTATUS_MCVALIDINT BIT(2) 112 #define IRQSTATUS_MCVALIDINT BIT(2)
113 #define IRQSTATUS_MCBOUNDSINT BIT(1) 113 #define IRQSTATUS_MCBOUNDSINT BIT(1)
114 #define IRQSTATUS_MCUDISABLEACKINT BIT(0) 114 #define IRQSTATUS_MCUDISABLEACKINT BIT(0)
115 115
116 /* IRQENABLE_SET and IRQENABLE_CLEAR */ 116 /* IRQENABLE_SET and IRQENABLE_CLEAR */
117 #define IRQENABLE_MCUACCUMINT BIT(3) 117 #define IRQENABLE_MCUACCUMINT BIT(3)
118 #define IRQENABLE_MCUVALIDINT BIT(2) 118 #define IRQENABLE_MCUVALIDINT BIT(2)
119 #define IRQENABLE_MCUBOUNDSINT BIT(1) 119 #define IRQENABLE_MCUBOUNDSINT BIT(1)
120 #define IRQENABLE_MCUDISABLEACKINT BIT(0) 120 #define IRQENABLE_MCUDISABLEACKINT BIT(0)
121 121
122 /* Common Bit values */ 122 /* Common Bit values */
123 123
124 #define SRCLKLENGTH_12MHZ_SYSCLK 0x3c 124 #define SRCLKLENGTH_12MHZ_SYSCLK 0x3c
125 #define SRCLKLENGTH_13MHZ_SYSCLK 0x41 125 #define SRCLKLENGTH_13MHZ_SYSCLK 0x41
126 #define SRCLKLENGTH_19MHZ_SYSCLK 0x60 126 #define SRCLKLENGTH_19MHZ_SYSCLK 0x60
127 #define SRCLKLENGTH_26MHZ_SYSCLK 0x82 127 #define SRCLKLENGTH_26MHZ_SYSCLK 0x82
128 #define SRCLKLENGTH_38MHZ_SYSCLK 0xC0 128 #define SRCLKLENGTH_38MHZ_SYSCLK 0xC0
129 129
130 /* 130 /*
131 * 3430 specific values. Maybe these should be passed from board file or 131 * 3430 specific values. Maybe these should be passed from board file or
132 * pmic structures. 132 * pmic structures.
133 */ 133 */
134 #define OMAP3430_SR_ACCUMDATA 0x1f4 134 #define OMAP3430_SR_ACCUMDATA 0x1f4
135 135
136 #define OMAP3430_SR1_SENPAVGWEIGHT 0x03 136 #define OMAP3430_SR1_SENPAVGWEIGHT 0x03
137 #define OMAP3430_SR1_SENNAVGWEIGHT 0x03 137 #define OMAP3430_SR1_SENNAVGWEIGHT 0x03
138 138
139 #define OMAP3430_SR2_SENPAVGWEIGHT 0x01 139 #define OMAP3430_SR2_SENPAVGWEIGHT 0x01
140 #define OMAP3430_SR2_SENNAVGWEIGHT 0x01 140 #define OMAP3430_SR2_SENNAVGWEIGHT 0x01
141 141
142 #define OMAP3430_SR_ERRWEIGHT 0x04 142 #define OMAP3430_SR_ERRWEIGHT 0x04
143 #define OMAP3430_SR_ERRMAXLIMIT 0x02 143 #define OMAP3430_SR_ERRMAXLIMIT 0x02
144 144
145 /** 145 /**
146 * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass 146 * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
147 * pmic specific info to smartreflex driver 147 * pmic specific info to smartreflex driver
148 * 148 *
149 * @sr_pmic_init: API to initialize smartreflex on the PMIC side. 149 * @sr_pmic_init: API to initialize smartreflex on the PMIC side.
150 */ 150 */
151 struct omap_sr_pmic_data { 151 struct omap_sr_pmic_data {
152 void (*sr_pmic_init) (void); 152 void (*sr_pmic_init) (void);
153 }; 153 };
154 154
155 #ifdef CONFIG_OMAP_SMARTREFLEX 155 #ifdef CONFIG_OMAP_SMARTREFLEX
156 /* 156 /*
157 * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR. 157 * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
158 * The smartreflex class driver should pass the class type. 158 * The smartreflex class driver should pass the class type.
159 * Should be used to populate the class_type field of the 159 * Should be used to populate the class_type field of the
160 * omap_smartreflex_class_data structure. 160 * omap_smartreflex_class_data structure.
161 */ 161 */
162 #define SR_CLASS1 0x1 162 #define SR_CLASS1 0x1
163 #define SR_CLASS2 0x2 163 #define SR_CLASS2 0x2
164 #define SR_CLASS3 0x3 164 #define SR_CLASS3 0x3
165 165
166 /** 166 /**
167 * struct omap_sr_class_data - Smartreflex class driver info 167 * struct omap_sr_class_data - Smartreflex class driver info
168 * 168 *
169 * @enable: API to enable a particular class smaartreflex. 169 * @enable: API to enable a particular class smaartreflex.
170 * @disable: API to disable a particular class smartreflex. 170 * @disable: API to disable a particular class smartreflex.
171 * @configure: API to configure a particular class smartreflex. 171 * @configure: API to configure a particular class smartreflex.
172 * @notify: API to notify the class driver about an event in SR. 172 * @notify: API to notify the class driver about an event in SR.
173 * Not needed for class3. 173 * Not needed for class3.
174 * @notify_flags: specify the events to be notified to the class driver 174 * @notify_flags: specify the events to be notified to the class driver
175 * @class_type: specify which smartreflex class. 175 * @class_type: specify which smartreflex class.
176 * Can be used by the SR driver to take any class 176 * Can be used by the SR driver to take any class
177 * based decisions. 177 * based decisions.
178 */ 178 */
179 struct omap_sr_class_data { 179 struct omap_sr_class_data {
180 int (*enable)(struct voltagedomain *voltdm); 180 int (*enable)(struct voltagedomain *voltdm);
181 int (*disable)(struct voltagedomain *voltdm, int is_volt_reset); 181 int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
182 int (*configure)(struct voltagedomain *voltdm); 182 int (*configure)(struct voltagedomain *voltdm);
183 int (*notify)(struct voltagedomain *voltdm, u32 status); 183 int (*notify)(struct voltagedomain *voltdm, u32 status);
184 u8 notify_flags; 184 u8 notify_flags;
185 u8 class_type; 185 u8 class_type;
186 }; 186 };
187 187
188 /** 188 /**
189 * struct omap_sr_nvalue_table - Smartreflex n-target value info 189 * struct omap_sr_nvalue_table - Smartreflex n-target value info
190 * 190 *
191 * @efuse_offs: The offset of the efuse where n-target values are stored. 191 * @efuse_offs: The offset of the efuse where n-target values are stored.
192 * @nvalue: The n-target value. 192 * @nvalue: The n-target value.
193 */ 193 */
194 struct omap_sr_nvalue_table { 194 struct omap_sr_nvalue_table {
195 u32 efuse_offs; 195 u32 efuse_offs;
196 u32 nvalue; 196 u32 nvalue;
197 }; 197 };
198 198
199 /** 199 /**
200 * struct omap_sr_data - Smartreflex platform data. 200 * struct omap_sr_data - Smartreflex platform data.
201 * 201 *
202 * @ip_type: Smartreflex IP type. 202 * @ip_type: Smartreflex IP type.
203 * @senp_mod: SENPENABLE value for the sr 203 * @senp_mod: SENPENABLE value for the sr
204 * @senn_mod: SENNENABLE value for sr 204 * @senn_mod: SENNENABLE value for sr
205 * @nvalue_count: Number of distinct nvalues in the nvalue table 205 * @nvalue_count: Number of distinct nvalues in the nvalue table
206 * @enable_on_init: whether this sr module needs to enabled at 206 * @enable_on_init: whether this sr module needs to enabled at
207 * boot up or not. 207 * boot up or not.
208 * @nvalue_table: table containing the efuse offsets and nvalues 208 * @nvalue_table: table containing the efuse offsets and nvalues
209 * corresponding to them. 209 * corresponding to them.
210 * @voltdm: Pointer to the voltage domain associated with the SR 210 * @voltdm: Pointer to the voltage domain associated with the SR
211 */ 211 */
212 struct omap_sr_data { 212 struct omap_sr_data {
213 int ip_type; 213 int ip_type;
214 u32 senp_mod; 214 u32 senp_mod;
215 u32 senn_mod; 215 u32 senn_mod;
216 int nvalue_count; 216 int nvalue_count;
217 bool enable_on_init; 217 bool enable_on_init;
218 struct omap_sr_nvalue_table *nvalue_table; 218 struct omap_sr_nvalue_table *nvalue_table;
219 struct voltagedomain *voltdm; 219 struct voltagedomain *voltdm;
220 }; 220 };
221 221
222 /* Smartreflex module enable/disable interface */ 222 /* Smartreflex module enable/disable interface */
223 void omap_sr_enable(struct voltagedomain *voltdm); 223 void omap_sr_enable(struct voltagedomain *voltdm);
224 void omap_sr_disable(struct voltagedomain *voltdm); 224 void omap_sr_disable(struct voltagedomain *voltdm);
225 void omap_sr_disable_reset_volt(struct voltagedomain *voltdm); 225 void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
226 226
227 /* API to register the pmic specific data with the smartreflex driver. */ 227 /* API to register the pmic specific data with the smartreflex driver. */
228 void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data); 228 void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
229 229
230 /* Smartreflex driver hooks to be called from Smartreflex class driver */ 230 /* Smartreflex driver hooks to be called from Smartreflex class driver */
231 int sr_enable(struct voltagedomain *voltdm, unsigned long volt); 231 int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
232 void sr_disable(struct voltagedomain *voltdm); 232 void sr_disable(struct voltagedomain *voltdm);
233 int sr_configure_errgen(struct voltagedomain *voltdm); 233 int sr_configure_errgen(struct voltagedomain *voltdm);
234 int sr_configure_minmax(struct voltagedomain *voltdm); 234 int sr_configure_minmax(struct voltagedomain *voltdm);
235 235
236 /* API to register the smartreflex class driver with the smartreflex driver */ 236 /* API to register the smartreflex class driver with the smartreflex driver */
237 int sr_register_class(struct omap_sr_class_data *class_data); 237 int sr_register_class(struct omap_sr_class_data *class_data);
238 #else 238 #else
239 static inline void omap_sr_enable(struct voltagedomain *voltdm) {} 239 static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
240 static inline void omap_sr_disable(struct voltagedomain *voltdm) {} 240 static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
241 static inline void omap_sr_disable_reset_volt( 241 static inline void omap_sr_disable_reset_volt(
242 struct voltagedomain *voltdm) {} 242 struct voltagedomain *voltdm) {}
243 static inline void omap_sr_register_pmic( 243 static inline void omap_sr_register_pmic(
244 struct omap_sr_pmic_data *pmic_data) {} 244 struct omap_sr_pmic_data *pmic_data) {}
245 #endif 245 #endif
246 #endif 246 #endif
arch/arm/mach-omap2/sr_device.c
1 /* 1 /*
2 * OMAP3/OMAP4 smartreflex device file 2 * OMAP3/OMAP4 smartreflex device file
3 * 3 *
4 * Author: Thara Gopinath <thara@ti.com> 4 * Author: Thara Gopinath <thara@ti.com>
5 * 5 *
6 * Based originally on code from smartreflex.c 6 * Based originally on code from smartreflex.c
7 * Copyright (C) 2010 Texas Instruments, Inc. 7 * Copyright (C) 2010 Texas Instruments, Inc.
8 * Thara Gopinath <thara@ti.com> 8 * Thara Gopinath <thara@ti.com>
9 * 9 *
10 * Copyright (C) 2008 Nokia Corporation 10 * Copyright (C) 2008 Nokia Corporation
11 * Kalle Jokiniemi 11 * Kalle Jokiniemi
12 * 12 *
13 * Copyright (C) 2007 Texas Instruments, Inc. 13 * Copyright (C) 2007 Texas Instruments, Inc.
14 * Lesly A M <x0080970@ti.com> 14 * Lesly A M <x0080970@ti.com>
15 * 15 *
16 * This program is free software; you can redistribute it and/or modify 16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2 as 17 * it under the terms of the GNU General Public License version 2 as
18 * published by the Free Software Foundation. 18 * published by the Free Software Foundation.
19 */ 19 */
20 20
21 #include <linux/err.h> 21 #include <linux/err.h>
22 #include <linux/slab.h> 22 #include <linux/slab.h>
23 #include <linux/io.h> 23 #include <linux/io.h>
24 24
25 #include <plat/omap_device.h> 25 #include <plat/omap_device.h>
26 #include <plat/voltage.h>
26 27
27 #include "smartreflex.h" 28 #include "smartreflex.h"
28 #include "voltage.h"
29 #include "control.h" 29 #include "control.h"
30 #include "pm.h" 30 #include "pm.h"
31 31
32 static bool sr_enable_on_init; 32 static bool sr_enable_on_init;
33 33
34 /* Read EFUSE values from control registers for OMAP3430 */ 34 /* Read EFUSE values from control registers for OMAP3430 */
35 static void __init sr_set_nvalues(struct omap_volt_data *volt_data, 35 static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
36 struct omap_sr_data *sr_data) 36 struct omap_sr_data *sr_data)
37 { 37 {
38 struct omap_sr_nvalue_table *nvalue_table; 38 struct omap_sr_nvalue_table *nvalue_table;
39 int i, count = 0; 39 int i, count = 0;
40 40
41 while (volt_data[count].volt_nominal) 41 while (volt_data[count].volt_nominal)
42 count++; 42 count++;
43 43
44 nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count, 44 nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count,
45 GFP_KERNEL); 45 GFP_KERNEL);
46 46
47 for (i = 0; i < count; i++) { 47 for (i = 0; i < count; i++) {
48 u32 v; 48 u32 v;
49 /* 49 /*
50 * In OMAP4 the efuse registers are 24 bit aligned. 50 * In OMAP4 the efuse registers are 24 bit aligned.
51 * A __raw_readl will fail for non-32 bit aligned address 51 * A __raw_readl will fail for non-32 bit aligned address
52 * and hence the 8-bit read and shift. 52 * and hence the 8-bit read and shift.
53 */ 53 */
54 if (cpu_is_omap44xx()) { 54 if (cpu_is_omap44xx()) {
55 u16 offset = volt_data[i].sr_efuse_offs; 55 u16 offset = volt_data[i].sr_efuse_offs;
56 56
57 v = omap_ctrl_readb(offset) | 57 v = omap_ctrl_readb(offset) |
58 omap_ctrl_readb(offset + 1) << 8 | 58 omap_ctrl_readb(offset + 1) << 8 |
59 omap_ctrl_readb(offset + 2) << 16; 59 omap_ctrl_readb(offset + 2) << 16;
60 } else { 60 } else {
61 v = omap_ctrl_readl(volt_data[i].sr_efuse_offs); 61 v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
62 } 62 }
63 63
64 nvalue_table[i].efuse_offs = volt_data[i].sr_efuse_offs; 64 nvalue_table[i].efuse_offs = volt_data[i].sr_efuse_offs;
65 nvalue_table[i].nvalue = v; 65 nvalue_table[i].nvalue = v;
66 } 66 }
67 67
68 sr_data->nvalue_table = nvalue_table; 68 sr_data->nvalue_table = nvalue_table;
69 sr_data->nvalue_count = count; 69 sr_data->nvalue_count = count;
70 } 70 }
71 71
72 static int sr_dev_init(struct omap_hwmod *oh, void *user) 72 static int sr_dev_init(struct omap_hwmod *oh, void *user)
73 { 73 {
74 struct omap_sr_data *sr_data; 74 struct omap_sr_data *sr_data;
75 struct platform_device *pdev; 75 struct platform_device *pdev;
76 struct omap_volt_data *volt_data; 76 struct omap_volt_data *volt_data;
77 char *name = "smartreflex"; 77 char *name = "smartreflex";
78 static int i; 78 static int i;
79 79
80 sr_data = kzalloc(sizeof(struct omap_sr_data), GFP_KERNEL); 80 sr_data = kzalloc(sizeof(struct omap_sr_data), GFP_KERNEL);
81 if (!sr_data) { 81 if (!sr_data) {
82 pr_err("%s: Unable to allocate memory for %s sr_data.Error!\n", 82 pr_err("%s: Unable to allocate memory for %s sr_data.Error!\n",
83 __func__, oh->name); 83 __func__, oh->name);
84 return -ENOMEM; 84 return -ENOMEM;
85 } 85 }
86 86
87 if (!oh->vdd_name) { 87 if (!oh->vdd_name) {
88 pr_err("%s: No voltage domain specified for %s." 88 pr_err("%s: No voltage domain specified for %s."
89 "Cannot initialize\n", __func__, oh->name); 89 "Cannot initialize\n", __func__, oh->name);
90 goto exit; 90 goto exit;
91 } 91 }
92 92
93 sr_data->ip_type = oh->class->rev; 93 sr_data->ip_type = oh->class->rev;
94 sr_data->senn_mod = 0x1; 94 sr_data->senn_mod = 0x1;
95 sr_data->senp_mod = 0x1; 95 sr_data->senp_mod = 0x1;
96 96
97 sr_data->voltdm = voltdm_lookup(oh->vdd_name); 97 sr_data->voltdm = voltdm_lookup(oh->vdd_name);
98 if (IS_ERR(sr_data->voltdm)) { 98 if (IS_ERR(sr_data->voltdm)) {
99 pr_err("%s: Unable to get voltage domain pointer for VDD %s\n", 99 pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
100 __func__, oh->vdd_name); 100 __func__, oh->vdd_name);
101 goto exit; 101 goto exit;
102 } 102 }
103 103
104 omap_voltage_get_volttable(sr_data->voltdm, &volt_data); 104 omap_voltage_get_volttable(sr_data->voltdm, &volt_data);
105 if (!volt_data) { 105 if (!volt_data) {
106 pr_warning("%s: No Voltage table registerd fo VDD%d." 106 pr_warning("%s: No Voltage table registerd fo VDD%d."
107 "Something really wrong\n\n", __func__, i + 1); 107 "Something really wrong\n\n", __func__, i + 1);
108 goto exit; 108 goto exit;
109 } 109 }
110 110
111 sr_set_nvalues(volt_data, sr_data); 111 sr_set_nvalues(volt_data, sr_data);
112 112
113 sr_data->enable_on_init = sr_enable_on_init; 113 sr_data->enable_on_init = sr_enable_on_init;
114 114
115 pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data), 115 pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
116 NULL, 0, 0); 116 NULL, 0, 0);
117 if (IS_ERR(pdev)) 117 if (IS_ERR(pdev))
118 pr_warning("%s: Could not build omap_device for %s: %s.\n\n", 118 pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
119 __func__, name, oh->name); 119 __func__, name, oh->name);
120 exit: 120 exit:
121 i++; 121 i++;
122 kfree(sr_data); 122 kfree(sr_data);
123 return 0; 123 return 0;
124 } 124 }
125 125
126 /* 126 /*
127 * API to be called from board files to enable smartreflex 127 * API to be called from board files to enable smartreflex
128 * autocompensation at init. 128 * autocompensation at init.
129 */ 129 */
130 void __init omap_enable_smartreflex_on_init(void) 130 void __init omap_enable_smartreflex_on_init(void)
131 { 131 {
132 sr_enable_on_init = true; 132 sr_enable_on_init = true;
133 } 133 }
134 134
135 int __init omap_devinit_smartreflex(void) 135 int __init omap_devinit_smartreflex(void)
136 { 136 {
137 return omap_hwmod_for_each_by_class("smartreflex", sr_dev_init, NULL); 137 return omap_hwmod_for_each_by_class("smartreflex", sr_dev_init, NULL);
138 } 138 }
arch/arm/mach-omap2/vc.c
1 /* 1 /*
2 * OMAP Voltage Controller (VC) interface 2 * OMAP Voltage Controller (VC) interface
3 * 3 *
4 * Copyright (C) 2011 Texas Instruments, Inc. 4 * Copyright (C) 2011 Texas Instruments, Inc.
5 * 5 *
6 * This file is licensed under the terms of the GNU General Public 6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any 7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied. 8 * warranty of any kind, whether express or implied.
9 */ 9 */
10 #include <linux/kernel.h> 10 #include <linux/kernel.h>
11 #include <linux/delay.h> 11 #include <linux/delay.h>
12 #include <linux/init.h> 12 #include <linux/init.h>
13 13
14 #include <plat/cpu.h> 14 #include <plat/cpu.h>
15 #include <plat/voltage.h>
16 #include <plat/vc.h>
15 17
16 #include "voltage.h"
17 #include "vc.h"
18 #include "prm-regbits-34xx.h" 18 #include "prm-regbits-34xx.h"
19 #include "prm-regbits-44xx.h" 19 #include "prm-regbits-44xx.h"
20 #include "prm44xx.h" 20 #include "prm44xx.h"
21 21
22 /** 22 /**
23 * struct omap_vc_channel_cfg - describe the cfg_channel bitfield 23 * struct omap_vc_channel_cfg - describe the cfg_channel bitfield
24 * @sa: bit for slave address 24 * @sa: bit for slave address
25 * @rav: bit for voltage configuration register 25 * @rav: bit for voltage configuration register
26 * @rac: bit for command configuration register 26 * @rac: bit for command configuration register
27 * @racen: enable bit for RAC 27 * @racen: enable bit for RAC
28 * @cmd: bit for command value set selection 28 * @cmd: bit for command value set selection
29 * 29 *
30 * Channel configuration bits, common for OMAP3+ 30 * Channel configuration bits, common for OMAP3+
31 * OMAP3 register: PRM_VC_CH_CONF 31 * OMAP3 register: PRM_VC_CH_CONF
32 * OMAP4 register: PRM_VC_CFG_CHANNEL 32 * OMAP4 register: PRM_VC_CFG_CHANNEL
33 * OMAP5 register: PRM_VC_SMPS_<voltdm>_CONFIG 33 * OMAP5 register: PRM_VC_SMPS_<voltdm>_CONFIG
34 */ 34 */
35 struct omap_vc_channel_cfg { 35 struct omap_vc_channel_cfg {
36 u8 sa; 36 u8 sa;
37 u8 rav; 37 u8 rav;
38 u8 rac; 38 u8 rac;
39 u8 racen; 39 u8 racen;
40 u8 cmd; 40 u8 cmd;
41 }; 41 };
42 42
43 static struct omap_vc_channel_cfg vc_default_channel_cfg = { 43 static struct omap_vc_channel_cfg vc_default_channel_cfg = {
44 .sa = BIT(0), 44 .sa = BIT(0),
45 .rav = BIT(1), 45 .rav = BIT(1),
46 .rac = BIT(2), 46 .rac = BIT(2),
47 .racen = BIT(3), 47 .racen = BIT(3),
48 .cmd = BIT(4), 48 .cmd = BIT(4),
49 }; 49 };
50 50
51 /* 51 /*
52 * On OMAP3+, all VC channels have the above default bitfield 52 * On OMAP3+, all VC channels have the above default bitfield
53 * configuration, except the OMAP4 MPU channel. This appears 53 * configuration, except the OMAP4 MPU channel. This appears
54 * to be a freak accident as every other VC channel has the 54 * to be a freak accident as every other VC channel has the
55 * default configuration, thus creating a mutant channel config. 55 * default configuration, thus creating a mutant channel config.
56 */ 56 */
57 static struct omap_vc_channel_cfg vc_mutant_channel_cfg = { 57 static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
58 .sa = BIT(0), 58 .sa = BIT(0),
59 .rav = BIT(2), 59 .rav = BIT(2),
60 .rac = BIT(3), 60 .rac = BIT(3),
61 .racen = BIT(4), 61 .racen = BIT(4),
62 .cmd = BIT(1), 62 .cmd = BIT(1),
63 }; 63 };
64 64
65 static struct omap_vc_channel_cfg *vc_cfg_bits; 65 static struct omap_vc_channel_cfg *vc_cfg_bits;
66 #define CFG_CHANNEL_MASK 0x1f 66 #define CFG_CHANNEL_MASK 0x1f
67 67
68 /** 68 /**
69 * omap_vc_config_channel - configure VC channel to PMIC mappings 69 * omap_vc_config_channel - configure VC channel to PMIC mappings
70 * @voltdm: pointer to voltagdomain defining the desired VC channel 70 * @voltdm: pointer to voltagdomain defining the desired VC channel
71 * 71 *
72 * Configures the VC channel to PMIC mappings for the following 72 * Configures the VC channel to PMIC mappings for the following
73 * PMIC settings 73 * PMIC settings
74 * - i2c slave address (SA) 74 * - i2c slave address (SA)
75 * - voltage configuration address (RAV) 75 * - voltage configuration address (RAV)
76 * - command configuration address (RAC) and enable bit (RACEN) 76 * - command configuration address (RAC) and enable bit (RACEN)
77 * - command values for ON, ONLP, RET and OFF (CMD) 77 * - command values for ON, ONLP, RET and OFF (CMD)
78 * 78 *
79 * This function currently only allows flexible configuration of the 79 * This function currently only allows flexible configuration of the
80 * non-default channel. Starting with OMAP4, there are more than 2 80 * non-default channel. Starting with OMAP4, there are more than 2
81 * channels, with one defined as the default (on OMAP4, it's MPU.) 81 * channels, with one defined as the default (on OMAP4, it's MPU.)
82 * Only the non-default channel can be configured. 82 * Only the non-default channel can be configured.
83 */ 83 */
84 static int omap_vc_config_channel(struct voltagedomain *voltdm) 84 static int omap_vc_config_channel(struct voltagedomain *voltdm)
85 { 85 {
86 struct omap_vc_channel *vc = voltdm->vc; 86 struct omap_vc_channel *vc = voltdm->vc;
87 87
88 /* 88 /*
89 * For default channel, the only configurable bit is RACEN. 89 * For default channel, the only configurable bit is RACEN.
90 * All others must stay at zero (see function comment above.) 90 * All others must stay at zero (see function comment above.)
91 */ 91 */
92 if (vc->flags & OMAP_VC_CHANNEL_DEFAULT) 92 if (vc->flags & OMAP_VC_CHANNEL_DEFAULT)
93 vc->cfg_channel &= vc_cfg_bits->racen; 93 vc->cfg_channel &= vc_cfg_bits->racen;
94 94
95 voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift, 95 voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift,
96 vc->cfg_channel << vc->cfg_channel_sa_shift, 96 vc->cfg_channel << vc->cfg_channel_sa_shift,
97 vc->cfg_channel_reg); 97 vc->cfg_channel_reg);
98 98
99 return 0; 99 return 0;
100 } 100 }
101 101
102 /* Voltage scale and accessory APIs */ 102 /* Voltage scale and accessory APIs */
103 int omap_vc_pre_scale(struct voltagedomain *voltdm, 103 int omap_vc_pre_scale(struct voltagedomain *voltdm,
104 unsigned long target_volt, 104 unsigned long target_volt,
105 u8 *target_vsel, u8 *current_vsel) 105 u8 *target_vsel, u8 *current_vsel)
106 { 106 {
107 struct omap_vc_channel *vc = voltdm->vc; 107 struct omap_vc_channel *vc = voltdm->vc;
108 u32 vc_cmdval; 108 u32 vc_cmdval;
109 109
110 /* Check if sufficient pmic info is available for this vdd */ 110 /* Check if sufficient pmic info is available for this vdd */
111 if (!voltdm->pmic) { 111 if (!voltdm->pmic) {
112 pr_err("%s: Insufficient pmic info to scale the vdd_%s\n", 112 pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
113 __func__, voltdm->name); 113 __func__, voltdm->name);
114 return -EINVAL; 114 return -EINVAL;
115 } 115 }
116 116
117 if (!voltdm->pmic->uv_to_vsel) { 117 if (!voltdm->pmic->uv_to_vsel) {
118 pr_err("%s: PMIC function to convert voltage in uV to" 118 pr_err("%s: PMIC function to convert voltage in uV to"
119 "vsel not registered. Hence unable to scale voltage" 119 "vsel not registered. Hence unable to scale voltage"
120 "for vdd_%s\n", __func__, voltdm->name); 120 "for vdd_%s\n", __func__, voltdm->name);
121 return -ENODATA; 121 return -ENODATA;
122 } 122 }
123 123
124 if (!voltdm->read || !voltdm->write) { 124 if (!voltdm->read || !voltdm->write) {
125 pr_err("%s: No read/write API for accessing vdd_%s regs\n", 125 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
126 __func__, voltdm->name); 126 __func__, voltdm->name);
127 return -EINVAL; 127 return -EINVAL;
128 } 128 }
129 129
130 *target_vsel = voltdm->pmic->uv_to_vsel(target_volt); 130 *target_vsel = voltdm->pmic->uv_to_vsel(target_volt);
131 *current_vsel = voltdm->pmic->uv_to_vsel(voltdm->nominal_volt); 131 *current_vsel = voltdm->pmic->uv_to_vsel(voltdm->nominal_volt);
132 132
133 /* Setting the ON voltage to the new target voltage */ 133 /* Setting the ON voltage to the new target voltage */
134 vc_cmdval = voltdm->read(vc->cmdval_reg); 134 vc_cmdval = voltdm->read(vc->cmdval_reg);
135 vc_cmdval &= ~vc->common->cmd_on_mask; 135 vc_cmdval &= ~vc->common->cmd_on_mask;
136 vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift); 136 vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
137 voltdm->write(vc_cmdval, vc->cmdval_reg); 137 voltdm->write(vc_cmdval, vc->cmdval_reg);
138 138
139 omap_vp_update_errorgain(voltdm, target_volt); 139 omap_vp_update_errorgain(voltdm, target_volt);
140 140
141 return 0; 141 return 0;
142 } 142 }
143 143
144 void omap_vc_post_scale(struct voltagedomain *voltdm, 144 void omap_vc_post_scale(struct voltagedomain *voltdm,
145 unsigned long target_volt, 145 unsigned long target_volt,
146 u8 target_vsel, u8 current_vsel) 146 u8 target_vsel, u8 current_vsel)
147 { 147 {
148 u32 smps_steps = 0, smps_delay = 0; 148 u32 smps_steps = 0, smps_delay = 0;
149 149
150 smps_steps = abs(target_vsel - current_vsel); 150 smps_steps = abs(target_vsel - current_vsel);
151 /* SMPS slew rate / step size. 2us added as buffer. */ 151 /* SMPS slew rate / step size. 2us added as buffer. */
152 smps_delay = ((smps_steps * voltdm->pmic->step_size) / 152 smps_delay = ((smps_steps * voltdm->pmic->step_size) /
153 voltdm->pmic->slew_rate) + 2; 153 voltdm->pmic->slew_rate) + 2;
154 udelay(smps_delay); 154 udelay(smps_delay);
155 } 155 }
156 156
157 /* vc_bypass_scale - VC bypass method of voltage scaling */ 157 /* vc_bypass_scale - VC bypass method of voltage scaling */
158 int omap_vc_bypass_scale(struct voltagedomain *voltdm, 158 int omap_vc_bypass_scale(struct voltagedomain *voltdm,
159 unsigned long target_volt) 159 unsigned long target_volt)
160 { 160 {
161 struct omap_vc_channel *vc = voltdm->vc; 161 struct omap_vc_channel *vc = voltdm->vc;
162 u32 loop_cnt = 0, retries_cnt = 0; 162 u32 loop_cnt = 0, retries_cnt = 0;
163 u32 vc_valid, vc_bypass_val_reg, vc_bypass_value; 163 u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
164 u8 target_vsel, current_vsel; 164 u8 target_vsel, current_vsel;
165 int ret; 165 int ret;
166 166
167 ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel); 167 ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
168 if (ret) 168 if (ret)
169 return ret; 169 return ret;
170 170
171 vc_valid = vc->common->valid; 171 vc_valid = vc->common->valid;
172 vc_bypass_val_reg = vc->common->bypass_val_reg; 172 vc_bypass_val_reg = vc->common->bypass_val_reg;
173 vc_bypass_value = (target_vsel << vc->common->data_shift) | 173 vc_bypass_value = (target_vsel << vc->common->data_shift) |
174 (vc->volt_reg_addr << vc->common->regaddr_shift) | 174 (vc->volt_reg_addr << vc->common->regaddr_shift) |
175 (vc->i2c_slave_addr << vc->common->slaveaddr_shift); 175 (vc->i2c_slave_addr << vc->common->slaveaddr_shift);
176 176
177 voltdm->write(vc_bypass_value, vc_bypass_val_reg); 177 voltdm->write(vc_bypass_value, vc_bypass_val_reg);
178 voltdm->write(vc_bypass_value | vc_valid, vc_bypass_val_reg); 178 voltdm->write(vc_bypass_value | vc_valid, vc_bypass_val_reg);
179 179
180 vc_bypass_value = voltdm->read(vc_bypass_val_reg); 180 vc_bypass_value = voltdm->read(vc_bypass_val_reg);
181 /* 181 /*
182 * Loop till the bypass command is acknowledged from the SMPS. 182 * Loop till the bypass command is acknowledged from the SMPS.
183 * NOTE: This is legacy code. The loop count and retry count needs 183 * NOTE: This is legacy code. The loop count and retry count needs
184 * to be revisited. 184 * to be revisited.
185 */ 185 */
186 while (!(vc_bypass_value & vc_valid)) { 186 while (!(vc_bypass_value & vc_valid)) {
187 loop_cnt++; 187 loop_cnt++;
188 188
189 if (retries_cnt > 10) { 189 if (retries_cnt > 10) {
190 pr_warning("%s: Retry count exceeded\n", __func__); 190 pr_warning("%s: Retry count exceeded\n", __func__);
191 return -ETIMEDOUT; 191 return -ETIMEDOUT;
192 } 192 }
193 193
194 if (loop_cnt > 50) { 194 if (loop_cnt > 50) {
195 retries_cnt++; 195 retries_cnt++;
196 loop_cnt = 0; 196 loop_cnt = 0;
197 udelay(10); 197 udelay(10);
198 } 198 }
199 vc_bypass_value = voltdm->read(vc_bypass_val_reg); 199 vc_bypass_value = voltdm->read(vc_bypass_val_reg);
200 } 200 }
201 201
202 omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel); 202 omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
203 return 0; 203 return 0;
204 } 204 }
205 205
206 static void __init omap3_vfsm_init(struct voltagedomain *voltdm) 206 static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
207 { 207 {
208 /* 208 /*
209 * Voltage Manager FSM parameters init 209 * Voltage Manager FSM parameters init
210 * XXX This data should be passed in from the board file 210 * XXX This data should be passed in from the board file
211 */ 211 */
212 voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET); 212 voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
213 voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET); 213 voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
214 voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET); 214 voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
215 } 215 }
216 216
217 static void __init omap3_vc_init_channel(struct voltagedomain *voltdm) 217 static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
218 { 218 {
219 static bool is_initialized; 219 static bool is_initialized;
220 220
221 if (is_initialized) 221 if (is_initialized)
222 return; 222 return;
223 223
224 omap3_vfsm_init(voltdm); 224 omap3_vfsm_init(voltdm);
225 225
226 is_initialized = true; 226 is_initialized = true;
227 } 227 }
228 228
229 229
230 /* OMAP4 specific voltage init functions */ 230 /* OMAP4 specific voltage init functions */
231 static void __init omap4_vc_init_channel(struct voltagedomain *voltdm) 231 static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
232 { 232 {
233 static bool is_initialized; 233 static bool is_initialized;
234 u32 vc_val; 234 u32 vc_val;
235 235
236 if (is_initialized) 236 if (is_initialized)
237 return; 237 return;
238 238
239 /* XXX These are magic numbers and do not belong! */ 239 /* XXX These are magic numbers and do not belong! */
240 vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT); 240 vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
241 voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET); 241 voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
242 242
243 is_initialized = true; 243 is_initialized = true;
244 } 244 }
245 245
246 /** 246 /**
247 * omap_vc_i2c_init - initialize I2C interface to PMIC 247 * omap_vc_i2c_init - initialize I2C interface to PMIC
248 * @voltdm: voltage domain containing VC data 248 * @voltdm: voltage domain containing VC data
249 * 249 *
250 * Use PMIC supplied seetings for I2C high-speed mode and 250 * Use PMIC supplied seetings for I2C high-speed mode and
251 * master code (if set) and program the VC I2C configuration 251 * master code (if set) and program the VC I2C configuration
252 * register. 252 * register.
253 * 253 *
254 * The VC I2C configuration is common to all VC channels, 254 * The VC I2C configuration is common to all VC channels,
255 * so this function only configures I2C for the first VC 255 * so this function only configures I2C for the first VC
256 * channel registers. All other VC channels will use the 256 * channel registers. All other VC channels will use the
257 * same configuration. 257 * same configuration.
258 */ 258 */
259 static void __init omap_vc_i2c_init(struct voltagedomain *voltdm) 259 static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
260 { 260 {
261 struct omap_vc_channel *vc = voltdm->vc; 261 struct omap_vc_channel *vc = voltdm->vc;
262 static bool initialized; 262 static bool initialized;
263 static bool i2c_high_speed; 263 static bool i2c_high_speed;
264 u8 mcode; 264 u8 mcode;
265 265
266 if (initialized) { 266 if (initialized) {
267 if (voltdm->pmic->i2c_high_speed != i2c_high_speed) 267 if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
268 pr_warn("%s: I2C config for all channels must match.", 268 pr_warn("%s: I2C config for all channels must match.",
269 __func__); 269 __func__);
270 return; 270 return;
271 } 271 }
272 272
273 i2c_high_speed = voltdm->pmic->i2c_high_speed; 273 i2c_high_speed = voltdm->pmic->i2c_high_speed;
274 if (i2c_high_speed) 274 if (i2c_high_speed)
275 voltdm->rmw(vc->common->i2c_cfg_hsen_mask, 275 voltdm->rmw(vc->common->i2c_cfg_hsen_mask,
276 vc->common->i2c_cfg_hsen_mask, 276 vc->common->i2c_cfg_hsen_mask,
277 vc->common->i2c_cfg_reg); 277 vc->common->i2c_cfg_reg);
278 278
279 mcode = voltdm->pmic->i2c_mcode; 279 mcode = voltdm->pmic->i2c_mcode;
280 if (mcode) 280 if (mcode)
281 voltdm->rmw(vc->common->i2c_mcode_mask, 281 voltdm->rmw(vc->common->i2c_mcode_mask,
282 mcode << __ffs(vc->common->i2c_mcode_mask), 282 mcode << __ffs(vc->common->i2c_mcode_mask),
283 vc->common->i2c_cfg_reg); 283 vc->common->i2c_cfg_reg);
284 284
285 initialized = true; 285 initialized = true;
286 } 286 }
287 287
288 void __init omap_vc_init_channel(struct voltagedomain *voltdm) 288 void __init omap_vc_init_channel(struct voltagedomain *voltdm)
289 { 289 {
290 struct omap_vc_channel *vc = voltdm->vc; 290 struct omap_vc_channel *vc = voltdm->vc;
291 u8 on_vsel, onlp_vsel, ret_vsel, off_vsel; 291 u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
292 u32 val; 292 u32 val;
293 293
294 if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) { 294 if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
295 pr_err("%s: PMIC info requried to configure vc for" 295 pr_err("%s: PMIC info requried to configure vc for"
296 "vdd_%s not populated.Hence cannot initialize vc\n", 296 "vdd_%s not populated.Hence cannot initialize vc\n",
297 __func__, voltdm->name); 297 __func__, voltdm->name);
298 return; 298 return;
299 } 299 }
300 300
301 if (!voltdm->read || !voltdm->write) { 301 if (!voltdm->read || !voltdm->write) {
302 pr_err("%s: No read/write API for accessing vdd_%s regs\n", 302 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
303 __func__, voltdm->name); 303 __func__, voltdm->name);
304 return; 304 return;
305 } 305 }
306 306
307 vc->cfg_channel = 0; 307 vc->cfg_channel = 0;
308 if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT) 308 if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT)
309 vc_cfg_bits = &vc_mutant_channel_cfg; 309 vc_cfg_bits = &vc_mutant_channel_cfg;
310 else 310 else
311 vc_cfg_bits = &vc_default_channel_cfg; 311 vc_cfg_bits = &vc_default_channel_cfg;
312 312
313 /* get PMIC/board specific settings */ 313 /* get PMIC/board specific settings */
314 vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr; 314 vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
315 vc->volt_reg_addr = voltdm->pmic->volt_reg_addr; 315 vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
316 vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr; 316 vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
317 vc->setup_time = voltdm->pmic->volt_setup_time; 317 vc->setup_time = voltdm->pmic->volt_setup_time;
318 318
319 /* Configure the i2c slave address for this VC */ 319 /* Configure the i2c slave address for this VC */
320 voltdm->rmw(vc->smps_sa_mask, 320 voltdm->rmw(vc->smps_sa_mask,
321 vc->i2c_slave_addr << __ffs(vc->smps_sa_mask), 321 vc->i2c_slave_addr << __ffs(vc->smps_sa_mask),
322 vc->smps_sa_reg); 322 vc->smps_sa_reg);
323 vc->cfg_channel |= vc_cfg_bits->sa; 323 vc->cfg_channel |= vc_cfg_bits->sa;
324 324
325 /* 325 /*
326 * Configure the PMIC register addresses. 326 * Configure the PMIC register addresses.
327 */ 327 */
328 voltdm->rmw(vc->smps_volra_mask, 328 voltdm->rmw(vc->smps_volra_mask,
329 vc->volt_reg_addr << __ffs(vc->smps_volra_mask), 329 vc->volt_reg_addr << __ffs(vc->smps_volra_mask),
330 vc->smps_volra_reg); 330 vc->smps_volra_reg);
331 vc->cfg_channel |= vc_cfg_bits->rav; 331 vc->cfg_channel |= vc_cfg_bits->rav;
332 332
333 if (vc->cmd_reg_addr) { 333 if (vc->cmd_reg_addr) {
334 voltdm->rmw(vc->smps_cmdra_mask, 334 voltdm->rmw(vc->smps_cmdra_mask,
335 vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask), 335 vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask),
336 vc->smps_cmdra_reg); 336 vc->smps_cmdra_reg);
337 vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen; 337 vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen;
338 } 338 }
339 339
340 /* Set up the on, inactive, retention and off voltage */ 340 /* Set up the on, inactive, retention and off voltage */
341 on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt); 341 on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt);
342 onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt); 342 onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt);
343 ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt); 343 ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt);
344 off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt); 344 off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt);
345 val = ((on_vsel << vc->common->cmd_on_shift) | 345 val = ((on_vsel << vc->common->cmd_on_shift) |
346 (onlp_vsel << vc->common->cmd_onlp_shift) | 346 (onlp_vsel << vc->common->cmd_onlp_shift) |
347 (ret_vsel << vc->common->cmd_ret_shift) | 347 (ret_vsel << vc->common->cmd_ret_shift) |
348 (off_vsel << vc->common->cmd_off_shift)); 348 (off_vsel << vc->common->cmd_off_shift));
349 voltdm->write(val, vc->cmdval_reg); 349 voltdm->write(val, vc->cmdval_reg);
350 vc->cfg_channel |= vc_cfg_bits->cmd; 350 vc->cfg_channel |= vc_cfg_bits->cmd;
351 351
352 /* Channel configuration */ 352 /* Channel configuration */
353 omap_vc_config_channel(voltdm); 353 omap_vc_config_channel(voltdm);
354 354
355 /* Configure the setup times */ 355 /* Configure the setup times */
356 voltdm->rmw(voltdm->vfsm->voltsetup_mask, 356 voltdm->rmw(voltdm->vfsm->voltsetup_mask,
357 vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask), 357 vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
358 voltdm->vfsm->voltsetup_reg); 358 voltdm->vfsm->voltsetup_reg);
359 359
360 omap_vc_i2c_init(voltdm); 360 omap_vc_i2c_init(voltdm);
361 361
362 if (cpu_is_omap34xx()) 362 if (cpu_is_omap34xx())
363 omap3_vc_init_channel(voltdm); 363 omap3_vc_init_channel(voltdm);
364 else if (cpu_is_omap44xx()) 364 else if (cpu_is_omap44xx())
365 omap4_vc_init_channel(voltdm); 365 omap4_vc_init_channel(voltdm);
366 } 366 }
arch/arm/mach-omap2/vc.h
1 /* File was deleted
2 * OMAP3/4 Voltage Controller (VC) structure and macro definitions
3 *
4 * Copyright (C) 2007, 2010 Texas Instruments, Inc.
5 * Rajendra Nayak <rnayak@ti.com>
6 * Lesly A M <x0080970@ti.com>
7 * Thara Gopinath <thara@ti.com>
8 *
9 * Copyright (C) 2008, 2011 Nokia Corporation
10 * Kalle Jokiniemi
11 * Paul Walmsley
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License version
15 * 2 as published by the Free Software Foundation.
16 */
17 #ifndef __ARCH_ARM_MACH_OMAP2_VC_H
18 #define __ARCH_ARM_MACH_OMAP2_VC_H
19
20 #include <linux/kernel.h>
21
22 struct voltagedomain;
23
24 /**
25 * struct omap_vc_common - per-VC register/bitfield data
26 * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register
27 * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register
28 * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start
29 * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register
30 * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register
31 * @regaddr_shift: REGADDR field shift in PRM_VC_BYPASS_VAL register
32 * @cmd_on_shift: ON field shift in PRM_VC_CMD_VAL_* register
33 * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register
34 * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
35 * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
36 * @i2c_cfg_reg: I2C configuration register offset
37 * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register
38 * @i2c_mcode_mask: MCODE field mask for I2C config register
39 *
40 * XXX One of cmd_on_mask and cmd_on_shift are not needed
41 * XXX VALID should probably be a shift, not a mask
42 */
43 struct omap_vc_common {
44 u32 cmd_on_mask;
45 u32 valid;
46 u8 bypass_val_reg;
47 u8 data_shift;
48 u8 slaveaddr_shift;
49 u8 regaddr_shift;
50 u8 cmd_on_shift;
51 u8 cmd_onlp_shift;
52 u8 cmd_ret_shift;
53 u8 cmd_off_shift;
54 u8 i2c_cfg_reg;
55 u8 i2c_cfg_hsen_mask;
56 u8 i2c_mcode_mask;
57 };
58
59 /* omap_vc_channel.flags values */
60 #define OMAP_VC_CHANNEL_DEFAULT BIT(0)
61 #define OMAP_VC_CHANNEL_CFG_MUTANT BIT(1)
62
63 /**
64 * struct omap_vc_channel - VC per-instance data
65 * @i2c_slave_addr: I2C slave address of PMIC for this VC channel
66 * @volt_reg_addr: voltage configuration register address
67 * @cmd_reg_addr: command configuration register address
68 * @setup_time: setup time (in sys_clk cycles) of regulator for this channel
69 * @cfg_channel: current value of VC channel configuration register
70 * @i2c_high_speed: whether or not to use I2C high-speed mode
71 *
72 * @common: pointer to VC common data for this platform
73 * @smps_sa_mask: i2c slave address bitmask in the PRM_VC_SMPS_SA register
74 * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
75 * @smps_cmdra_mask: CMDRA* bitmask in the PRM_VC_CMD_RA register
76 * @cmdval_reg: register for on/ret/off voltage level values for this channel
77 * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
78 * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
79 * @smps_cmdra_reg: Offset of PRM_VC_SMPS_CMD_RA reg from PRM start
80 * @cfg_channel_reg: VC channel configuration register
81 * @cfg_channel_sa_shift: bit shift for slave address cfg_channel register
82 * @flags: VC channel-specific flags (optional)
83 */
84 struct omap_vc_channel {
85 /* channel state */
86 u16 i2c_slave_addr;
87 u16 volt_reg_addr;
88 u16 cmd_reg_addr;
89 u16 setup_time;
90 u8 cfg_channel;
91 bool i2c_high_speed;
92
93 /* register access data */
94 const struct omap_vc_common *common;
95 u32 smps_sa_mask;
96 u32 smps_volra_mask;
97 u32 smps_cmdra_mask;
98 u8 cmdval_reg;
99 u8 smps_sa_reg;
100 u8 smps_volra_reg;
101 u8 smps_cmdra_reg;
102 u8 cfg_channel_reg;
103 u8 cfg_channel_sa_shift;
104 u8 flags;
105 };
106
107 extern struct omap_vc_channel omap3_vc_mpu;
108 extern struct omap_vc_channel omap3_vc_core;
109
110 extern struct omap_vc_channel omap4_vc_mpu;
111 extern struct omap_vc_channel omap4_vc_iva;
112 extern struct omap_vc_channel omap4_vc_core;
113
114 void omap_vc_init_channel(struct voltagedomain *voltdm);
115 int omap_vc_pre_scale(struct voltagedomain *voltdm,
116 unsigned long target_volt,
117 u8 *target_vsel, u8 *current_vsel);
118 void omap_vc_post_scale(struct voltagedomain *voltdm,
119 unsigned long target_volt,
120 u8 target_vsel, u8 current_vsel);
121 int omap_vc_bypass_scale(struct voltagedomain *voltdm,
122 unsigned long target_volt);
123
124 #endif
125 1 /*
126 2 * OMAP3/4 Voltage Controller (VC) structure and macro definitions
arch/arm/mach-omap2/vc3xxx_data.c
1 /* 1 /*
2 * OMAP3 Voltage Controller (VC) data 2 * OMAP3 Voltage Controller (VC) data
3 * 3 *
4 * Copyright (C) 2007, 2010 Texas Instruments, Inc. 4 * Copyright (C) 2007, 2010 Texas Instruments, Inc.
5 * Rajendra Nayak <rnayak@ti.com> 5 * Rajendra Nayak <rnayak@ti.com>
6 * Lesly A M <x0080970@ti.com> 6 * Lesly A M <x0080970@ti.com>
7 * Thara Gopinath <thara@ti.com> 7 * Thara Gopinath <thara@ti.com>
8 * 8 *
9 * Copyright (C) 2008, 2011 Nokia Corporation 9 * Copyright (C) 2008, 2011 Nokia Corporation
10 * Kalle Jokiniemi 10 * Kalle Jokiniemi
11 * Paul Walmsley 11 * Paul Walmsley
12 * 12 *
13 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as 14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation. 15 * published by the Free Software Foundation.
16 */ 16 */
17 #include <linux/io.h> 17 #include <linux/io.h>
18 #include <linux/err.h> 18 #include <linux/err.h>
19 #include <linux/init.h> 19 #include <linux/init.h>
20 20
21 #include <plat/common.h> 21 #include <plat/common.h>
22 #include <plat/voltage.h>
23 #include <plat/vc.h>
22 24
23 #include "prm-regbits-34xx.h" 25 #include "prm-regbits-34xx.h"
24 #include "voltage.h"
25
26 #include "vc.h"
27 26
28 /* 27 /*
29 * VC data common to 34xx/36xx chips 28 * VC data common to 34xx/36xx chips
30 * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file. 29 * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
31 */ 30 */
32 static struct omap_vc_common omap3_vc_common = { 31 static struct omap_vc_common omap3_vc_common = {
33 .bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET, 32 .bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET,
34 .data_shift = OMAP3430_DATA_SHIFT, 33 .data_shift = OMAP3430_DATA_SHIFT,
35 .slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT, 34 .slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT,
36 .regaddr_shift = OMAP3430_REGADDR_SHIFT, 35 .regaddr_shift = OMAP3430_REGADDR_SHIFT,
37 .valid = OMAP3430_VALID_MASK, 36 .valid = OMAP3430_VALID_MASK,
38 .cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT, 37 .cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT,
39 .cmd_on_mask = OMAP3430_VC_CMD_ON_MASK, 38 .cmd_on_mask = OMAP3430_VC_CMD_ON_MASK,
40 .cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT, 39 .cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT,
41 .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT, 40 .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT,
42 .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT, 41 .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT,
43 .i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK, 42 .i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK,
44 .i2c_cfg_reg = OMAP3_PRM_VC_I2C_CFG_OFFSET, 43 .i2c_cfg_reg = OMAP3_PRM_VC_I2C_CFG_OFFSET,
45 .i2c_mcode_mask = OMAP3430_MCODE_MASK, 44 .i2c_mcode_mask = OMAP3430_MCODE_MASK,
46 }; 45 };
47 46
48 struct omap_vc_channel omap3_vc_mpu = { 47 struct omap_vc_channel omap3_vc_mpu = {
49 .common = &omap3_vc_common, 48 .common = &omap3_vc_common,
50 .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET, 49 .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET,
51 .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET, 50 .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
52 .smps_cmdra_reg = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET, 51 .smps_cmdra_reg = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
53 .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET, 52 .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
54 .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET, 53 .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET,
55 .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK, 54 .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK,
56 .smps_volra_mask = OMAP3430_VOLRA0_MASK, 55 .smps_volra_mask = OMAP3430_VOLRA0_MASK,
57 .smps_cmdra_mask = OMAP3430_CMDRA0_MASK, 56 .smps_cmdra_mask = OMAP3430_CMDRA0_MASK,
58 .cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT, 57 .cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
59 }; 58 };
60 59
61 struct omap_vc_channel omap3_vc_core = { 60 struct omap_vc_channel omap3_vc_core = {
62 .common = &omap3_vc_common, 61 .common = &omap3_vc_common,
63 .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET, 62 .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET,
64 .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET, 63 .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
65 .smps_cmdra_reg = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET, 64 .smps_cmdra_reg = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
66 .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET, 65 .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
67 .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET, 66 .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET,
68 .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK, 67 .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK,
69 .smps_volra_mask = OMAP3430_VOLRA1_MASK, 68 .smps_volra_mask = OMAP3430_VOLRA1_MASK,
70 .smps_cmdra_mask = OMAP3430_CMDRA1_MASK, 69 .smps_cmdra_mask = OMAP3430_CMDRA1_MASK,
71 .cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT, 70 .cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
arch/arm/mach-omap2/vc44xx_data.c
1 /* 1 /*
2 * OMAP4 Voltage Controller (VC) data 2 * OMAP4 Voltage Controller (VC) data
3 * 3 *
4 * Copyright (C) 2007, 2010 Texas Instruments, Inc. 4 * Copyright (C) 2007, 2010 Texas Instruments, Inc.
5 * Rajendra Nayak <rnayak@ti.com> 5 * Rajendra Nayak <rnayak@ti.com>
6 * Lesly A M <x0080970@ti.com> 6 * Lesly A M <x0080970@ti.com>
7 * Thara Gopinath <thara@ti.com> 7 * Thara Gopinath <thara@ti.com>
8 * 8 *
9 * Copyright (C) 2008, 2011 Nokia Corporation 9 * Copyright (C) 2008, 2011 Nokia Corporation
10 * Kalle Jokiniemi 10 * Kalle Jokiniemi
11 * Paul Walmsley 11 * Paul Walmsley
12 * 12 *
13 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as 14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation. 15 * published by the Free Software Foundation.
16 */ 16 */
17 #include <linux/io.h> 17 #include <linux/io.h>
18 #include <linux/err.h> 18 #include <linux/err.h>
19 #include <linux/init.h> 19 #include <linux/init.h>
20 20
21 #include <plat/common.h> 21 #include <plat/common.h>
22 #include <plat/vc.h>
22 23
23 #include "prm44xx.h" 24 #include "prm44xx.h"
24 #include "prm-regbits-44xx.h" 25 #include "prm-regbits-44xx.h"
25 #include "voltage.h" 26 #include "voltage.h"
26
27 #include "vc.h"
28 27
29 /* 28 /*
30 * VC data common to 44xx chips 29 * VC data common to 44xx chips
31 * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file. 30 * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
32 */ 31 */
33 static const struct omap_vc_common omap4_vc_common = { 32 static const struct omap_vc_common omap4_vc_common = {
34 .bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET, 33 .bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET,
35 .data_shift = OMAP4430_DATA_SHIFT, 34 .data_shift = OMAP4430_DATA_SHIFT,
36 .slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT, 35 .slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT,
37 .regaddr_shift = OMAP4430_REGADDR_SHIFT, 36 .regaddr_shift = OMAP4430_REGADDR_SHIFT,
38 .valid = OMAP4430_VALID_MASK, 37 .valid = OMAP4430_VALID_MASK,
39 .cmd_on_shift = OMAP4430_ON_SHIFT, 38 .cmd_on_shift = OMAP4430_ON_SHIFT,
40 .cmd_on_mask = OMAP4430_ON_MASK, 39 .cmd_on_mask = OMAP4430_ON_MASK,
41 .cmd_onlp_shift = OMAP4430_ONLP_SHIFT, 40 .cmd_onlp_shift = OMAP4430_ONLP_SHIFT,
42 .cmd_ret_shift = OMAP4430_RET_SHIFT, 41 .cmd_ret_shift = OMAP4430_RET_SHIFT,
43 .cmd_off_shift = OMAP4430_OFF_SHIFT, 42 .cmd_off_shift = OMAP4430_OFF_SHIFT,
44 .i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET, 43 .i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET,
45 .i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK, 44 .i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK,
46 .i2c_mcode_mask = OMAP4430_HSMCODE_MASK, 45 .i2c_mcode_mask = OMAP4430_HSMCODE_MASK,
47 }; 46 };
48 47
49 /* VC instance data for each controllable voltage line */ 48 /* VC instance data for each controllable voltage line */
50 struct omap_vc_channel omap4_vc_mpu = { 49 struct omap_vc_channel omap4_vc_mpu = {
51 .flags = OMAP_VC_CHANNEL_DEFAULT | OMAP_VC_CHANNEL_CFG_MUTANT, 50 .flags = OMAP_VC_CHANNEL_DEFAULT | OMAP_VC_CHANNEL_CFG_MUTANT,
52 .common = &omap4_vc_common, 51 .common = &omap4_vc_common,
53 .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET, 52 .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
54 .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET, 53 .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
55 .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET, 54 .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
56 .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET, 55 .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
57 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET, 56 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET,
58 .smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK, 57 .smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK,
59 .smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK, 58 .smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK,
60 .smps_cmdra_mask = OMAP4430_CMDRA_VDD_MPU_L_MASK, 59 .smps_cmdra_mask = OMAP4430_CMDRA_VDD_MPU_L_MASK,
61 .cfg_channel_sa_shift = OMAP4430_SA_VDD_MPU_L_SHIFT, 60 .cfg_channel_sa_shift = OMAP4430_SA_VDD_MPU_L_SHIFT,
62 }; 61 };
63 62
64 struct omap_vc_channel omap4_vc_iva = { 63 struct omap_vc_channel omap4_vc_iva = {
65 .common = &omap4_vc_common, 64 .common = &omap4_vc_common,
66 .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET, 65 .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
67 .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET, 66 .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
68 .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET, 67 .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
69 .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET, 68 .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
70 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET, 69 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET,
71 .smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK, 70 .smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK,
72 .smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK, 71 .smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK,
73 .smps_cmdra_mask = OMAP4430_CMDRA_VDD_IVA_L_MASK, 72 .smps_cmdra_mask = OMAP4430_CMDRA_VDD_IVA_L_MASK,
74 .cfg_channel_sa_shift = OMAP4430_SA_VDD_IVA_L_SHIFT, 73 .cfg_channel_sa_shift = OMAP4430_SA_VDD_IVA_L_SHIFT,
75 }; 74 };
76 75
77 struct omap_vc_channel omap4_vc_core = { 76 struct omap_vc_channel omap4_vc_core = {
78 .common = &omap4_vc_common, 77 .common = &omap4_vc_common,
79 .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET, 78 .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
80 .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET, 79 .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
81 .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET, 80 .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
82 .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET, 81 .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
83 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET, 82 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET,
84 .smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK, 83 .smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK,
85 .smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK, 84 .smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK,
86 .smps_cmdra_mask = OMAP4430_CMDRA_VDD_CORE_L_MASK, 85 .smps_cmdra_mask = OMAP4430_CMDRA_VDD_CORE_L_MASK,
87 .cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT, 86 .cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT,
88 }; 87 };
89 88
arch/arm/mach-omap2/voltage.c
1 /* 1 /*
2 * OMAP3/OMAP4 Voltage Management Routines 2 * OMAP3/OMAP4 Voltage Management Routines
3 * 3 *
4 * Author: Thara Gopinath <thara@ti.com> 4 * Author: Thara Gopinath <thara@ti.com>
5 * 5 *
6 * Copyright (C) 2007 Texas Instruments, Inc. 6 * Copyright (C) 2007 Texas Instruments, Inc.
7 * Rajendra Nayak <rnayak@ti.com> 7 * Rajendra Nayak <rnayak@ti.com>
8 * Lesly A M <x0080970@ti.com> 8 * Lesly A M <x0080970@ti.com>
9 * 9 *
10 * Copyright (C) 2008, 2011 Nokia Corporation 10 * Copyright (C) 2008, 2011 Nokia Corporation
11 * Kalle Jokiniemi 11 * Kalle Jokiniemi
12 * Paul Walmsley 12 * Paul Walmsley
13 * 13 *
14 * Copyright (C) 2010 Texas Instruments, Inc. 14 * Copyright (C) 2010 Texas Instruments, Inc.
15 * Thara Gopinath <thara@ti.com> 15 * Thara Gopinath <thara@ti.com>
16 * 16 *
17 * This program is free software; you can redistribute it and/or modify 17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License version 2 as 18 * it under the terms of the GNU General Public License version 2 as
19 * published by the Free Software Foundation. 19 * published by the Free Software Foundation.
20 */ 20 */
21 21
22 #include <linux/delay.h> 22 #include <linux/delay.h>
23 #include <linux/io.h> 23 #include <linux/io.h>
24 #include <linux/err.h> 24 #include <linux/err.h>
25 #include <linux/debugfs.h> 25 #include <linux/debugfs.h>
26 #include <linux/slab.h> 26 #include <linux/slab.h>
27 #include <linux/clk.h> 27 #include <linux/clk.h>
28 28
29 #include <plat/common.h> 29 #include <plat/common.h>
30 #include <plat/voltage.h>
31 #include <plat/vc.h>
32 #include <plat/vp.h>
30 33
31 #include "prm-regbits-34xx.h" 34 #include "prm-regbits-34xx.h"
32 #include "prm-regbits-44xx.h" 35 #include "prm-regbits-44xx.h"
33 #include "prm44xx.h" 36 #include "prm44xx.h"
34 #include "prcm44xx.h" 37 #include "prcm44xx.h"
35 #include "prminst44xx.h" 38 #include "prminst44xx.h"
36 #include "control.h" 39 #include "control.h"
37 40
38 #include "voltage.h"
39 #include "powerdomain.h" 41 #include "powerdomain.h"
40
41 #include "vc.h"
42 #include "vp.h"
43 42
44 static LIST_HEAD(voltdm_list); 43 static LIST_HEAD(voltdm_list);
45 44
46 /* Public functions */ 45 /* Public functions */
47 /** 46 /**
48 * voltdm_get_voltage() - Gets the current non-auto-compensated voltage 47 * voltdm_get_voltage() - Gets the current non-auto-compensated voltage
49 * @voltdm: pointer to the voltdm for which current voltage info is needed 48 * @voltdm: pointer to the voltdm for which current voltage info is needed
50 * 49 *
51 * API to get the current non-auto-compensated voltage for a voltage domain. 50 * API to get the current non-auto-compensated voltage for a voltage domain.
52 * Returns 0 in case of error else returns the current voltage. 51 * Returns 0 in case of error else returns the current voltage.
53 */ 52 */
54 unsigned long voltdm_get_voltage(struct voltagedomain *voltdm) 53 unsigned long voltdm_get_voltage(struct voltagedomain *voltdm)
55 { 54 {
56 if (!voltdm || IS_ERR(voltdm)) { 55 if (!voltdm || IS_ERR(voltdm)) {
57 pr_warning("%s: VDD specified does not exist!\n", __func__); 56 pr_warning("%s: VDD specified does not exist!\n", __func__);
58 return 0; 57 return 0;
59 } 58 }
60 59
61 return voltdm->nominal_volt; 60 return voltdm->nominal_volt;
62 } 61 }
63 62
64 /** 63 /**
65 * voltdm_scale() - API to scale voltage of a particular voltage domain. 64 * voltdm_scale() - API to scale voltage of a particular voltage domain.
66 * @voltdm: pointer to the voltage domain which is to be scaled. 65 * @voltdm: pointer to the voltage domain which is to be scaled.
67 * @target_volt: The target voltage of the voltage domain 66 * @target_volt: The target voltage of the voltage domain
68 * 67 *
69 * This API should be called by the kernel to do the voltage scaling 68 * This API should be called by the kernel to do the voltage scaling
70 * for a particular voltage domain during DVFS. 69 * for a particular voltage domain during DVFS.
71 */ 70 */
72 int voltdm_scale(struct voltagedomain *voltdm, 71 int voltdm_scale(struct voltagedomain *voltdm,
73 unsigned long target_volt) 72 unsigned long target_volt)
74 { 73 {
75 int ret; 74 int ret;
76 75
77 if (!voltdm || IS_ERR(voltdm)) { 76 if (!voltdm || IS_ERR(voltdm)) {
78 pr_warning("%s: VDD specified does not exist!\n", __func__); 77 pr_warning("%s: VDD specified does not exist!\n", __func__);
79 return -EINVAL; 78 return -EINVAL;
80 } 79 }
81 80
82 if (!voltdm->scale) { 81 if (!voltdm->scale) {
83 pr_err("%s: No voltage scale API registered for vdd_%s\n", 82 pr_err("%s: No voltage scale API registered for vdd_%s\n",
84 __func__, voltdm->name); 83 __func__, voltdm->name);
85 return -ENODATA; 84 return -ENODATA;
86 } 85 }
87 86
88 ret = voltdm->scale(voltdm, target_volt); 87 ret = voltdm->scale(voltdm, target_volt);
89 if (!ret) 88 if (!ret)
90 voltdm->nominal_volt = target_volt; 89 voltdm->nominal_volt = target_volt;
91 90
92 return ret; 91 return ret;
93 } 92 }
94 93
95 /** 94 /**
96 * voltdm_reset() - Resets the voltage of a particular voltage domain 95 * voltdm_reset() - Resets the voltage of a particular voltage domain
97 * to that of the current OPP. 96 * to that of the current OPP.
98 * @voltdm: pointer to the voltage domain whose voltage is to be reset. 97 * @voltdm: pointer to the voltage domain whose voltage is to be reset.
99 * 98 *
100 * This API finds out the correct voltage the voltage domain is supposed 99 * This API finds out the correct voltage the voltage domain is supposed
101 * to be at and resets the voltage to that level. Should be used especially 100 * to be at and resets the voltage to that level. Should be used especially
102 * while disabling any voltage compensation modules. 101 * while disabling any voltage compensation modules.
103 */ 102 */
104 void voltdm_reset(struct voltagedomain *voltdm) 103 void voltdm_reset(struct voltagedomain *voltdm)
105 { 104 {
106 unsigned long target_volt; 105 unsigned long target_volt;
107 106
108 if (!voltdm || IS_ERR(voltdm)) { 107 if (!voltdm || IS_ERR(voltdm)) {
109 pr_warning("%s: VDD specified does not exist!\n", __func__); 108 pr_warning("%s: VDD specified does not exist!\n", __func__);
110 return; 109 return;
111 } 110 }
112 111
113 target_volt = voltdm_get_voltage(voltdm); 112 target_volt = voltdm_get_voltage(voltdm);
114 if (!target_volt) { 113 if (!target_volt) {
115 pr_err("%s: unable to find current voltage for vdd_%s\n", 114 pr_err("%s: unable to find current voltage for vdd_%s\n",
116 __func__, voltdm->name); 115 __func__, voltdm->name);
117 return; 116 return;
118 } 117 }
119 118
120 voltdm_scale(voltdm, target_volt); 119 voltdm_scale(voltdm, target_volt);
121 } 120 }
122 121
123 /** 122 /**
124 * omap_voltage_get_volttable() - API to get the voltage table associated with a 123 * omap_voltage_get_volttable() - API to get the voltage table associated with a
125 * particular voltage domain. 124 * particular voltage domain.
126 * @voltdm: pointer to the VDD for which the voltage table is required 125 * @voltdm: pointer to the VDD for which the voltage table is required
127 * @volt_data: the voltage table for the particular vdd which is to be 126 * @volt_data: the voltage table for the particular vdd which is to be
128 * populated by this API 127 * populated by this API
129 * 128 *
130 * This API populates the voltage table associated with a VDD into the 129 * This API populates the voltage table associated with a VDD into the
131 * passed parameter pointer. Returns the count of distinct voltages 130 * passed parameter pointer. Returns the count of distinct voltages
132 * supported by this vdd. 131 * supported by this vdd.
133 * 132 *
134 */ 133 */
135 void omap_voltage_get_volttable(struct voltagedomain *voltdm, 134 void omap_voltage_get_volttable(struct voltagedomain *voltdm,
136 struct omap_volt_data **volt_data) 135 struct omap_volt_data **volt_data)
137 { 136 {
138 if (!voltdm || IS_ERR(voltdm)) { 137 if (!voltdm || IS_ERR(voltdm)) {
139 pr_warning("%s: VDD specified does not exist!\n", __func__); 138 pr_warning("%s: VDD specified does not exist!\n", __func__);
140 return; 139 return;
141 } 140 }
142 141
143 *volt_data = voltdm->volt_data; 142 *volt_data = voltdm->volt_data;
144 } 143 }
145 144
146 /** 145 /**
147 * omap_voltage_get_voltdata() - API to get the voltage table entry for a 146 * omap_voltage_get_voltdata() - API to get the voltage table entry for a
148 * particular voltage 147 * particular voltage
149 * @voltdm: pointer to the VDD whose voltage table has to be searched 148 * @voltdm: pointer to the VDD whose voltage table has to be searched
150 * @volt: the voltage to be searched in the voltage table 149 * @volt: the voltage to be searched in the voltage table
151 * 150 *
152 * This API searches through the voltage table for the required voltage 151 * This API searches through the voltage table for the required voltage
153 * domain and tries to find a matching entry for the passed voltage volt. 152 * domain and tries to find a matching entry for the passed voltage volt.
154 * If a matching entry is found volt_data is populated with that entry. 153 * If a matching entry is found volt_data is populated with that entry.
155 * This API searches only through the non-compensated voltages int the 154 * This API searches only through the non-compensated voltages int the
156 * voltage table. 155 * voltage table.
157 * Returns pointer to the voltage table entry corresponding to volt on 156 * Returns pointer to the voltage table entry corresponding to volt on
158 * success. Returns -ENODATA if no voltage table exisits for the passed voltage 157 * success. Returns -ENODATA if no voltage table exisits for the passed voltage
159 * domain or if there is no matching entry. 158 * domain or if there is no matching entry.
160 */ 159 */
161 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, 160 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
162 unsigned long volt) 161 unsigned long volt)
163 { 162 {
164 int i; 163 int i;
165 164
166 if (!voltdm || IS_ERR(voltdm)) { 165 if (!voltdm || IS_ERR(voltdm)) {
167 pr_warning("%s: VDD specified does not exist!\n", __func__); 166 pr_warning("%s: VDD specified does not exist!\n", __func__);
168 return ERR_PTR(-EINVAL); 167 return ERR_PTR(-EINVAL);
169 } 168 }
170 169
171 if (!voltdm->volt_data) { 170 if (!voltdm->volt_data) {
172 pr_warning("%s: voltage table does not exist for vdd_%s\n", 171 pr_warning("%s: voltage table does not exist for vdd_%s\n",
173 __func__, voltdm->name); 172 __func__, voltdm->name);
174 return ERR_PTR(-ENODATA); 173 return ERR_PTR(-ENODATA);
175 } 174 }
176 175
177 for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) { 176 for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
178 if (voltdm->volt_data[i].volt_nominal == volt) 177 if (voltdm->volt_data[i].volt_nominal == volt)
179 return &voltdm->volt_data[i]; 178 return &voltdm->volt_data[i];
180 } 179 }
181 180
182 pr_notice("%s: Unable to match the current voltage with the voltage" 181 pr_notice("%s: Unable to match the current voltage with the voltage"
183 "table for vdd_%s\n", __func__, voltdm->name); 182 "table for vdd_%s\n", __func__, voltdm->name);
184 183
185 return ERR_PTR(-ENODATA); 184 return ERR_PTR(-ENODATA);
186 } 185 }
187 186
188 /** 187 /**
189 * omap_voltage_register_pmic() - API to register PMIC specific data 188 * omap_voltage_register_pmic() - API to register PMIC specific data
190 * @voltdm: pointer to the VDD for which the PMIC specific data is 189 * @voltdm: pointer to the VDD for which the PMIC specific data is
191 * to be registered 190 * to be registered
192 * @pmic: the structure containing pmic info 191 * @pmic: the structure containing pmic info
193 * 192 *
194 * This API is to be called by the SOC/PMIC file to specify the 193 * This API is to be called by the SOC/PMIC file to specify the
195 * pmic specific info as present in omap_voltdm_pmic structure. 194 * pmic specific info as present in omap_voltdm_pmic structure.
196 */ 195 */
197 int omap_voltage_register_pmic(struct voltagedomain *voltdm, 196 int omap_voltage_register_pmic(struct voltagedomain *voltdm,
198 struct omap_voltdm_pmic *pmic) 197 struct omap_voltdm_pmic *pmic)
199 { 198 {
200 if (!voltdm || IS_ERR(voltdm)) { 199 if (!voltdm || IS_ERR(voltdm)) {
201 pr_warning("%s: VDD specified does not exist!\n", __func__); 200 pr_warning("%s: VDD specified does not exist!\n", __func__);
202 return -EINVAL; 201 return -EINVAL;
203 } 202 }
204 203
205 voltdm->pmic = pmic; 204 voltdm->pmic = pmic;
206 205
207 return 0; 206 return 0;
208 } 207 }
209 208
210 /** 209 /**
211 * omap_change_voltscale_method() - API to change the voltage scaling method. 210 * omap_change_voltscale_method() - API to change the voltage scaling method.
212 * @voltdm: pointer to the VDD whose voltage scaling method 211 * @voltdm: pointer to the VDD whose voltage scaling method
213 * has to be changed. 212 * has to be changed.
214 * @voltscale_method: the method to be used for voltage scaling. 213 * @voltscale_method: the method to be used for voltage scaling.
215 * 214 *
216 * This API can be used by the board files to change the method of voltage 215 * This API can be used by the board files to change the method of voltage
217 * scaling between vpforceupdate and vcbypass. The parameter values are 216 * scaling between vpforceupdate and vcbypass. The parameter values are
218 * defined in voltage.h 217 * defined in voltage.h
219 */ 218 */
220 void omap_change_voltscale_method(struct voltagedomain *voltdm, 219 void omap_change_voltscale_method(struct voltagedomain *voltdm,
221 int voltscale_method) 220 int voltscale_method)
222 { 221 {
223 if (!voltdm || IS_ERR(voltdm)) { 222 if (!voltdm || IS_ERR(voltdm)) {
224 pr_warning("%s: VDD specified does not exist!\n", __func__); 223 pr_warning("%s: VDD specified does not exist!\n", __func__);
225 return; 224 return;
226 } 225 }
227 226
228 switch (voltscale_method) { 227 switch (voltscale_method) {
229 case VOLTSCALE_VPFORCEUPDATE: 228 case VOLTSCALE_VPFORCEUPDATE:
230 voltdm->scale = omap_vp_forceupdate_scale; 229 voltdm->scale = omap_vp_forceupdate_scale;
231 return; 230 return;
232 case VOLTSCALE_VCBYPASS: 231 case VOLTSCALE_VCBYPASS:
233 voltdm->scale = omap_vc_bypass_scale; 232 voltdm->scale = omap_vc_bypass_scale;
234 return; 233 return;
235 default: 234 default:
236 pr_warning("%s: Trying to change the method of voltage scaling" 235 pr_warning("%s: Trying to change the method of voltage scaling"
237 "to an unsupported one!\n", __func__); 236 "to an unsupported one!\n", __func__);
238 } 237 }
239 } 238 }
240 239
241 /** 240 /**
242 * omap_voltage_late_init() - Init the various voltage parameters 241 * omap_voltage_late_init() - Init the various voltage parameters
243 * 242 *
244 * This API is to be called in the later stages of the 243 * This API is to be called in the later stages of the
245 * system boot to init the voltage controller and 244 * system boot to init the voltage controller and
246 * voltage processors. 245 * voltage processors.
247 */ 246 */
248 int __init omap_voltage_late_init(void) 247 int __init omap_voltage_late_init(void)
249 { 248 {
250 struct voltagedomain *voltdm; 249 struct voltagedomain *voltdm;
251 250
252 if (list_empty(&voltdm_list)) { 251 if (list_empty(&voltdm_list)) {
253 pr_err("%s: Voltage driver support not added\n", 252 pr_err("%s: Voltage driver support not added\n",
254 __func__); 253 __func__);
255 return -EINVAL; 254 return -EINVAL;
256 } 255 }
257 256
258 list_for_each_entry(voltdm, &voltdm_list, node) { 257 list_for_each_entry(voltdm, &voltdm_list, node) {
259 struct clk *sys_ck; 258 struct clk *sys_ck;
260 259
261 if (!voltdm->scalable) 260 if (!voltdm->scalable)
262 continue; 261 continue;
263 262
264 sys_ck = clk_get(NULL, voltdm->sys_clk.name); 263 sys_ck = clk_get(NULL, voltdm->sys_clk.name);
265 if (IS_ERR(sys_ck)) { 264 if (IS_ERR(sys_ck)) {
266 pr_warning("%s: Could not get sys clk.\n", __func__); 265 pr_warning("%s: Could not get sys clk.\n", __func__);
267 return -EINVAL; 266 return -EINVAL;
268 } 267 }
269 voltdm->sys_clk.rate = clk_get_rate(sys_ck); 268 voltdm->sys_clk.rate = clk_get_rate(sys_ck);
270 WARN_ON(!voltdm->sys_clk.rate); 269 WARN_ON(!voltdm->sys_clk.rate);
271 clk_put(sys_ck); 270 clk_put(sys_ck);
272 271
273 if (voltdm->vc) { 272 if (voltdm->vc) {
274 voltdm->scale = omap_vc_bypass_scale; 273 voltdm->scale = omap_vc_bypass_scale;
275 omap_vc_init_channel(voltdm); 274 omap_vc_init_channel(voltdm);
276 } 275 }
277 276
278 if (voltdm->vp) { 277 if (voltdm->vp) {
279 voltdm->scale = omap_vp_forceupdate_scale; 278 voltdm->scale = omap_vp_forceupdate_scale;
280 omap_vp_init(voltdm); 279 omap_vp_init(voltdm);
281 } 280 }
282 } 281 }
283 282
284 return 0; 283 return 0;
285 } 284 }
286 285
287 static struct voltagedomain *_voltdm_lookup(const char *name) 286 static struct voltagedomain *_voltdm_lookup(const char *name)
288 { 287 {
289 struct voltagedomain *voltdm, *temp_voltdm; 288 struct voltagedomain *voltdm, *temp_voltdm;
290 289
291 voltdm = NULL; 290 voltdm = NULL;
292 291
293 list_for_each_entry(temp_voltdm, &voltdm_list, node) { 292 list_for_each_entry(temp_voltdm, &voltdm_list, node) {
294 if (!strcmp(name, temp_voltdm->name)) { 293 if (!strcmp(name, temp_voltdm->name)) {
295 voltdm = temp_voltdm; 294 voltdm = temp_voltdm;
296 break; 295 break;
297 } 296 }
298 } 297 }
299 298
300 return voltdm; 299 return voltdm;
301 } 300 }
302 301
303 /** 302 /**
304 * voltdm_add_pwrdm - add a powerdomain to a voltagedomain 303 * voltdm_add_pwrdm - add a powerdomain to a voltagedomain
305 * @voltdm: struct voltagedomain * to add the powerdomain to 304 * @voltdm: struct voltagedomain * to add the powerdomain to
306 * @pwrdm: struct powerdomain * to associate with a voltagedomain 305 * @pwrdm: struct powerdomain * to associate with a voltagedomain
307 * 306 *
308 * Associate the powerdomain @pwrdm with a voltagedomain @voltdm. This 307 * Associate the powerdomain @pwrdm with a voltagedomain @voltdm. This
309 * enables the use of voltdm_for_each_pwrdm(). Returns -EINVAL if 308 * enables the use of voltdm_for_each_pwrdm(). Returns -EINVAL if
310 * presented with invalid pointers; -ENOMEM if memory could not be allocated; 309 * presented with invalid pointers; -ENOMEM if memory could not be allocated;
311 * or 0 upon success. 310 * or 0 upon success.
312 */ 311 */
313 int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm) 312 int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm)
314 { 313 {
315 if (!voltdm || !pwrdm) 314 if (!voltdm || !pwrdm)
316 return -EINVAL; 315 return -EINVAL;
317 316
318 pr_debug("voltagedomain: associating powerdomain %s with voltagedomain " 317 pr_debug("voltagedomain: associating powerdomain %s with voltagedomain "
319 "%s\n", pwrdm->name, voltdm->name); 318 "%s\n", pwrdm->name, voltdm->name);
320 319
321 list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list); 320 list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list);
322 321
323 return 0; 322 return 0;
324 } 323 }
325 324
326 /** 325 /**
327 * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm 326 * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm
328 * @voltdm: struct voltagedomain * to iterate over 327 * @voltdm: struct voltagedomain * to iterate over
329 * @fn: callback function * 328 * @fn: callback function *
330 * 329 *
331 * Call the supplied function @fn for each powerdomain in the 330 * Call the supplied function @fn for each powerdomain in the
332 * voltagedomain @voltdm. Returns -EINVAL if presented with invalid 331 * voltagedomain @voltdm. Returns -EINVAL if presented with invalid
333 * pointers; or passes along the last return value of the callback 332 * pointers; or passes along the last return value of the callback
334 * function, which should be 0 for success or anything else to 333 * function, which should be 0 for success or anything else to
335 * indicate failure. 334 * indicate failure.
336 */ 335 */
337 int voltdm_for_each_pwrdm(struct voltagedomain *voltdm, 336 int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
338 int (*fn)(struct voltagedomain *voltdm, 337 int (*fn)(struct voltagedomain *voltdm,
339 struct powerdomain *pwrdm)) 338 struct powerdomain *pwrdm))
340 { 339 {
341 struct powerdomain *pwrdm; 340 struct powerdomain *pwrdm;
342 int ret = 0; 341 int ret = 0;
343 342
344 if (!fn) 343 if (!fn)
345 return -EINVAL; 344 return -EINVAL;
346 345
347 list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node) 346 list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node)
348 ret = (*fn)(voltdm, pwrdm); 347 ret = (*fn)(voltdm, pwrdm);
349 348
350 return ret; 349 return ret;
351 } 350 }
352 351
353 /** 352 /**
354 * voltdm_for_each - call function on each registered voltagedomain 353 * voltdm_for_each - call function on each registered voltagedomain
355 * @fn: callback function * 354 * @fn: callback function *
356 * 355 *
357 * Call the supplied function @fn for each registered voltagedomain. 356 * Call the supplied function @fn for each registered voltagedomain.
358 * The callback function @fn can return anything but 0 to bail out 357 * The callback function @fn can return anything but 0 to bail out
359 * early from the iterator. Returns the last return value of the 358 * early from the iterator. Returns the last return value of the
360 * callback function, which should be 0 for success or anything else 359 * callback function, which should be 0 for success or anything else
361 * to indicate failure; or -EINVAL if the function pointer is null. 360 * to indicate failure; or -EINVAL if the function pointer is null.
362 */ 361 */
363 int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user), 362 int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
364 void *user) 363 void *user)
365 { 364 {
366 struct voltagedomain *temp_voltdm; 365 struct voltagedomain *temp_voltdm;
367 int ret = 0; 366 int ret = 0;
368 367
369 if (!fn) 368 if (!fn)
370 return -EINVAL; 369 return -EINVAL;
371 370
372 list_for_each_entry(temp_voltdm, &voltdm_list, node) { 371 list_for_each_entry(temp_voltdm, &voltdm_list, node) {
373 ret = (*fn)(temp_voltdm, user); 372 ret = (*fn)(temp_voltdm, user);
374 if (ret) 373 if (ret)
375 break; 374 break;
376 } 375 }
377 376
378 return ret; 377 return ret;
379 } 378 }
380 379
381 static int _voltdm_register(struct voltagedomain *voltdm) 380 static int _voltdm_register(struct voltagedomain *voltdm)
382 { 381 {
383 if (!voltdm || !voltdm->name) 382 if (!voltdm || !voltdm->name)
384 return -EINVAL; 383 return -EINVAL;
385 384
386 INIT_LIST_HEAD(&voltdm->pwrdm_list); 385 INIT_LIST_HEAD(&voltdm->pwrdm_list);
387 list_add(&voltdm->node, &voltdm_list); 386 list_add(&voltdm->node, &voltdm_list);
388 387
389 pr_debug("voltagedomain: registered %s\n", voltdm->name); 388 pr_debug("voltagedomain: registered %s\n", voltdm->name);
390 389
391 return 0; 390 return 0;
392 } 391 }
393 392
394 /** 393 /**
395 * voltdm_lookup - look up a voltagedomain by name, return a pointer 394 * voltdm_lookup - look up a voltagedomain by name, return a pointer
396 * @name: name of voltagedomain 395 * @name: name of voltagedomain
397 * 396 *
398 * Find a registered voltagedomain by its name @name. Returns a pointer 397 * Find a registered voltagedomain by its name @name. Returns a pointer
399 * to the struct voltagedomain if found, or NULL otherwise. 398 * to the struct voltagedomain if found, or NULL otherwise.
400 */ 399 */
401 struct voltagedomain *voltdm_lookup(const char *name) 400 struct voltagedomain *voltdm_lookup(const char *name)
402 { 401 {
403 struct voltagedomain *voltdm ; 402 struct voltagedomain *voltdm ;
404 403
405 if (!name) 404 if (!name)
406 return NULL; 405 return NULL;
407 406
408 voltdm = _voltdm_lookup(name); 407 voltdm = _voltdm_lookup(name);
409 408
410 return voltdm; 409 return voltdm;
411 } 410 }
412 411
413 /** 412 /**
414 * voltdm_init - set up the voltagedomain layer 413 * voltdm_init - set up the voltagedomain layer
415 * @voltdm_list: array of struct voltagedomain pointers to register 414 * @voltdm_list: array of struct voltagedomain pointers to register
416 * 415 *
417 * Loop through the array of voltagedomains @voltdm_list, registering all 416 * Loop through the array of voltagedomains @voltdm_list, registering all
418 * that are available on the current CPU. If voltdm_list is supplied 417 * that are available on the current CPU. If voltdm_list is supplied
419 * and not null, all of the referenced voltagedomains will be 418 * and not null, all of the referenced voltagedomains will be
420 * registered. No return value. 419 * registered. No return value.
421 */ 420 */
422 void voltdm_init(struct voltagedomain **voltdms) 421 void voltdm_init(struct voltagedomain **voltdms)
423 { 422 {
424 struct voltagedomain **v; 423 struct voltagedomain **v;
425 424
426 if (voltdms) { 425 if (voltdms) {
427 for (v = voltdms; *v; v++) 426 for (v = voltdms; *v; v++)
428 _voltdm_register(*v); 427 _voltdm_register(*v);
arch/arm/mach-omap2/voltage.h
1 /* File was deleted
2 * OMAP Voltage Management Routines
3 *
4 * Author: Thara Gopinath <thara@ti.com>
5 *
6 * Copyright (C) 2009 Texas Instruments, Inc.
7 * Thara Gopinath <thara@ti.com>
8 *
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
11 * published by the Free Software Foundation.
12 */
13
14 #ifndef __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
15 #define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
16
17 #include <linux/err.h>
18
19 #include "vc.h"
20 #include "vp.h"
21
22 struct powerdomain;
23
24 /* XXX document */
25 #define VOLTSCALE_VPFORCEUPDATE 1
26 #define VOLTSCALE_VCBYPASS 2
27
28 /*
29 * OMAP3 GENERIC setup times. Revisit to see if these needs to be
30 * passed from board or PMIC file
31 */
32 #define OMAP3_CLKSETUP 0xff
33 #define OMAP3_VOLTOFFSET 0xff
34 #define OMAP3_VOLTSETUP2 0xff
35
36 struct omap_vdd_info;
37
38 /**
39 * struct omap_vfsm_instance - per-voltage manager FSM register/bitfield
40 * data
41 * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
42 * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
43 *
44 * XXX What about VOLTOFFSET/VOLTCTRL?
45 */
46 struct omap_vfsm_instance {
47 u32 voltsetup_mask;
48 u8 voltsetup_reg;
49 };
50
51 /**
52 * struct voltagedomain - omap voltage domain global structure.
53 * @name: Name of the voltage domain which can be used as a unique identifier.
54 * @scalable: Whether or not this voltage domain is scalable
55 * @node: list_head linking all voltage domains
56 * @pwrdm_list: list_head linking all powerdomains in this voltagedomain
57 * @vc: pointer to VC channel associated with this voltagedomain
58 * @vp: pointer to VP associated with this voltagedomain
59 * @read: read a VC/VP register
60 * @write: write a VC/VP register
61 * @read: read-modify-write a VC/VP register
62 * @sys_clk: system clock name/frequency, used for various timing calculations
63 * @scale: function used to scale the voltage of the voltagedomain
64 * @nominal_volt: current nominal voltage for this voltage domain
65 * @volt_data: voltage table having the distinct voltages supported
66 * by the domain and other associated per voltage data.
67 */
68 struct voltagedomain {
69 char *name;
70 bool scalable;
71 struct list_head node;
72 struct list_head pwrdm_list;
73 struct omap_vc_channel *vc;
74 const struct omap_vfsm_instance *vfsm;
75 struct omap_vp_instance *vp;
76 struct omap_voltdm_pmic *pmic;
77
78 /* VC/VP register access functions: SoC specific */
79 u32 (*read) (u8 offset);
80 void (*write) (u32 val, u8 offset);
81 u32 (*rmw)(u32 mask, u32 bits, u8 offset);
82
83 union {
84 const char *name;
85 u32 rate;
86 } sys_clk;
87
88 int (*scale) (struct voltagedomain *voltdm,
89 unsigned long target_volt);
90
91 u32 nominal_volt;
92 struct omap_volt_data *volt_data;
93 struct omap_vdd_info *vdd;
94 struct dentry *debug_dir;
95 };
96
97 /**
98 * struct omap_volt_data - Omap voltage specific data.
99 * @voltage_nominal: The possible voltage value in uV
100 * @sr_efuse_offs: The offset of the efuse register(from system
101 * control module base address) from where to read
102 * the n-target value for the smartreflex module.
103 * @sr_errminlimit: Error min limit value for smartreflex. This value
104 * differs at differnet opp and thus is linked
105 * with voltage.
106 * @vp_errorgain: Error gain value for the voltage processor. This
107 * field also differs according to the voltage/opp.
108 */
109 struct omap_volt_data {
110 u32 volt_nominal;
111 u32 sr_efuse_offs;
112 u8 sr_errminlimit;
113 u8 vp_errgain;
114 };
115
116 /**
117 * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
118 * @slew_rate: PMIC slew rate (in uv/us)
119 * @step_size: PMIC voltage step size (in uv)
120 * @i2c_slave_addr: I2C slave address of PMIC
121 * @volt_reg_addr: voltage configuration register address
122 * @cmd_reg_addr: command (on, on-LP, ret, off) configuration register address
123 * @i2c_high_speed: whether VC uses I2C high-speed mode to PMIC
124 * @i2c_mcode: master code value for I2C high-speed preamble transmission
125 * @vsel_to_uv: PMIC API to convert vsel value to actual voltage in uV.
126 * @uv_to_vsel: PMIC API to convert voltage in uV to vsel value.
127 */
128 struct omap_voltdm_pmic {
129 int slew_rate;
130 int step_size;
131 u32 on_volt;
132 u32 onlp_volt;
133 u32 ret_volt;
134 u32 off_volt;
135 u16 volt_setup_time;
136 u16 i2c_slave_addr;
137 u16 volt_reg_addr;
138 u16 cmd_reg_addr;
139 u8 vp_erroroffset;
140 u8 vp_vstepmin;
141 u8 vp_vstepmax;
142 u8 vp_vddmin;
143 u8 vp_vddmax;
144 u8 vp_timeout_us;
145 bool i2c_high_speed;
146 u8 i2c_mcode;
147 unsigned long (*vsel_to_uv) (const u8 vsel);
148 u8 (*uv_to_vsel) (unsigned long uV);
149 };
150
151 /**
152 * struct omap_vdd_dep_volt - Map table for voltage dependencies
153 * @main_vdd_volt : The main vdd voltage
154 * @dep_vdd_volt : The voltage at which the dependent vdd should be
155 * when the main vdd is at <main_vdd_volt> voltage
156 *
157 * Table containing the parent vdd voltage and the dependent vdd voltage
158 * corresponding to it.
159 */
160 struct omap_vdd_dep_volt {
161 u32 main_vdd_volt;
162 u32 dep_vdd_volt;
163 };
164
165 /**
166 * struct omap_vdd_dep_info - Dependent vdd info
167 * @name : Dependent vdd name
168 * @_dep_voltdm : internal structure meant to prevent multiple lookups
169 * @dep_table : Table containing the dependent vdd voltage
170 * corresponding to every main vdd voltage.
171 * @nr_dep_entries : number of dependency voltage entries
172 */
173 struct omap_vdd_dep_info {
174 char *name;
175 struct voltagedomain *_dep_voltdm;
176 struct omap_vdd_dep_volt *dep_table;
177 int nr_dep_entries;
178 };
179
180 /**
181 * omap_vdd_info - Per Voltage Domain info
182 *
183 * @volt_data : voltage table having the distinct voltages supported
184 * by the domain and other associated per voltage data.
185 * @dep_vdd_info : Array ending with a 0 terminator for dependency
186 * voltage information.
187 */
188 struct omap_vdd_info {
189 struct omap_volt_data *volt_data;
190 struct omap_vdd_dep_info *dep_vdd_info;
191 };
192
193 void omap_voltage_get_volttable(struct voltagedomain *voltdm,
194 struct omap_volt_data **volt_data);
195 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
196 unsigned long volt);
197 int omap_voltage_register_pmic(struct voltagedomain *voltdm,
198 struct omap_voltdm_pmic *pmic);
199 void omap_change_voltscale_method(struct voltagedomain *voltdm,
200 int voltscale_method);
201 int omap_voltage_late_init(void);
202
203 extern void omap2xxx_voltagedomains_init(void);
204 extern void omap3xxx_voltagedomains_init(void);
205 extern void am33xx_voltagedomains_init(void);
206 extern void omap44xx_voltagedomains_init(void);
207
208 struct voltagedomain *voltdm_lookup(const char *name);
209 void voltdm_init(struct voltagedomain **voltdm_list);
210 int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm);
211 int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
212 void *user);
213 int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
214 int (*fn)(struct voltagedomain *voltdm,
215 struct powerdomain *pwrdm));
216 int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
217 void voltdm_reset(struct voltagedomain *voltdm);
218 unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
219 #endif
220 1 /*
arch/arm/mach-omap2/voltagedomains2xxx_data.c
1 /* 1 /*
2 * OMAP3 voltage domain data 2 * OMAP3 voltage domain data
3 * 3 *
4 * Copyright (C) 2011 Texas Instruments, Inc. 4 * Copyright (C) 2011 Texas Instruments, Inc.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 #include <linux/kernel.h> 10 #include <linux/kernel.h>
11 #include <linux/init.h> 11 #include <linux/init.h>
12 #include <plat/voltage.h>
12 13
13 #include "voltage.h"
14 14
15 static struct voltagedomain omap2_voltdm_core = { 15 static struct voltagedomain omap2_voltdm_core = {
16 .name = "core", 16 .name = "core",
17 }; 17 };
18 18
19 static struct voltagedomain omap2_voltdm_wkup = { 19 static struct voltagedomain omap2_voltdm_wkup = {
20 .name = "wakeup", 20 .name = "wakeup",
21 }; 21 };
22 22
23 static struct voltagedomain *voltagedomains_omap2[] __initdata = { 23 static struct voltagedomain *voltagedomains_omap2[] __initdata = {
24 &omap2_voltdm_core, 24 &omap2_voltdm_core,
25 &omap2_voltdm_wkup, 25 &omap2_voltdm_wkup,
26 NULL, 26 NULL,
27 }; 27 };
28 28
29 void __init omap2xxx_voltagedomains_init(void) 29 void __init omap2xxx_voltagedomains_init(void)
30 { 30 {
31 voltdm_init(voltagedomains_omap2); 31 voltdm_init(voltagedomains_omap2);
32 } 32 }
arch/arm/mach-omap2/voltagedomains33xx_data.c
1 /* 1 /*
2 * AM33XX voltage domain data 2 * AM33XX voltage domain data
3 * 3 *
4 * Copyright (C) 2011 Texas Instruments, Inc. 4 * Copyright (C) 2011 Texas Instruments, Inc.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 #include <linux/kernel.h> 10 #include <linux/kernel.h>
11 #include <linux/init.h> 11 #include <linux/init.h>
12 12
13 #include "voltage.h" 13 #include <plat/voltage.h>
14 14
15 static struct voltagedomain am33xx_voltdm_mpu = { 15 static struct voltagedomain am33xx_voltdm_mpu = {
16 .name = "mpu", 16 .name = "mpu",
17 }; 17 };
18 18
19 static struct voltagedomain am33xx_voltdm_core = { 19 static struct voltagedomain am33xx_voltdm_core = {
20 .name = "core", 20 .name = "core",
21 }; 21 };
22 22
23 static struct voltagedomain am33xx_voltdm_rtc = { 23 static struct voltagedomain am33xx_voltdm_rtc = {
24 .name = "rtc", 24 .name = "rtc",
25 }; 25 };
26 26
27 static struct voltagedomain *voltagedomains_am33xx[] __initdata = { 27 static struct voltagedomain *voltagedomains_am33xx[] __initdata = {
28 &am33xx_voltdm_mpu, 28 &am33xx_voltdm_mpu,
29 &am33xx_voltdm_core, 29 &am33xx_voltdm_core,
30 &am33xx_voltdm_rtc, 30 &am33xx_voltdm_rtc,
31 NULL, 31 NULL,
32 }; 32 };
33 33
34 void __init am33xx_voltagedomains_init(void) 34 void __init am33xx_voltagedomains_init(void)
35 { 35 {
36 voltdm_init(voltagedomains_am33xx); 36 voltdm_init(voltagedomains_am33xx);
37 } 37 }
38 38
arch/arm/mach-omap2/voltagedomains3xxx_data.c
1 /* 1 /*
2 * OMAP3 voltage domain data 2 * OMAP3 voltage domain data
3 * 3 *
4 * Copyright (C) 2007, 2010 Texas Instruments, Inc. 4 * Copyright (C) 2007, 2010 Texas Instruments, Inc.
5 * Rajendra Nayak <rnayak@ti.com> 5 * Rajendra Nayak <rnayak@ti.com>
6 * Lesly A M <x0080970@ti.com> 6 * Lesly A M <x0080970@ti.com>
7 * Thara Gopinath <thara@ti.com> 7 * Thara Gopinath <thara@ti.com>
8 * 8 *
9 * Copyright (C) 2008, 2011 Nokia Corporation 9 * Copyright (C) 2008, 2011 Nokia Corporation
10 * Kalle Jokiniemi 10 * Kalle Jokiniemi
11 * Paul Walmsley 11 * Paul Walmsley
12 * 12 *
13 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as 14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation. 15 * published by the Free Software Foundation.
16 */ 16 */
17 #include <linux/kernel.h> 17 #include <linux/kernel.h>
18 #include <linux/err.h> 18 #include <linux/err.h>
19 #include <linux/init.h> 19 #include <linux/init.h>
20 20
21 #include <plat/common.h> 21 #include <plat/common.h>
22 #include <plat/cpu.h> 22 #include <plat/cpu.h>
23 #include <plat/voltage.h>
24 #include <plat/vc.h>
25 #include <plat/vp.h>
23 26
24 #include "prm-regbits-34xx.h" 27 #include "prm-regbits-34xx.h"
25 #include "omap_opp_data.h" 28 #include "omap_opp_data.h"
26 #include "voltage.h"
27 #include "vc.h"
28 #include "vp.h"
29 29
30 /* 30 /*
31 * VDD data 31 * VDD data
32 */ 32 */
33 33
34 static const struct omap_vfsm_instance omap3_vdd1_vfsm = { 34 static const struct omap_vfsm_instance omap3_vdd1_vfsm = {
35 .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET, 35 .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
36 .voltsetup_mask = OMAP3430_SETUP_TIME1_MASK, 36 .voltsetup_mask = OMAP3430_SETUP_TIME1_MASK,
37 }; 37 };
38 38
39 static struct omap_vdd_info omap3_vdd1_info; 39 static struct omap_vdd_info omap3_vdd1_info;
40 40
41 static const struct omap_vfsm_instance omap3_vdd2_vfsm = { 41 static const struct omap_vfsm_instance omap3_vdd2_vfsm = {
42 .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET, 42 .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
43 .voltsetup_mask = OMAP3430_SETUP_TIME2_MASK, 43 .voltsetup_mask = OMAP3430_SETUP_TIME2_MASK,
44 }; 44 };
45 45
46 static struct voltagedomain omap3_voltdm_mpu = { 46 static struct voltagedomain omap3_voltdm_mpu = {
47 .name = "mpu_iva", 47 .name = "mpu_iva",
48 .scalable = true, 48 .scalable = true,
49 .read = omap3_prm_vcvp_read, 49 .read = omap3_prm_vcvp_read,
50 .write = omap3_prm_vcvp_write, 50 .write = omap3_prm_vcvp_write,
51 .rmw = omap3_prm_vcvp_rmw, 51 .rmw = omap3_prm_vcvp_rmw,
52 .vc = &omap3_vc_mpu, 52 .vc = &omap3_vc_mpu,
53 .vfsm = &omap3_vdd1_vfsm, 53 .vfsm = &omap3_vdd1_vfsm,
54 .vp = &omap3_vp_mpu, 54 .vp = &omap3_vp_mpu,
55 .vdd = &omap3_vdd1_info, 55 .vdd = &omap3_vdd1_info,
56 }; 56 };
57 57
58 static struct omap_vdd_info omap3_vdd2_info; 58 static struct omap_vdd_info omap3_vdd2_info;
59 59
60 static struct voltagedomain omap3_voltdm_core = { 60 static struct voltagedomain omap3_voltdm_core = {
61 .name = "core", 61 .name = "core",
62 .scalable = true, 62 .scalable = true,
63 .read = omap3_prm_vcvp_read, 63 .read = omap3_prm_vcvp_read,
64 .write = omap3_prm_vcvp_write, 64 .write = omap3_prm_vcvp_write,
65 .rmw = omap3_prm_vcvp_rmw, 65 .rmw = omap3_prm_vcvp_rmw,
66 .vc = &omap3_vc_core, 66 .vc = &omap3_vc_core,
67 .vfsm = &omap3_vdd2_vfsm, 67 .vfsm = &omap3_vdd2_vfsm,
68 .vp = &omap3_vp_core, 68 .vp = &omap3_vp_core,
69 .vdd = &omap3_vdd2_info, 69 .vdd = &omap3_vdd2_info,
70 }; 70 };
71 71
72 static struct voltagedomain omap3_voltdm_wkup = { 72 static struct voltagedomain omap3_voltdm_wkup = {
73 .name = "wakeup", 73 .name = "wakeup",
74 }; 74 };
75 75
76 static struct voltagedomain *voltagedomains_omap3[] __initdata = { 76 static struct voltagedomain *voltagedomains_omap3[] __initdata = {
77 &omap3_voltdm_mpu, 77 &omap3_voltdm_mpu,
78 &omap3_voltdm_core, 78 &omap3_voltdm_core,
79 &omap3_voltdm_wkup, 79 &omap3_voltdm_wkup,
80 NULL, 80 NULL,
81 }; 81 };
82 82
83 static const char *sys_clk_name __initdata = "sys_ck"; 83 static const char *sys_clk_name __initdata = "sys_ck";
84 84
85 void __init omap3xxx_voltagedomains_init(void) 85 void __init omap3xxx_voltagedomains_init(void)
86 { 86 {
87 struct voltagedomain *voltdm; 87 struct voltagedomain *voltdm;
88 int i; 88 int i;
89 89
90 /* 90 /*
91 * XXX Will depend on the process, validation, and binning 91 * XXX Will depend on the process, validation, and binning
92 * for the currently-running IC 92 * for the currently-running IC
93 */ 93 */
94 if (cpu_is_omap3630()) { 94 if (cpu_is_omap3630()) {
95 omap3_voltdm_mpu.volt_data = omap36xx_vddmpu_volt_data; 95 omap3_voltdm_mpu.volt_data = omap36xx_vddmpu_volt_data;
96 omap3_voltdm_core.volt_data = omap36xx_vddcore_volt_data; 96 omap3_voltdm_core.volt_data = omap36xx_vddcore_volt_data;
97 omap3_vdd1_info.dep_vdd_info = omap36xx_vddmpu_dep_info; 97 omap3_vdd1_info.dep_vdd_info = omap36xx_vddmpu_dep_info;
98 } else { 98 } else {
99 omap3_voltdm_mpu.volt_data = omap34xx_vddmpu_volt_data; 99 omap3_voltdm_mpu.volt_data = omap34xx_vddmpu_volt_data;
100 omap3_voltdm_core.volt_data = omap34xx_vddcore_volt_data; 100 omap3_voltdm_core.volt_data = omap34xx_vddcore_volt_data;
101 omap3_vdd1_info.dep_vdd_info = omap34xx_vddmpu_dep_info; 101 omap3_vdd1_info.dep_vdd_info = omap34xx_vddmpu_dep_info;
102 } 102 }
103 103
104 for (i = 0; voltdm = voltagedomains_omap3[i], voltdm; i++) 104 for (i = 0; voltdm = voltagedomains_omap3[i], voltdm; i++)
105 voltdm->sys_clk.name = sys_clk_name; 105 voltdm->sys_clk.name = sys_clk_name;
106 106
arch/arm/mach-omap2/voltagedomains44xx_data.c
1 /* 1 /*
2 * OMAP3/OMAP4 Voltage Management Routines 2 * OMAP3/OMAP4 Voltage Management Routines
3 * 3 *
4 * Author: Thara Gopinath <thara@ti.com> 4 * Author: Thara Gopinath <thara@ti.com>
5 * 5 *
6 * Copyright (C) 2007 Texas Instruments, Inc. 6 * Copyright (C) 2007 Texas Instruments, Inc.
7 * Rajendra Nayak <rnayak@ti.com> 7 * Rajendra Nayak <rnayak@ti.com>
8 * Lesly A M <x0080970@ti.com> 8 * Lesly A M <x0080970@ti.com>
9 * 9 *
10 * Copyright (C) 2008 Nokia Corporation 10 * Copyright (C) 2008 Nokia Corporation
11 * Kalle Jokiniemi 11 * Kalle Jokiniemi
12 * 12 *
13 * Copyright (C) 2010 Texas Instruments, Inc. 13 * Copyright (C) 2010 Texas Instruments, Inc.
14 * Thara Gopinath <thara@ti.com> 14 * Thara Gopinath <thara@ti.com>
15 * 15 *
16 * This program is free software; you can redistribute it and/or modify 16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2 as 17 * it under the terms of the GNU General Public License version 2 as
18 * published by the Free Software Foundation. 18 * published by the Free Software Foundation.
19 */ 19 */
20 #include <linux/kernel.h> 20 #include <linux/kernel.h>
21 #include <linux/err.h> 21 #include <linux/err.h>
22 #include <linux/init.h> 22 #include <linux/init.h>
23 23
24 #include <plat/common.h> 24 #include <plat/common.h>
25 #include <plat/vc.h>
26 #include <plat/vp.h>
25 27
26 #include "prm-regbits-44xx.h" 28 #include "prm-regbits-44xx.h"
27 #include "prm44xx.h" 29 #include "prm44xx.h"
28 #include "prcm44xx.h" 30 #include "prcm44xx.h"
29 #include "prminst44xx.h" 31 #include "prminst44xx.h"
30 #include "voltage.h" 32 #include "voltage.h"
31 #include "omap_opp_data.h" 33 #include "omap_opp_data.h"
32 #include "vc.h"
33 #include "vp.h"
34 34
35 static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = { 35 static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = {
36 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET, 36 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
37 }; 37 };
38 static struct omap_vdd_info omap4_vdd_mpu_info; 38 static struct omap_vdd_info omap4_vdd_mpu_info;
39 39
40 40
41 static const struct omap_vfsm_instance omap4_vdd_iva_vfsm = { 41 static const struct omap_vfsm_instance omap4_vdd_iva_vfsm = {
42 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET, 42 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
43 }; 43 };
44 static struct omap_vdd_info omap4_vdd_iva_info; 44 static struct omap_vdd_info omap4_vdd_iva_info;
45 45
46 static const struct omap_vfsm_instance omap4_vdd_core_vfsm = { 46 static const struct omap_vfsm_instance omap4_vdd_core_vfsm = {
47 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET, 47 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
48 }; 48 };
49 static struct omap_vdd_info omap4_vdd_core_info; 49 static struct omap_vdd_info omap4_vdd_core_info;
50 50
51 static struct voltagedomain omap4_voltdm_mpu = { 51 static struct voltagedomain omap4_voltdm_mpu = {
52 .name = "mpu", 52 .name = "mpu",
53 .scalable = true, 53 .scalable = true,
54 .read = omap4_prm_vcvp_read, 54 .read = omap4_prm_vcvp_read,
55 .write = omap4_prm_vcvp_write, 55 .write = omap4_prm_vcvp_write,
56 .rmw = omap4_prm_vcvp_rmw, 56 .rmw = omap4_prm_vcvp_rmw,
57 .vc = &omap4_vc_mpu, 57 .vc = &omap4_vc_mpu,
58 .vfsm = &omap4_vdd_mpu_vfsm, 58 .vfsm = &omap4_vdd_mpu_vfsm,
59 .vp = &omap4_vp_mpu, 59 .vp = &omap4_vp_mpu,
60 .vdd = &omap4_vdd_mpu_info, 60 .vdd = &omap4_vdd_mpu_info,
61 }; 61 };
62 62
63 static struct voltagedomain omap4_voltdm_iva = { 63 static struct voltagedomain omap4_voltdm_iva = {
64 .name = "iva", 64 .name = "iva",
65 .scalable = true, 65 .scalable = true,
66 .read = omap4_prm_vcvp_read, 66 .read = omap4_prm_vcvp_read,
67 .write = omap4_prm_vcvp_write, 67 .write = omap4_prm_vcvp_write,
68 .rmw = omap4_prm_vcvp_rmw, 68 .rmw = omap4_prm_vcvp_rmw,
69 .vc = &omap4_vc_iva, 69 .vc = &omap4_vc_iva,
70 .vfsm = &omap4_vdd_iva_vfsm, 70 .vfsm = &omap4_vdd_iva_vfsm,
71 .vp = &omap4_vp_iva, 71 .vp = &omap4_vp_iva,
72 .vdd = &omap4_vdd_iva_info, 72 .vdd = &omap4_vdd_iva_info,
73 }; 73 };
74 74
75 static struct voltagedomain omap4_voltdm_core = { 75 static struct voltagedomain omap4_voltdm_core = {
76 .name = "core", 76 .name = "core",
77 .scalable = true, 77 .scalable = true,
78 .read = omap4_prm_vcvp_read, 78 .read = omap4_prm_vcvp_read,
79 .write = omap4_prm_vcvp_write, 79 .write = omap4_prm_vcvp_write,
80 .rmw = omap4_prm_vcvp_rmw, 80 .rmw = omap4_prm_vcvp_rmw,
81 .vc = &omap4_vc_core, 81 .vc = &omap4_vc_core,
82 .vfsm = &omap4_vdd_core_vfsm, 82 .vfsm = &omap4_vdd_core_vfsm,
83 .vp = &omap4_vp_core, 83 .vp = &omap4_vp_core,
84 .vdd = &omap4_vdd_core_info, 84 .vdd = &omap4_vdd_core_info,
85 }; 85 };
86 86
87 static struct voltagedomain omap4_voltdm_wkup = { 87 static struct voltagedomain omap4_voltdm_wkup = {
88 .name = "wakeup", 88 .name = "wakeup",
89 }; 89 };
90 90
91 static struct voltagedomain *voltagedomains_omap4[] __initdata = { 91 static struct voltagedomain *voltagedomains_omap4[] __initdata = {
92 &omap4_voltdm_mpu, 92 &omap4_voltdm_mpu,
93 &omap4_voltdm_iva, 93 &omap4_voltdm_iva,
94 &omap4_voltdm_core, 94 &omap4_voltdm_core,
95 &omap4_voltdm_wkup, 95 &omap4_voltdm_wkup,
96 NULL, 96 NULL,
97 }; 97 };
98 98
99 static const char *sys_clk_name __initdata = "sys_clkin_ck"; 99 static const char *sys_clk_name __initdata = "sys_clkin_ck";
100 100
101 void __init omap44xx_voltagedomains_init(void) 101 void __init omap44xx_voltagedomains_init(void)
102 { 102 {
103 struct voltagedomain *voltdm; 103 struct voltagedomain *voltdm;
104 int i; 104 int i;
105 105
106 /* 106 /*
107 * XXX Will depend on the process, validation, and binning 107 * XXX Will depend on the process, validation, and binning
108 * for the currently-running IC 108 * for the currently-running IC
109 */ 109 */
110 omap4_voltdm_mpu.volt_data = omap44xx_vdd_mpu_volt_data; 110 omap4_voltdm_mpu.volt_data = omap44xx_vdd_mpu_volt_data;
111 omap4_vdd_mpu_info.dep_vdd_info = omap443x_vddmpu_dep_info; 111 omap4_vdd_mpu_info.dep_vdd_info = omap443x_vddmpu_dep_info;
112 112
113 omap4_voltdm_iva.volt_data = omap44xx_vdd_iva_volt_data; 113 omap4_voltdm_iva.volt_data = omap44xx_vdd_iva_volt_data;
114 omap4_vdd_iva_info.dep_vdd_info = omap443x_vddiva_dep_info; 114 omap4_vdd_iva_info.dep_vdd_info = omap443x_vddiva_dep_info;
115 115
116 omap4_voltdm_core.volt_data = omap44xx_vdd_core_volt_data; 116 omap4_voltdm_core.volt_data = omap44xx_vdd_core_volt_data;
117 117
118 for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++) 118 for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++)
119 voltdm->sys_clk.name = sys_clk_name; 119 voltdm->sys_clk.name = sys_clk_name;
120 120
121 voltdm_init(voltagedomains_omap4); 121 voltdm_init(voltagedomains_omap4);
arch/arm/mach-omap2/vp.c
1 #include <linux/kernel.h> 1 #include <linux/kernel.h>
2 #include <linux/init.h> 2 #include <linux/init.h>
3 3
4 #include <plat/common.h> 4 #include <plat/common.h>
5 #include <plat/voltage.h>
6 #include <plat/vp.h>
5 7
6 #include "voltage.h"
7 #include "vp.h"
8 #include "prm-regbits-34xx.h" 8 #include "prm-regbits-34xx.h"
9 #include "prm-regbits-44xx.h" 9 #include "prm-regbits-44xx.h"
10 #include "prm44xx.h" 10 #include "prm44xx.h"
11 11
12 static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt) 12 static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt)
13 { 13 {
14 struct omap_vp_instance *vp = voltdm->vp; 14 struct omap_vp_instance *vp = voltdm->vp;
15 u32 vpconfig; 15 u32 vpconfig;
16 char vsel; 16 char vsel;
17 17
18 vsel = voltdm->pmic->uv_to_vsel(volt); 18 vsel = voltdm->pmic->uv_to_vsel(volt);
19 19
20 vpconfig = voltdm->read(vp->vpconfig); 20 vpconfig = voltdm->read(vp->vpconfig);
21 vpconfig &= ~(vp->common->vpconfig_initvoltage_mask | 21 vpconfig &= ~(vp->common->vpconfig_initvoltage_mask |
22 vp->common->vpconfig_forceupdate | 22 vp->common->vpconfig_forceupdate |
23 vp->common->vpconfig_initvdd); 23 vp->common->vpconfig_initvdd);
24 vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask); 24 vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask);
25 voltdm->write(vpconfig, vp->vpconfig); 25 voltdm->write(vpconfig, vp->vpconfig);
26 26
27 /* Trigger initVDD value copy to voltage processor */ 27 /* Trigger initVDD value copy to voltage processor */
28 voltdm->write((vpconfig | vp->common->vpconfig_initvdd), 28 voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
29 vp->vpconfig); 29 vp->vpconfig);
30 30
31 /* Clear initVDD copy trigger bit */ 31 /* Clear initVDD copy trigger bit */
32 voltdm->write(vpconfig, vp->vpconfig); 32 voltdm->write(vpconfig, vp->vpconfig);
33 33
34 return vpconfig; 34 return vpconfig;
35 } 35 }
36 36
37 /* Generic voltage init functions */ 37 /* Generic voltage init functions */
38 void __init omap_vp_init(struct voltagedomain *voltdm) 38 void __init omap_vp_init(struct voltagedomain *voltdm)
39 { 39 {
40 struct omap_vp_instance *vp = voltdm->vp; 40 struct omap_vp_instance *vp = voltdm->vp;
41 u32 val, sys_clk_rate, timeout, waittime; 41 u32 val, sys_clk_rate, timeout, waittime;
42 u32 vddmin, vddmax, vstepmin, vstepmax; 42 u32 vddmin, vddmax, vstepmin, vstepmax;
43 43
44 if (!voltdm->read || !voltdm->write) { 44 if (!voltdm->read || !voltdm->write) {
45 pr_err("%s: No read/write API for accessing vdd_%s regs\n", 45 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
46 __func__, voltdm->name); 46 __func__, voltdm->name);
47 return; 47 return;
48 } 48 }
49 49
50 vp->enabled = false; 50 vp->enabled = false;
51 51
52 /* Divide to avoid overflow */ 52 /* Divide to avoid overflow */
53 sys_clk_rate = voltdm->sys_clk.rate / 1000; 53 sys_clk_rate = voltdm->sys_clk.rate / 1000;
54 54
55 timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000; 55 timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
56 vddmin = voltdm->pmic->vp_vddmin; 56 vddmin = voltdm->pmic->vp_vddmin;
57 vddmax = voltdm->pmic->vp_vddmax; 57 vddmax = voltdm->pmic->vp_vddmax;
58 58
59 waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) * 59 waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) *
60 sys_clk_rate) / 1000; 60 sys_clk_rate) / 1000;
61 vstepmin = voltdm->pmic->vp_vstepmin; 61 vstepmin = voltdm->pmic->vp_vstepmin;
62 vstepmax = voltdm->pmic->vp_vstepmax; 62 vstepmax = voltdm->pmic->vp_vstepmax;
63 63
64 /* 64 /*
65 * VP_CONFIG: error gain is not set here, it will be updated 65 * VP_CONFIG: error gain is not set here, it will be updated
66 * on each scale, based on OPP. 66 * on each scale, based on OPP.
67 */ 67 */
68 val = (voltdm->pmic->vp_erroroffset << 68 val = (voltdm->pmic->vp_erroroffset <<
69 __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) | 69 __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) |
70 vp->common->vpconfig_timeouten; 70 vp->common->vpconfig_timeouten;
71 voltdm->write(val, vp->vpconfig); 71 voltdm->write(val, vp->vpconfig);
72 72
73 /* VSTEPMIN */ 73 /* VSTEPMIN */
74 val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) | 74 val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) |
75 (vstepmin << vp->common->vstepmin_stepmin_shift); 75 (vstepmin << vp->common->vstepmin_stepmin_shift);
76 voltdm->write(val, vp->vstepmin); 76 voltdm->write(val, vp->vstepmin);
77 77
78 /* VSTEPMAX */ 78 /* VSTEPMAX */
79 val = (vstepmax << vp->common->vstepmax_stepmax_shift) | 79 val = (vstepmax << vp->common->vstepmax_stepmax_shift) |
80 (waittime << vp->common->vstepmax_smpswaittimemax_shift); 80 (waittime << vp->common->vstepmax_smpswaittimemax_shift);
81 voltdm->write(val, vp->vstepmax); 81 voltdm->write(val, vp->vstepmax);
82 82
83 /* VLIMITTO */ 83 /* VLIMITTO */
84 val = (vddmax << vp->common->vlimitto_vddmax_shift) | 84 val = (vddmax << vp->common->vlimitto_vddmax_shift) |
85 (vddmin << vp->common->vlimitto_vddmin_shift) | 85 (vddmin << vp->common->vlimitto_vddmin_shift) |
86 (timeout << vp->common->vlimitto_timeout_shift); 86 (timeout << vp->common->vlimitto_timeout_shift);
87 voltdm->write(val, vp->vlimitto); 87 voltdm->write(val, vp->vlimitto);
88 } 88 }
89 89
90 int omap_vp_update_errorgain(struct voltagedomain *voltdm, 90 int omap_vp_update_errorgain(struct voltagedomain *voltdm,
91 unsigned long target_volt) 91 unsigned long target_volt)
92 { 92 {
93 struct omap_volt_data *volt_data; 93 struct omap_volt_data *volt_data;
94 94
95 if (!voltdm->vp) 95 if (!voltdm->vp)
96 return -EINVAL; 96 return -EINVAL;
97 97
98 /* Get volt_data corresponding to target_volt */ 98 /* Get volt_data corresponding to target_volt */
99 volt_data = omap_voltage_get_voltdata(voltdm, target_volt); 99 volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
100 if (IS_ERR(volt_data)) 100 if (IS_ERR(volt_data))
101 return -EINVAL; 101 return -EINVAL;
102 102
103 /* Setting vp errorgain based on the voltage */ 103 /* Setting vp errorgain based on the voltage */
104 voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask, 104 voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask,
105 volt_data->vp_errgain << 105 volt_data->vp_errgain <<
106 __ffs(voltdm->vp->common->vpconfig_errorgain_mask), 106 __ffs(voltdm->vp->common->vpconfig_errorgain_mask),
107 voltdm->vp->vpconfig); 107 voltdm->vp->vpconfig);
108 108
109 return 0; 109 return 0;
110 } 110 }
111 111
112 /* VP force update method of voltage scaling */ 112 /* VP force update method of voltage scaling */
113 int omap_vp_forceupdate_scale(struct voltagedomain *voltdm, 113 int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
114 unsigned long target_volt) 114 unsigned long target_volt)
115 { 115 {
116 struct omap_vp_instance *vp = voltdm->vp; 116 struct omap_vp_instance *vp = voltdm->vp;
117 u32 vpconfig; 117 u32 vpconfig;
118 u8 target_vsel, current_vsel; 118 u8 target_vsel, current_vsel;
119 int ret, timeout = 0; 119 int ret, timeout = 0;
120 120
121 ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel); 121 ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
122 if (ret) 122 if (ret)
123 return ret; 123 return ret;
124 124
125 /* 125 /*
126 * Clear all pending TransactionDone interrupt/status. Typical latency 126 * Clear all pending TransactionDone interrupt/status. Typical latency
127 * is <3us 127 * is <3us
128 */ 128 */
129 while (timeout++ < VP_TRANXDONE_TIMEOUT) { 129 while (timeout++ < VP_TRANXDONE_TIMEOUT) {
130 vp->common->ops->clear_txdone(vp->id); 130 vp->common->ops->clear_txdone(vp->id);
131 if (!vp->common->ops->check_txdone(vp->id)) 131 if (!vp->common->ops->check_txdone(vp->id))
132 break; 132 break;
133 udelay(1); 133 udelay(1);
134 } 134 }
135 if (timeout >= VP_TRANXDONE_TIMEOUT) { 135 if (timeout >= VP_TRANXDONE_TIMEOUT) {
136 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded." 136 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
137 "Voltage change aborted", __func__, voltdm->name); 137 "Voltage change aborted", __func__, voltdm->name);
138 return -ETIMEDOUT; 138 return -ETIMEDOUT;
139 } 139 }
140 140
141 vpconfig = _vp_set_init_voltage(voltdm, target_volt); 141 vpconfig = _vp_set_init_voltage(voltdm, target_volt);
142 142
143 /* Force update of voltage */ 143 /* Force update of voltage */
144 voltdm->write(vpconfig | vp->common->vpconfig_forceupdate, 144 voltdm->write(vpconfig | vp->common->vpconfig_forceupdate,
145 voltdm->vp->vpconfig); 145 voltdm->vp->vpconfig);
146 146
147 /* 147 /*
148 * Wait for TransactionDone. Typical latency is <200us. 148 * Wait for TransactionDone. Typical latency is <200us.
149 * Depends on SMPSWAITTIMEMIN/MAX and voltage change 149 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
150 */ 150 */
151 timeout = 0; 151 timeout = 0;
152 omap_test_timeout(vp->common->ops->check_txdone(vp->id), 152 omap_test_timeout(vp->common->ops->check_txdone(vp->id),
153 VP_TRANXDONE_TIMEOUT, timeout); 153 VP_TRANXDONE_TIMEOUT, timeout);
154 if (timeout >= VP_TRANXDONE_TIMEOUT) 154 if (timeout >= VP_TRANXDONE_TIMEOUT)
155 pr_err("%s: vdd_%s TRANXDONE timeout exceeded." 155 pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
156 "TRANXDONE never got set after the voltage update\n", 156 "TRANXDONE never got set after the voltage update\n",
157 __func__, voltdm->name); 157 __func__, voltdm->name);
158 158
159 omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel); 159 omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
160 160
161 /* 161 /*
162 * Disable TransactionDone interrupt , clear all status, clear 162 * Disable TransactionDone interrupt , clear all status, clear
163 * control registers 163 * control registers
164 */ 164 */
165 timeout = 0; 165 timeout = 0;
166 while (timeout++ < VP_TRANXDONE_TIMEOUT) { 166 while (timeout++ < VP_TRANXDONE_TIMEOUT) {
167 vp->common->ops->clear_txdone(vp->id); 167 vp->common->ops->clear_txdone(vp->id);
168 if (!vp->common->ops->check_txdone(vp->id)) 168 if (!vp->common->ops->check_txdone(vp->id))
169 break; 169 break;
170 udelay(1); 170 udelay(1);
171 } 171 }
172 172
173 if (timeout >= VP_TRANXDONE_TIMEOUT) 173 if (timeout >= VP_TRANXDONE_TIMEOUT)
174 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying" 174 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
175 "to clear the TRANXDONE status\n", 175 "to clear the TRANXDONE status\n",
176 __func__, voltdm->name); 176 __func__, voltdm->name);
177 177
178 /* Clear force bit */ 178 /* Clear force bit */
179 voltdm->write(vpconfig, vp->vpconfig); 179 voltdm->write(vpconfig, vp->vpconfig);
180 180
181 return 0; 181 return 0;
182 } 182 }
183 183
184 /** 184 /**
185 * omap_vp_enable() - API to enable a particular VP 185 * omap_vp_enable() - API to enable a particular VP
186 * @voltdm: pointer to the VDD whose VP is to be enabled. 186 * @voltdm: pointer to the VDD whose VP is to be enabled.
187 * 187 *
188 * This API enables a particular voltage processor. Needed by the smartreflex 188 * This API enables a particular voltage processor. Needed by the smartreflex
189 * class drivers. 189 * class drivers.
190 */ 190 */
191 void omap_vp_enable(struct voltagedomain *voltdm) 191 void omap_vp_enable(struct voltagedomain *voltdm)
192 { 192 {
193 struct omap_vp_instance *vp; 193 struct omap_vp_instance *vp;
194 u32 vpconfig, volt; 194 u32 vpconfig, volt;
195 195
196 if (!voltdm || IS_ERR(voltdm)) { 196 if (!voltdm || IS_ERR(voltdm)) {
197 pr_warning("%s: VDD specified does not exist!\n", __func__); 197 pr_warning("%s: VDD specified does not exist!\n", __func__);
198 return; 198 return;
199 } 199 }
200 200
201 vp = voltdm->vp; 201 vp = voltdm->vp;
202 if (!voltdm->read || !voltdm->write) { 202 if (!voltdm->read || !voltdm->write) {
203 pr_err("%s: No read/write API for accessing vdd_%s regs\n", 203 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
204 __func__, voltdm->name); 204 __func__, voltdm->name);
205 return; 205 return;
206 } 206 }
207 207
208 /* If VP is already enabled, do nothing. Return */ 208 /* If VP is already enabled, do nothing. Return */
209 if (vp->enabled) 209 if (vp->enabled)
210 return; 210 return;
211 211
212 volt = voltdm_get_voltage(voltdm); 212 volt = voltdm_get_voltage(voltdm);
213 if (!volt) { 213 if (!volt) {
214 pr_warning("%s: unable to find current voltage for %s\n", 214 pr_warning("%s: unable to find current voltage for %s\n",
215 __func__, voltdm->name); 215 __func__, voltdm->name);
216 return; 216 return;
217 } 217 }
218 218
219 vpconfig = _vp_set_init_voltage(voltdm, volt); 219 vpconfig = _vp_set_init_voltage(voltdm, volt);
220 220
221 /* Enable VP */ 221 /* Enable VP */
222 vpconfig |= vp->common->vpconfig_vpenable; 222 vpconfig |= vp->common->vpconfig_vpenable;
223 voltdm->write(vpconfig, vp->vpconfig); 223 voltdm->write(vpconfig, vp->vpconfig);
224 224
225 vp->enabled = true; 225 vp->enabled = true;
226 } 226 }
227 227
228 /** 228 /**
229 * omap_vp_disable() - API to disable a particular VP 229 * omap_vp_disable() - API to disable a particular VP
230 * @voltdm: pointer to the VDD whose VP is to be disabled. 230 * @voltdm: pointer to the VDD whose VP is to be disabled.
231 * 231 *
232 * This API disables a particular voltage processor. Needed by the smartreflex 232 * This API disables a particular voltage processor. Needed by the smartreflex
233 * class drivers. 233 * class drivers.
234 */ 234 */
235 void omap_vp_disable(struct voltagedomain *voltdm) 235 void omap_vp_disable(struct voltagedomain *voltdm)
236 { 236 {
237 struct omap_vp_instance *vp; 237 struct omap_vp_instance *vp;
238 u32 vpconfig; 238 u32 vpconfig;
239 int timeout; 239 int timeout;
240 240
241 if (!voltdm || IS_ERR(voltdm)) { 241 if (!voltdm || IS_ERR(voltdm)) {
242 pr_warning("%s: VDD specified does not exist!\n", __func__); 242 pr_warning("%s: VDD specified does not exist!\n", __func__);
243 return; 243 return;
244 } 244 }
245 245
246 vp = voltdm->vp; 246 vp = voltdm->vp;
247 if (!voltdm->read || !voltdm->write) { 247 if (!voltdm->read || !voltdm->write) {
248 pr_err("%s: No read/write API for accessing vdd_%s regs\n", 248 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
249 __func__, voltdm->name); 249 __func__, voltdm->name);
250 return; 250 return;
251 } 251 }
252 252
253 /* If VP is already disabled, do nothing. Return */ 253 /* If VP is already disabled, do nothing. Return */
254 if (!vp->enabled) { 254 if (!vp->enabled) {
255 pr_warning("%s: Trying to disable VP for vdd_%s when" 255 pr_warning("%s: Trying to disable VP for vdd_%s when"
256 "it is already disabled\n", __func__, voltdm->name); 256 "it is already disabled\n", __func__, voltdm->name);
257 return; 257 return;
258 } 258 }
259 259
260 /* Disable VP */ 260 /* Disable VP */
261 vpconfig = voltdm->read(vp->vpconfig); 261 vpconfig = voltdm->read(vp->vpconfig);
262 vpconfig &= ~vp->common->vpconfig_vpenable; 262 vpconfig &= ~vp->common->vpconfig_vpenable;
263 voltdm->write(vpconfig, vp->vpconfig); 263 voltdm->write(vpconfig, vp->vpconfig);
264 264
265 /* 265 /*
266 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us 266 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
267 */ 267 */
268 omap_test_timeout((voltdm->read(vp->vstatus)), 268 omap_test_timeout((voltdm->read(vp->vstatus)),
269 VP_IDLE_TIMEOUT, timeout); 269 VP_IDLE_TIMEOUT, timeout);
270 270
271 if (timeout >= VP_IDLE_TIMEOUT) 271 if (timeout >= VP_IDLE_TIMEOUT)
272 pr_warning("%s: vdd_%s idle timedout\n", 272 pr_warning("%s: vdd_%s idle timedout\n",
273 __func__, voltdm->name); 273 __func__, voltdm->name);
274 274
275 vp->enabled = false; 275 vp->enabled = false;
276 276
277 return; 277 return;
arch/arm/mach-omap2/vp.h
1 /* File was deleted
2 * OMAP3/4 Voltage Processor (VP) structure and macro definitions
3 *
4 * Copyright (C) 2007, 2010 Texas Instruments, Inc.
5 * Rajendra Nayak <rnayak@ti.com>
6 * Lesly A M <x0080970@ti.com>
7 * Thara Gopinath <thara@ti.com>
8 *
9 * Copyright (C) 2008, 2011 Nokia Corporation
10 * Kalle Jokiniemi
11 * Paul Walmsley
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License version
15 * 2 as published by the Free Software Foundation.
16 */
17 #ifndef __ARCH_ARM_MACH_OMAP2_VP_H
18 #define __ARCH_ARM_MACH_OMAP2_VP_H
19
20 #include <linux/kernel.h>
21
22 struct voltagedomain;
23
24 /*
25 * Voltage Processor (VP) identifiers
26 */
27 #define OMAP3_VP_VDD_MPU_ID 0
28 #define OMAP3_VP_VDD_CORE_ID 1
29 #define OMAP4_VP_VDD_CORE_ID 0
30 #define OMAP4_VP_VDD_IVA_ID 1
31 #define OMAP4_VP_VDD_MPU_ID 2
32
33 /* XXX document */
34 #define VP_IDLE_TIMEOUT 200
35 #define VP_TRANXDONE_TIMEOUT 300
36
37 /**
38 * struct omap_vp_ops - per-VP operations
39 * @check_txdone: check for VP transaction done
40 * @clear_txdone: clear VP transaction done status
41 */
42 struct omap_vp_ops {
43 u32 (*check_txdone)(u8 vp_id);
44 void (*clear_txdone)(u8 vp_id);
45 };
46
47 /**
48 * struct omap_vp_common - register data common to all VDDs
49 * @vpconfig_erroroffset_mask: ERROROFFSET bitmask in the PRM_VP*_CONFIG reg
50 * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg
51 * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg
52 * @vpconfig_timeouten: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
53 * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg
54 * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg
55 * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg
56 * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg
57 * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg
58 * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg
59 * @vstepmin_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
60 * @vstepmin_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
61 * @vstepmax_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
62 * @vstepmax_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
63 * @vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
64 * @vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
65 * @vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
66 * @vpvoltage_mask: VPVOLTAGE field mask in PRM_VP*_VOLTAGE reg
67 */
68 struct omap_vp_common {
69 u32 vpconfig_erroroffset_mask;
70 u32 vpconfig_errorgain_mask;
71 u32 vpconfig_initvoltage_mask;
72 u8 vpconfig_timeouten;
73 u8 vpconfig_initvdd;
74 u8 vpconfig_forceupdate;
75 u8 vpconfig_vpenable;
76 u8 vstepmin_stepmin_shift;
77 u8 vstepmin_smpswaittimemin_shift;
78 u8 vstepmax_stepmax_shift;
79 u8 vstepmax_smpswaittimemax_shift;
80 u8 vlimitto_vddmin_shift;
81 u8 vlimitto_vddmax_shift;
82 u8 vlimitto_timeout_shift;
83 u8 vpvoltage_mask;
84
85 const struct omap_vp_ops *ops;
86 };
87
88 /**
89 * struct omap_vp_instance - VP register offsets (per-VDD)
90 * @common: pointer to struct omap_vp_common * for this SoC
91 * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start
92 * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start
93 * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start
94 * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start
95 * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start
96 * @id: Unique identifier for VP instance.
97 * @enabled: flag to keep track of whether vp is enabled or not
98 *
99 * XXX vp_common is probably not needed since it is per-SoC
100 */
101 struct omap_vp_instance {
102 const struct omap_vp_common *common;
103 u8 vpconfig;
104 u8 vstepmin;
105 u8 vstepmax;
106 u8 vlimitto;
107 u8 vstatus;
108 u8 voltage;
109 u8 id;
110 bool enabled;
111 };
112
113 extern struct omap_vp_instance omap3_vp_mpu;
114 extern struct omap_vp_instance omap3_vp_core;
115
116 extern struct omap_vp_instance omap4_vp_mpu;
117 extern struct omap_vp_instance omap4_vp_iva;
118 extern struct omap_vp_instance omap4_vp_core;
119
120 void omap_vp_init(struct voltagedomain *voltdm);
121 void omap_vp_enable(struct voltagedomain *voltdm);
122 void omap_vp_disable(struct voltagedomain *voltdm);
123 int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
124 unsigned long target_volt);
125 int omap_vp_update_errorgain(struct voltagedomain *voltdm,
126 unsigned long target_volt);
127
128 #endif
129 1 /*
arch/arm/mach-omap2/vp3xxx_data.c
1 /* 1 /*
2 * OMAP3 Voltage Processor (VP) data 2 * OMAP3 Voltage Processor (VP) data
3 * 3 *
4 * Copyright (C) 2007, 2010 Texas Instruments, Inc. 4 * Copyright (C) 2007, 2010 Texas Instruments, Inc.
5 * Rajendra Nayak <rnayak@ti.com> 5 * Rajendra Nayak <rnayak@ti.com>
6 * Lesly A M <x0080970@ti.com> 6 * Lesly A M <x0080970@ti.com>
7 * Thara Gopinath <thara@ti.com> 7 * Thara Gopinath <thara@ti.com>
8 * 8 *
9 * Copyright (C) 2008, 2011 Nokia Corporation 9 * Copyright (C) 2008, 2011 Nokia Corporation
10 * Kalle Jokiniemi 10 * Kalle Jokiniemi
11 * Paul Walmsley 11 * Paul Walmsley
12 * 12 *
13 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as 14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation. 15 * published by the Free Software Foundation.
16 */ 16 */
17 17
18 #include <linux/io.h> 18 #include <linux/io.h>
19 #include <linux/err.h> 19 #include <linux/err.h>
20 #include <linux/init.h> 20 #include <linux/init.h>
21 21
22 #include <plat/common.h> 22 #include <plat/common.h>
23 #include <plat/voltage.h>
24 #include <plat/vp.h>
23 25
24 #include "prm-regbits-34xx.h" 26 #include "prm-regbits-34xx.h"
25 #include "voltage.h"
26 27
27 #include "vp.h"
28 #include "prm2xxx_3xxx.h" 28 #include "prm2xxx_3xxx.h"
29 29
30 static const struct omap_vp_ops omap3_vp_ops = { 30 static const struct omap_vp_ops omap3_vp_ops = {
31 .check_txdone = omap3_prm_vp_check_txdone, 31 .check_txdone = omap3_prm_vp_check_txdone,
32 .clear_txdone = omap3_prm_vp_clear_txdone, 32 .clear_txdone = omap3_prm_vp_clear_txdone,
33 }; 33 };
34 34
35 /* 35 /*
36 * VP data common to 34xx/36xx chips 36 * VP data common to 34xx/36xx chips
37 * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file. 37 * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file.
38 */ 38 */
39 static const struct omap_vp_common omap3_vp_common = { 39 static const struct omap_vp_common omap3_vp_common = {
40 .vpconfig_erroroffset_mask = OMAP3430_ERROROFFSET_MASK, 40 .vpconfig_erroroffset_mask = OMAP3430_ERROROFFSET_MASK,
41 .vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK, 41 .vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK,
42 .vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK, 42 .vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK,
43 .vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK, 43 .vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK,
44 .vpconfig_initvdd = OMAP3430_INITVDD_MASK, 44 .vpconfig_initvdd = OMAP3430_INITVDD_MASK,
45 .vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK, 45 .vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK,
46 .vpconfig_vpenable = OMAP3430_VPENABLE_MASK, 46 .vpconfig_vpenable = OMAP3430_VPENABLE_MASK,
47 .vstepmin_smpswaittimemin_shift = OMAP3430_SMPSWAITTIMEMIN_SHIFT, 47 .vstepmin_smpswaittimemin_shift = OMAP3430_SMPSWAITTIMEMIN_SHIFT,
48 .vstepmax_smpswaittimemax_shift = OMAP3430_SMPSWAITTIMEMAX_SHIFT, 48 .vstepmax_smpswaittimemax_shift = OMAP3430_SMPSWAITTIMEMAX_SHIFT,
49 .vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT, 49 .vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT,
50 .vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT, 50 .vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT,
51 .vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT, 51 .vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT,
52 .vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT, 52 .vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT,
53 .vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT, 53 .vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT,
54 .vpvoltage_mask = OMAP3430_VPVOLTAGE_MASK, 54 .vpvoltage_mask = OMAP3430_VPVOLTAGE_MASK,
55 55
56 .ops = &omap3_vp_ops, 56 .ops = &omap3_vp_ops,
57 }; 57 };
58 58
59 struct omap_vp_instance omap3_vp_mpu = { 59 struct omap_vp_instance omap3_vp_mpu = {
60 .id = OMAP3_VP_VDD_MPU_ID, 60 .id = OMAP3_VP_VDD_MPU_ID,
61 .common = &omap3_vp_common, 61 .common = &omap3_vp_common,
62 .vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET, 62 .vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
63 .vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET, 63 .vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
64 .vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET, 64 .vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
65 .vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET, 65 .vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
66 .vstatus = OMAP3_PRM_VP1_STATUS_OFFSET, 66 .vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
67 .voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET, 67 .voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
68 }; 68 };
69 69
70 struct omap_vp_instance omap3_vp_core = { 70 struct omap_vp_instance omap3_vp_core = {
71 .id = OMAP3_VP_VDD_CORE_ID, 71 .id = OMAP3_VP_VDD_CORE_ID,
72 .common = &omap3_vp_common, 72 .common = &omap3_vp_common,
73 .vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET, 73 .vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
74 .vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET, 74 .vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
75 .vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET, 75 .vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
76 .vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET, 76 .vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
77 .vstatus = OMAP3_PRM_VP2_STATUS_OFFSET, 77 .vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
78 .voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET, 78 .voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
arch/arm/mach-omap2/vp44xx_data.c
1 /* 1 /*
2 * OMAP3 Voltage Processor (VP) data 2 * OMAP3 Voltage Processor (VP) data
3 * 3 *
4 * Copyright (C) 2007, 2010 Texas Instruments, Inc. 4 * Copyright (C) 2007, 2010 Texas Instruments, Inc.
5 * Rajendra Nayak <rnayak@ti.com> 5 * Rajendra Nayak <rnayak@ti.com>
6 * Lesly A M <x0080970@ti.com> 6 * Lesly A M <x0080970@ti.com>
7 * Thara Gopinath <thara@ti.com> 7 * Thara Gopinath <thara@ti.com>
8 * 8 *
9 * Copyright (C) 2008, 2011 Nokia Corporation 9 * Copyright (C) 2008, 2011 Nokia Corporation
10 * Kalle Jokiniemi 10 * Kalle Jokiniemi
11 * Paul Walmsley 11 * Paul Walmsley
12 * 12 *
13 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as 14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation. 15 * published by the Free Software Foundation.
16 */ 16 */
17 17
18 #include <linux/io.h> 18 #include <linux/io.h>
19 #include <linux/err.h> 19 #include <linux/err.h>
20 #include <linux/init.h> 20 #include <linux/init.h>
21 21
22 #include <plat/common.h> 22 #include <plat/common.h>
23 #include <plat/voltage.h>
24 #include <plat/vp.h>
23 25
24 #include "prm44xx.h" 26 #include "prm44xx.h"
25 #include "prm-regbits-44xx.h" 27 #include "prm-regbits-44xx.h"
26 #include "voltage.h"
27
28 #include "vp.h"
29 28
30 static const struct omap_vp_ops omap4_vp_ops = { 29 static const struct omap_vp_ops omap4_vp_ops = {
31 .check_txdone = omap4_prm_vp_check_txdone, 30 .check_txdone = omap4_prm_vp_check_txdone,
32 .clear_txdone = omap4_prm_vp_clear_txdone, 31 .clear_txdone = omap4_prm_vp_clear_txdone,
33 }; 32 };
34 33
35 /* 34 /*
36 * VP data common to 44xx chips 35 * VP data common to 44xx chips
37 * XXX This stuff presumably belongs in the vp44xx.c or vp.c file. 36 * XXX This stuff presumably belongs in the vp44xx.c or vp.c file.
38 */ 37 */
39 static const struct omap_vp_common omap4_vp_common = { 38 static const struct omap_vp_common omap4_vp_common = {
40 .vpconfig_erroroffset_mask = OMAP4430_ERROROFFSET_MASK, 39 .vpconfig_erroroffset_mask = OMAP4430_ERROROFFSET_MASK,
41 .vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK, 40 .vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK,
42 .vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK, 41 .vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK,
43 .vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK, 42 .vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK,
44 .vpconfig_initvdd = OMAP4430_INITVDD_MASK, 43 .vpconfig_initvdd = OMAP4430_INITVDD_MASK,
45 .vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK, 44 .vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK,
46 .vpconfig_vpenable = OMAP4430_VPENABLE_MASK, 45 .vpconfig_vpenable = OMAP4430_VPENABLE_MASK,
47 .vstepmin_smpswaittimemin_shift = OMAP4430_SMPSWAITTIMEMIN_SHIFT, 46 .vstepmin_smpswaittimemin_shift = OMAP4430_SMPSWAITTIMEMIN_SHIFT,
48 .vstepmax_smpswaittimemax_shift = OMAP4430_SMPSWAITTIMEMAX_SHIFT, 47 .vstepmax_smpswaittimemax_shift = OMAP4430_SMPSWAITTIMEMAX_SHIFT,
49 .vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT, 48 .vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT,
50 .vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT, 49 .vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT,
51 .vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT, 50 .vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT,
52 .vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT, 51 .vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT,
53 .vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT, 52 .vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT,
54 .vpvoltage_mask = OMAP4430_VPVOLTAGE_MASK, 53 .vpvoltage_mask = OMAP4430_VPVOLTAGE_MASK,
55 .ops = &omap4_vp_ops, 54 .ops = &omap4_vp_ops,
56 }; 55 };
57 56
58 struct omap_vp_instance omap4_vp_mpu = { 57 struct omap_vp_instance omap4_vp_mpu = {
59 .id = OMAP4_VP_VDD_MPU_ID, 58 .id = OMAP4_VP_VDD_MPU_ID,
60 .common = &omap4_vp_common, 59 .common = &omap4_vp_common,
61 .vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET, 60 .vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
62 .vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET, 61 .vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
63 .vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET, 62 .vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
64 .vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET, 63 .vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
65 .vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET, 64 .vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
66 .voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET, 65 .voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
67 }; 66 };
68 67
69 struct omap_vp_instance omap4_vp_iva = { 68 struct omap_vp_instance omap4_vp_iva = {
70 .id = OMAP4_VP_VDD_IVA_ID, 69 .id = OMAP4_VP_VDD_IVA_ID,
71 .common = &omap4_vp_common, 70 .common = &omap4_vp_common,
72 .vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET, 71 .vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
73 .vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET, 72 .vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
74 .vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET, 73 .vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
75 .vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET, 74 .vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
76 .vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET, 75 .vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
77 .voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET, 76 .voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
78 }; 77 };
79 78
80 struct omap_vp_instance omap4_vp_core = { 79 struct omap_vp_instance omap4_vp_core = {
81 .id = OMAP4_VP_VDD_CORE_ID, 80 .id = OMAP4_VP_VDD_CORE_ID,
82 .common = &omap4_vp_common, 81 .common = &omap4_vp_common,
83 .vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET, 82 .vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
84 .vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET, 83 .vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
85 .vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET, 84 .vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
86 .vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET, 85 .vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
87 .vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET, 86 .vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
88 .voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET, 87 .voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
arch/arm/plat-omap/include/plat/dvfs.h
File was created 1 /*
2 * OMAP3/OMAP4 DVFS Management Routines
3 *
4 * Author: Vishwanath BS <vishwanath.bs@ti.com>
5 *
6 * Copyright (C) 2011 Texas Instruments, Inc.
7 * Vishwanath BS <vishwanath.bs@ti.com>
8 *
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
11 * published by the Free Software Foundation.
12 */
13
14 #ifndef __ARCH_ARM_MACH_OMAP2_DVFS_H
15 #define __ARCH_ARM_MACH_OMAP2_DVFS_H
16 #include <plat/omap_hwmod.h>
17 #include <plat/voltage.h>
18
19 #ifdef CONFIG_PM
20 int omap_dvfs_register_device(struct device *dev, char *voltdm_name,
21 char *clk_name);
22 int omap_device_scale(struct device *req_dev, struct device *target_dev,
23 unsigned long rate);
24 #else
25 static inline int omap_dvfs_register_device(struct omap_hwmod *oh,
26 struct device *dev)
27 static inline int omap_dvfs_register_device(struct device *dev,
28 char *voltdm_name, char *clk_name)
29 {
30 return -EINVAL;
31 }
32 static inline int omap_device_scale(struct device *req_dev,
33 struct device *target_dev, unsigned long rate)
34 {
35 return -EINVAL;
36 }
37 #endif
38 #endif
39
arch/arm/plat-omap/include/plat/vc.h
File was created 1 /*
2 * OMAP3/4 Voltage Controller (VC) structure and macro definitions
3 *
4 * Copyright (C) 2007, 2010 Texas Instruments, Inc.
5 * Rajendra Nayak <rnayak@ti.com>
6 * Lesly A M <x0080970@ti.com>
7 * Thara Gopinath <thara@ti.com>
8 *
9 * Copyright (C) 2008, 2011 Nokia Corporation
10 * Kalle Jokiniemi
11 * Paul Walmsley
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License version
15 * 2 as published by the Free Software Foundation.
16 */
17 #ifndef __ARCH_ARM_MACH_OMAP2_VC_H
18 #define __ARCH_ARM_MACH_OMAP2_VC_H
19
20 #include <linux/kernel.h>
21
22 struct voltagedomain;
23
24 /**
25 * struct omap_vc_common - per-VC register/bitfield data
26 * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register
27 * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register
28 * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start
29 * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register
30 * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register
31 * @regaddr_shift: REGADDR field shift in PRM_VC_BYPASS_VAL register
32 * @cmd_on_shift: ON field shift in PRM_VC_CMD_VAL_* register
33 * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register
34 * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
35 * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
36 * @i2c_cfg_reg: I2C configuration register offset
37 * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register
38 * @i2c_mcode_mask: MCODE field mask for I2C config register
39 *
40 * XXX One of cmd_on_mask and cmd_on_shift are not needed
41 * XXX VALID should probably be a shift, not a mask
42 */
43 struct omap_vc_common {
44 u32 cmd_on_mask;
45 u32 valid;
46 u8 bypass_val_reg;
47 u8 data_shift;
48 u8 slaveaddr_shift;
49 u8 regaddr_shift;
50 u8 cmd_on_shift;
51 u8 cmd_onlp_shift;
52 u8 cmd_ret_shift;
53 u8 cmd_off_shift;
54 u8 i2c_cfg_reg;
55 u8 i2c_cfg_hsen_mask;
56 u8 i2c_mcode_mask;
57 };
58
59 /* omap_vc_channel.flags values */
60 #define OMAP_VC_CHANNEL_DEFAULT BIT(0)
61 #define OMAP_VC_CHANNEL_CFG_MUTANT BIT(1)
62
63 /**
64 * struct omap_vc_channel - VC per-instance data
65 * @i2c_slave_addr: I2C slave address of PMIC for this VC channel
66 * @volt_reg_addr: voltage configuration register address
67 * @cmd_reg_addr: command configuration register address
68 * @setup_time: setup time (in sys_clk cycles) of regulator for this channel
69 * @cfg_channel: current value of VC channel configuration register
70 * @i2c_high_speed: whether or not to use I2C high-speed mode
71 *
72 * @common: pointer to VC common data for this platform
73 * @smps_sa_mask: i2c slave address bitmask in the PRM_VC_SMPS_SA register
74 * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
75 * @smps_cmdra_mask: CMDRA* bitmask in the PRM_VC_CMD_RA register
76 * @cmdval_reg: register for on/ret/off voltage level values for this channel
77 * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
78 * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
79 * @smps_cmdra_reg: Offset of PRM_VC_SMPS_CMD_RA reg from PRM start
80 * @cfg_channel_reg: VC channel configuration register
81 * @cfg_channel_sa_shift: bit shift for slave address cfg_channel register
82 * @flags: VC channel-specific flags (optional)
83 */
84 struct omap_vc_channel {
85 /* channel state */
86 u16 i2c_slave_addr;
87 u16 volt_reg_addr;
88 u16 cmd_reg_addr;
89 u16 setup_time;
90 u8 cfg_channel;
91 bool i2c_high_speed;
92
93 /* register access data */
94 const struct omap_vc_common *common;
95 u32 smps_sa_mask;
96 u32 smps_volra_mask;
97 u32 smps_cmdra_mask;
98 u8 cmdval_reg;
99 u8 smps_sa_reg;
100 u8 smps_volra_reg;
101 u8 smps_cmdra_reg;
102 u8 cfg_channel_reg;
103 u8 cfg_channel_sa_shift;
104 u8 flags;
105 };
106
107 extern struct omap_vc_channel omap3_vc_mpu;
108 extern struct omap_vc_channel omap3_vc_core;
109
110 extern struct omap_vc_channel omap4_vc_mpu;
111 extern struct omap_vc_channel omap4_vc_iva;
112 extern struct omap_vc_channel omap4_vc_core;
113
114 void omap_vc_init_channel(struct voltagedomain *voltdm);
115 int omap_vc_pre_scale(struct voltagedomain *voltdm,
116 unsigned long target_volt,
117 u8 *target_vsel, u8 *current_vsel);
118 void omap_vc_post_scale(struct voltagedomain *voltdm,
119 unsigned long target_volt,
120 u8 target_vsel, u8 current_vsel);
121 int omap_vc_bypass_scale(struct voltagedomain *voltdm,
122 unsigned long target_volt);
123
124 #endif
125
arch/arm/plat-omap/include/plat/voltage.h
1 /* 1 /*
2 * OMAP Voltage Management Routines 2 * OMAP Voltage Management Routines
3 * 3 *
4 * Copyright (C) 2011, Texas Instruments, Inc. 4 * Author: Thara Gopinath <thara@ti.com>
5 * 5 *
6 * Copyright (C) 2009 Texas Instruments, Inc.
7 * Thara Gopinath <thara@ti.com>
8 *
6 * 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
7 * 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
8 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
9 */ 12 */
10 13
11 #ifndef __ARCH_ARM_OMAP_VOLTAGE_H 14 #ifndef __ARCH_ARM_OMAP_VOLTAGE_H
12 #define __ARCH_ARM_OMAP_VOLTAGE_H 15 #define __ARCH_ARM_OMAP_VOLTAGE_H
13 16
14 struct voltagedomain; 17 #include <linux/err.h>
15 18
19 #include <plat/vc.h>
20 #include <plat/vp.h>
21
22 struct powerdomain;
23
24 /* XXX document */
25 #define VOLTSCALE_VPFORCEUPDATE 1
26 #define VOLTSCALE_VCBYPASS 2
27
28 /*
29 * OMAP3 GENERIC setup times. Revisit to see if these needs to be
30 * passed from board or PMIC file
31 */
32 #define OMAP3_CLKSETUP 0xff
33 #define OMAP3_VOLTOFFSET 0xff
34 #define OMAP3_VOLTSETUP2 0xff
35
36 struct omap_vdd_info;
37
38 /**
39 * struct omap_vfsm_instance - per-voltage manager FSM register/bitfield
40 * data
41 * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
42 * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
43 *
44 * XXX What about VOLTOFFSET/VOLTCTRL?
45 */
46 struct omap_vfsm_instance {
47 u32 voltsetup_mask;
48 u8 voltsetup_reg;
49 };
50
51 /**
52 * struct voltagedomain - omap voltage domain global structure.
53 * @name: Name of the voltage domain which can be used as a unique identifier.
54 * @scalable: Whether or not this voltage domain is scalable
55 * @node: list_head linking all voltage domains
56 * @pwrdm_list: list_head linking all powerdomains in this voltagedomain
57 * @vc: pointer to VC channel associated with this voltagedomain
58 * @vp: pointer to VP associated with this voltagedomain
59 * @read: read a VC/VP register
60 * @write: write a VC/VP register
61 * @read: read-modify-write a VC/VP register
62 * @sys_clk: system clock name/frequency, used for various timing calculations
63 * @scale: function used to scale the voltage of the voltagedomain
64 * @nominal_volt: current nominal voltage for this voltage domain
65 * @volt_data: voltage table having the distinct voltages supported
66 * by the domain and other associated per voltage data.
67 */
68 struct voltagedomain {
69 char *name;
70 bool scalable;
71 struct list_head node;
72 struct list_head pwrdm_list;
73 struct omap_vc_channel *vc;
74 const struct omap_vfsm_instance *vfsm;
75 struct omap_vp_instance *vp;
76 struct omap_voltdm_pmic *pmic;
77
78 /* VC/VP register access functions: SoC specific */
79 u32 (*read) (u8 offset);
80 void (*write) (u32 val, u8 offset);
81 u32 (*rmw)(u32 mask, u32 bits, u8 offset);
82
83 union {
84 const char *name;
85 u32 rate;
86 } sys_clk;
87
88 int (*scale) (struct voltagedomain *voltdm,
89 unsigned long target_volt);
90
91 u32 nominal_volt;
92 struct omap_volt_data *volt_data;
93 struct omap_vdd_info *vdd;
94 struct dentry *debug_dir;
95 };
96
97 /**
98 * struct omap_volt_data - Omap voltage specific data.
99 * @voltage_nominal: The possible voltage value in uV
100 * @sr_efuse_offs: The offset of the efuse register(from system
101 * control module base address) from where to read
102 * the n-target value for the smartreflex module.
103 * @sr_errminlimit: Error min limit value for smartreflex. This value
104 * differs at differnet opp and thus is linked
105 * with voltage.
106 * @vp_errorgain: Error gain value for the voltage processor. This
107 * field also differs according to the voltage/opp.
108 */
109 struct omap_volt_data {
110 u32 volt_nominal;
111 u32 sr_efuse_offs;
112 u8 sr_errminlimit;
113 u8 vp_errgain;
114 };
115
116 /**
117 * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
118 * @slew_rate: PMIC slew rate (in uv/us)
119 * @step_size: PMIC voltage step size (in uv)
120 * @i2c_slave_addr: I2C slave address of PMIC
121 * @volt_reg_addr: voltage configuration register address
122 * @cmd_reg_addr: command (on, on-LP, ret, off) configuration register address
123 * @i2c_high_speed: whether VC uses I2C high-speed mode to PMIC
124 * @i2c_mcode: master code value for I2C high-speed preamble transmission
125 * @vsel_to_uv: PMIC API to convert vsel value to actual voltage in uV.
126 * @uv_to_vsel: PMIC API to convert voltage in uV to vsel value.
127 */
128 struct omap_voltdm_pmic {
129 int slew_rate;
130 int step_size;
131 u32 on_volt;
132 u32 onlp_volt;
133 u32 ret_volt;
134 u32 off_volt;
135 u16 volt_setup_time;
136 u16 i2c_slave_addr;
137 u16 volt_reg_addr;
138 u16 cmd_reg_addr;
139 u8 vp_erroroffset;
140 u8 vp_vstepmin;
141 u8 vp_vstepmax;
142 u8 vp_vddmin;
143 u8 vp_vddmax;
144 u8 vp_timeout_us;
145 bool i2c_high_speed;
146 u8 i2c_mcode;
147 unsigned long (*vsel_to_uv) (const u8 vsel);
148 u8 (*uv_to_vsel) (unsigned long uV);
149 };
150
151 /**
152 * struct omap_vdd_dep_volt - Map table for voltage dependencies
153 * @main_vdd_volt : The main vdd voltage
154 * @dep_vdd_volt : The voltage at which the dependent vdd should be
155 * when the main vdd is at <main_vdd_volt> voltage
156 *
157 * Table containing the parent vdd voltage and the dependent vdd voltage
158 * corresponding to it.
159 */
160 struct omap_vdd_dep_volt {
161 u32 main_vdd_volt;
162 u32 dep_vdd_volt;
163 };
164
165 /**
166 * struct omap_vdd_dep_info - Dependent vdd info
167 * @name : Dependent vdd name
168 * @_dep_voltdm : internal structure meant to prevent multiple lookups
169 * @dep_table : Table containing the dependent vdd voltage
170 * corresponding to every main vdd voltage.
171 * @nr_dep_entries : number of dependency voltage entries
172 */
173 struct omap_vdd_dep_info {
174 char *name;
175 struct voltagedomain *_dep_voltdm;
176 struct omap_vdd_dep_volt *dep_table;
177 int nr_dep_entries;
178 };
179
180 /**
181 * omap_vdd_info - Per Voltage Domain info
182 *
183 * @volt_data : voltage table having the distinct voltages supported
184 * by the domain and other associated per voltage data.
185 * @dep_vdd_info : Array ending with a 0 terminator for dependency
186 * voltage information.
187 */
188 struct omap_vdd_info {
189 struct omap_volt_data *volt_data;
190 struct omap_vdd_dep_info *dep_vdd_info;
191 };
192
193 void omap_voltage_get_volttable(struct voltagedomain *voltdm,
194 struct omap_volt_data **volt_data);
195 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
196 unsigned long volt);
197 int omap_voltage_register_pmic(struct voltagedomain *voltdm,
198 struct omap_voltdm_pmic *pmic);
199 void omap_change_voltscale_method(struct voltagedomain *voltdm,
200 int voltscale_method);
201 int omap_voltage_late_init(void);
202
203 extern void omap2xxx_voltagedomains_init(void);
204 extern void omap3xxx_voltagedomains_init(void);
205 extern void am33xx_voltagedomains_init(void);
206 extern void omap44xx_voltagedomains_init(void);
207
16 struct voltagedomain *voltdm_lookup(const char *name); 208 struct voltagedomain *voltdm_lookup(const char *name);
209 void voltdm_init(struct voltagedomain **voltdm_list);
210 int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm);
211 int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
212 void *user);
213 int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
214 int (*fn)(struct voltagedomain *voltdm,
215 struct powerdomain *pwrdm));
17 int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt); 216 int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
217 void voltdm_reset(struct voltagedomain *voltdm);
18 unsigned long voltdm_get_voltage(struct voltagedomain *voltdm); 218 unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
19
20 #endif 219 #endif
arch/arm/plat-omap/include/plat/vp.h
File was created 1 /*
2 * OMAP3/4 Voltage Processor (VP) structure and macro definitions
3 *
4 * Copyright (C) 2007, 2010 Texas Instruments, Inc.
5 * Rajendra Nayak <rnayak@ti.com>
6 * Lesly A M <x0080970@ti.com>
7 * Thara Gopinath <thara@ti.com>
8 *
9 * Copyright (C) 2008, 2011 Nokia Corporation
10 * Kalle Jokiniemi
11 * Paul Walmsley
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License version
15 * 2 as published by the Free Software Foundation.
16 */
17 #ifndef __ARCH_ARM_MACH_OMAP2_VP_H
18 #define __ARCH_ARM_MACH_OMAP2_VP_H
19
20 #include <linux/kernel.h>
21
22 struct voltagedomain;
23
24 /*
25 * Voltage Processor (VP) identifiers
26 */
27 #define OMAP3_VP_VDD_MPU_ID 0
28 #define OMAP3_VP_VDD_CORE_ID 1
29 #define OMAP4_VP_VDD_CORE_ID 0
30 #define OMAP4_VP_VDD_IVA_ID 1
31 #define OMAP4_VP_VDD_MPU_ID 2
32
33 /* XXX document */
34 #define VP_IDLE_TIMEOUT 200
35 #define VP_TRANXDONE_TIMEOUT 300
36
37 /**
38 * struct omap_vp_ops - per-VP operations
39 * @check_txdone: check for VP transaction done
40 * @clear_txdone: clear VP transaction done status
41 */
42 struct omap_vp_ops {
43 u32 (*check_txdone)(u8 vp_id);
44 void (*clear_txdone)(u8 vp_id);
45 };
46
47 /**
48 * struct omap_vp_common - register data common to all VDDs
49 * @vpconfig_erroroffset_mask: ERROROFFSET bitmask in the PRM_VP*_CONFIG reg
50 * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg
51 * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg
52 * @vpconfig_timeouten: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
53 * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg
54 * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg
55 * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg
56 * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg
57 * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg
58 * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg
59 * @vstepmin_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
60 * @vstepmin_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
61 * @vstepmax_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
62 * @vstepmax_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
63 * @vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
64 * @vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
65 * @vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
66 * @vpvoltage_mask: VPVOLTAGE field mask in PRM_VP*_VOLTAGE reg
67 */
68 struct omap_vp_common {
69 u32 vpconfig_erroroffset_mask;
70 u32 vpconfig_errorgain_mask;
71 u32 vpconfig_initvoltage_mask;
72 u8 vpconfig_timeouten;
73 u8 vpconfig_initvdd;
74 u8 vpconfig_forceupdate;
75 u8 vpconfig_vpenable;
76 u8 vstepmin_stepmin_shift;
77 u8 vstepmin_smpswaittimemin_shift;
78 u8 vstepmax_stepmax_shift;
79 u8 vstepmax_smpswaittimemax_shift;
80 u8 vlimitto_vddmin_shift;
81 u8 vlimitto_vddmax_shift;
82 u8 vlimitto_timeout_shift;
83 u8 vpvoltage_mask;
84
85 const struct omap_vp_ops *ops;
86 };
87
88 /**
89 * struct omap_vp_instance - VP register offsets (per-VDD)
90 * @common: pointer to struct omap_vp_common * for this SoC
91 * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start
92 * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start
93 * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start
94 * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start
95 * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start
96 * @id: Unique identifier for VP instance.
97 * @enabled: flag to keep track of whether vp is enabled or not
98 *
99 * XXX vp_common is probably not needed since it is per-SoC
100 */
101 struct omap_vp_instance {
102 const struct omap_vp_common *common;
103 u8 vpconfig;
104 u8 vstepmin;
105 u8 vstepmax;
106 u8 vlimitto;
107 u8 vstatus;
108 u8 voltage;
109 u8 id;
110 bool enabled;
111 };
112
113 extern struct omap_vp_instance omap3_vp_mpu;
114 extern struct omap_vp_instance omap3_vp_core;
115
116 extern struct omap_vp_instance omap4_vp_mpu;
117 extern struct omap_vp_instance omap4_vp_iva;
118 extern struct omap_vp_instance omap4_vp_core;
119
120 void omap_vp_init(struct voltagedomain *voltdm);
121 void omap_vp_enable(struct voltagedomain *voltdm);
122 void omap_vp_disable(struct voltagedomain *voltdm);
123 int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
124 unsigned long target_volt);
125 int omap_vp_update_errorgain(struct voltagedomain *voltdm,
126 unsigned long target_volt);
127
128 #endif
129
drivers/cpufreq/omap-cpufreq.c
1 /* 1 /*
2 * CPU frequency scaling for OMAP using OPP information 2 * CPU frequency scaling for OMAP using OPP information
3 * 3 *
4 * Copyright (C) 2005 Nokia Corporation 4 * Copyright (C) 2005 Nokia Corporation
5 * Written by Tony Lindgren <tony@atomide.com> 5 * Written by Tony Lindgren <tony@atomide.com>
6 * 6 *
7 * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King 7 * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
8 * 8 *
9 * Copyright (C) 2007-2011 Texas Instruments, Inc. 9 * Copyright (C) 2007-2011 Texas Instruments, Inc.
10 * - OMAP3/4 support by Rajendra Nayak, Santosh Shilimkar 10 * - OMAP3/4 support by Rajendra Nayak, Santosh Shilimkar
11 * 11 *
12 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as 13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation. 14 * published by the Free Software Foundation.
15 */ 15 */
16 #include <linux/types.h> 16 #include <linux/types.h>
17 #include <linux/kernel.h> 17 #include <linux/kernel.h>
18 #include <linux/sched.h> 18 #include <linux/sched.h>
19 #include <linux/cpufreq.h> 19 #include <linux/cpufreq.h>
20 #include <linux/delay.h> 20 #include <linux/delay.h>
21 #include <linux/init.h> 21 #include <linux/init.h>
22 #include <linux/err.h> 22 #include <linux/err.h>
23 #include <linux/clk.h> 23 #include <linux/clk.h>
24 #include <linux/io.h> 24 #include <linux/io.h>
25 #include <linux/opp.h> 25 #include <linux/opp.h>
26 #include <linux/cpu.h> 26 #include <linux/cpu.h>
27 27
28 #include <asm/system.h> 28 #include <asm/system.h>
29 #include <asm/smp_plat.h> 29 #include <asm/smp_plat.h>
30 #include <asm/cpu.h> 30 #include <asm/cpu.h>
31 31
32 #include <plat/clock.h> 32 #include <plat/clock.h>
33 #include <plat/omap-pm.h> 33 #include <plat/omap-pm.h>
34 #include <plat/omap_device.h> 34 #include <plat/omap_device.h>
35 #include <plat/common.h> 35 #include <plat/common.h>
36 #include <plat/dvfs.h>
36 37
37 #include <mach/hardware.h> 38 #include <mach/hardware.h>
38 39
39 #ifdef CONFIG_SMP 40 #ifdef CONFIG_SMP
40 struct lpj_info { 41 struct lpj_info {
41 unsigned long ref; 42 unsigned long ref;
42 unsigned int freq; 43 unsigned int freq;
43 }; 44 };
44 45
45 static DEFINE_PER_CPU(struct lpj_info, lpj_ref); 46 static DEFINE_PER_CPU(struct lpj_info, lpj_ref);
46 static struct lpj_info global_lpj_ref; 47 static struct lpj_info global_lpj_ref;
47 #endif 48 #endif
48 49
49 static struct cpufreq_frequency_table *freq_table; 50 static struct cpufreq_frequency_table *freq_table;
50 static atomic_t freq_table_users = ATOMIC_INIT(0); 51 static atomic_t freq_table_users = ATOMIC_INIT(0);
51 static struct clk *mpu_clk; 52 static struct clk *mpu_clk;
52 static char *mpu_clk_name; 53 static char *mpu_clk_name;
53 static struct device *mpu_dev; 54 static struct device *mpu_dev;
54 55
55 static int omap_verify_speed(struct cpufreq_policy *policy) 56 static int omap_verify_speed(struct cpufreq_policy *policy)
56 { 57 {
57 if (!freq_table) 58 if (!freq_table)
58 return -EINVAL; 59 return -EINVAL;
59 return cpufreq_frequency_table_verify(policy, freq_table); 60 return cpufreq_frequency_table_verify(policy, freq_table);
60 } 61 }
61 62
62 static unsigned int omap_getspeed(unsigned int cpu) 63 static unsigned int omap_getspeed(unsigned int cpu)
63 { 64 {
64 unsigned long rate; 65 unsigned long rate;
65 66
66 if (cpu >= NR_CPUS) 67 if (cpu >= NR_CPUS)
67 return 0; 68 return 0;
68 69
69 rate = clk_get_rate(mpu_clk) / 1000; 70 rate = clk_get_rate(mpu_clk) / 1000;
70 return rate; 71 return rate;
71 } 72 }
72 73
73 static int omap_target(struct cpufreq_policy *policy, 74 static int omap_target(struct cpufreq_policy *policy,
74 unsigned int target_freq, 75 unsigned int target_freq,
75 unsigned int relation) 76 unsigned int relation)
76 { 77 {
77 unsigned int i; 78 unsigned int i;
78 int ret = 0; 79 int ret = 0;
79 struct cpufreq_freqs freqs; 80 struct cpufreq_freqs freqs;
80 81
81 if (!freq_table) { 82 if (!freq_table) {
82 dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__, 83 dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__,
83 policy->cpu); 84 policy->cpu);
84 return -EINVAL; 85 return -EINVAL;
85 } 86 }
86 87
87 ret = cpufreq_frequency_table_target(policy, freq_table, target_freq, 88 ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
88 relation, &i); 89 relation, &i);
89 if (ret) { 90 if (ret) {
90 dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n", 91 dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n",
91 __func__, policy->cpu, target_freq, ret); 92 __func__, policy->cpu, target_freq, ret);
92 return ret; 93 return ret;
93 } 94 }
94 freqs.new = freq_table[i].frequency; 95 freqs.new = freq_table[i].frequency;
95 if (!freqs.new) { 96 if (!freqs.new) {
96 dev_err(mpu_dev, "%s: cpu%d: no match for freq %d\n", __func__, 97 dev_err(mpu_dev, "%s: cpu%d: no match for freq %d\n", __func__,
97 policy->cpu, target_freq); 98 policy->cpu, target_freq);
98 return -EINVAL; 99 return -EINVAL;
99 } 100 }
100 101
101 freqs.old = omap_getspeed(policy->cpu); 102 freqs.old = omap_getspeed(policy->cpu);
102 freqs.cpu = policy->cpu; 103 freqs.cpu = policy->cpu;
103 104
104 if (freqs.old == freqs.new && policy->cur == freqs.new) 105 if (freqs.old == freqs.new && policy->cur == freqs.new)
105 return ret; 106 return ret;
106 107
107 /* notifiers */ 108 /* notifiers */
108 for_each_cpu(i, policy->cpus) { 109 for_each_cpu(i, policy->cpus) {
109 freqs.cpu = i; 110 freqs.cpu = i;
110 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 111 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
111 } 112 }
112 113
113 #ifdef CONFIG_CPU_FREQ_DEBUG 114 #ifdef CONFIG_CPU_FREQ_DEBUG
114 pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); 115 pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
115 #endif 116 #endif
116 117
117 ret = clk_set_rate(mpu_clk, freqs.new * 1000); 118 ret = clk_set_rate(mpu_clk, freqs.new * 1000);
118 freqs.new = omap_getspeed(policy->cpu); 119 freqs.new = omap_getspeed(policy->cpu);
119 120
120 #ifdef CONFIG_SMP 121 #ifdef CONFIG_SMP
121 /* 122 /*
122 * Note that loops_per_jiffy is not updated on SMP systems in 123 * Note that loops_per_jiffy is not updated on SMP systems in
123 * cpufreq driver. So, update the per-CPU loops_per_jiffy value 124 * cpufreq driver. So, update the per-CPU loops_per_jiffy value
124 * on frequency transition. We need to update all dependent CPUs. 125 * on frequency transition. We need to update all dependent CPUs.
125 */ 126 */
126 for_each_cpu(i, policy->cpus) { 127 for_each_cpu(i, policy->cpus) {
127 struct lpj_info *lpj = &per_cpu(lpj_ref, i); 128 struct lpj_info *lpj = &per_cpu(lpj_ref, i);
128 if (!lpj->freq) { 129 if (!lpj->freq) {
129 lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy; 130 lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy;
130 lpj->freq = freqs.old; 131 lpj->freq = freqs.old;
131 } 132 }
132 133
133 per_cpu(cpu_data, i).loops_per_jiffy = 134 per_cpu(cpu_data, i).loops_per_jiffy =
134 cpufreq_scale(lpj->ref, lpj->freq, freqs.new); 135 cpufreq_scale(lpj->ref, lpj->freq, freqs.new);
135 } 136 }
136 137
137 /* And don't forget to adjust the global one */ 138 /* And don't forget to adjust the global one */
138 if (!global_lpj_ref.freq) { 139 if (!global_lpj_ref.freq) {
139 global_lpj_ref.ref = loops_per_jiffy; 140 global_lpj_ref.ref = loops_per_jiffy;
140 global_lpj_ref.freq = freqs.old; 141 global_lpj_ref.freq = freqs.old;
141 } 142 }
142 loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq, 143 loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq,
143 freqs.new); 144 freqs.new);
144 #endif 145 #endif
145 146
146 /* notifiers */ 147 /* notifiers */
147 for_each_cpu(i, policy->cpus) { 148 for_each_cpu(i, policy->cpus) {
148 freqs.cpu = i; 149 freqs.cpu = i;
149 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 150 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
150 } 151 }
151 152
152 return ret; 153 return ret;
153 } 154 }
154 155
155 static inline void freq_table_free(void) 156 static inline void freq_table_free(void)
156 { 157 {
157 if (atomic_dec_and_test(&freq_table_users)) 158 if (atomic_dec_and_test(&freq_table_users))
158 opp_free_cpufreq_table(mpu_dev, &freq_table); 159 opp_free_cpufreq_table(mpu_dev, &freq_table);
159 } 160 }
160 161
161 static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) 162 static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
162 { 163 {
163 int result = 0; 164 int result = 0;
164 165
165 mpu_clk = clk_get(NULL, mpu_clk_name); 166 mpu_clk = clk_get(NULL, mpu_clk_name);
166 if (IS_ERR(mpu_clk)) 167 if (IS_ERR(mpu_clk))
167 return PTR_ERR(mpu_clk); 168 return PTR_ERR(mpu_clk);
168 169
169 if (policy->cpu >= NR_CPUS) { 170 if (policy->cpu >= NR_CPUS) {
170 result = -EINVAL; 171 result = -EINVAL;
171 goto fail_ck; 172 goto fail_ck;
172 } 173 }
173 174
174 policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); 175 policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
175 176
176 if (atomic_inc_return(&freq_table_users) == 1) 177 if (atomic_inc_return(&freq_table_users) == 1)
177 result = opp_init_cpufreq_table(mpu_dev, &freq_table); 178 result = opp_init_cpufreq_table(mpu_dev, &freq_table);
178 179
179 if (result) { 180 if (result) {
180 dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n", 181 dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
181 __func__, policy->cpu, result); 182 __func__, policy->cpu, result);
182 goto fail_ck; 183 goto fail_ck;
183 } 184 }
184 185
185 result = cpufreq_frequency_table_cpuinfo(policy, freq_table); 186 result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
186 if (result) 187 if (result)
187 goto fail_table; 188 goto fail_table;
188 189
189 cpufreq_frequency_table_get_attr(freq_table, policy->cpu); 190 cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
190 191
191 policy->min = policy->cpuinfo.min_freq; 192 policy->min = policy->cpuinfo.min_freq;
192 policy->max = policy->cpuinfo.max_freq; 193 policy->max = policy->cpuinfo.max_freq;
193 policy->cur = omap_getspeed(policy->cpu); 194 policy->cur = omap_getspeed(policy->cpu);
194 195
195 /* 196 /*
196 * On OMAP SMP configuartion, both processors share the voltage 197 * On OMAP SMP configuartion, both processors share the voltage
197 * and clock. So both CPUs needs to be scaled together and hence 198 * and clock. So both CPUs needs to be scaled together and hence
198 * needs software co-ordination. Use cpufreq affected_cpus 199 * needs software co-ordination. Use cpufreq affected_cpus
199 * interface to handle this scenario. Additional is_smp() check 200 * interface to handle this scenario. Additional is_smp() check
200 * is to keep SMP_ON_UP build working. 201 * is to keep SMP_ON_UP build working.
201 */ 202 */
202 if (is_smp()) { 203 if (is_smp()) {
203 policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; 204 policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
204 cpumask_setall(policy->cpus); 205 cpumask_setall(policy->cpus);
205 } 206 }
206 207
207 /* FIXME: what's the actual transition time? */ 208 /* FIXME: what's the actual transition time? */
208 policy->cpuinfo.transition_latency = 300 * 1000; 209 policy->cpuinfo.transition_latency = 300 * 1000;
209 210
210 return 0; 211 return 0;
211 212
212 fail_table: 213 fail_table:
213 freq_table_free(); 214 freq_table_free();
214 fail_ck: 215 fail_ck:
215 clk_put(mpu_clk); 216 clk_put(mpu_clk);
216 return result; 217 return result;
217 } 218 }
218 219
219 static int omap_cpu_exit(struct cpufreq_policy *policy) 220 static int omap_cpu_exit(struct cpufreq_policy *policy)
220 { 221 {
221 freq_table_free(); 222 freq_table_free();
222 clk_put(mpu_clk); 223 clk_put(mpu_clk);
223 return 0; 224 return 0;
224 } 225 }
225 226
226 static struct freq_attr *omap_cpufreq_attr[] = { 227 static struct freq_attr *omap_cpufreq_attr[] = {
227 &cpufreq_freq_attr_scaling_available_freqs, 228 &cpufreq_freq_attr_scaling_available_freqs,
228 NULL, 229 NULL,
229 }; 230 };
230 231
231 static struct cpufreq_driver omap_driver = { 232 static struct cpufreq_driver omap_driver = {
232 .flags = CPUFREQ_STICKY, 233 .flags = CPUFREQ_STICKY,
233 .verify = omap_verify_speed, 234 .verify = omap_verify_speed,
234 .target = omap_target, 235 .target = omap_target,
235 .get = omap_getspeed, 236 .get = omap_getspeed,
236 .init = omap_cpu_init, 237 .init = omap_cpu_init,
237 .exit = omap_cpu_exit, 238 .exit = omap_cpu_exit,
238 .name = "omap", 239 .name = "omap",
239 .attr = omap_cpufreq_attr, 240 .attr = omap_cpufreq_attr,
240 }; 241 };
241 242
242 static int __init omap_cpufreq_init(void) 243 static int __init omap_cpufreq_init(void)
243 { 244 {
244 if (cpu_is_omap24xx()) 245 if (cpu_is_omap24xx())
245 mpu_clk_name = "virt_prcm_set"; 246 mpu_clk_name = "virt_prcm_set";
246 else if (cpu_is_omap34xx()) 247 else if (cpu_is_omap34xx())
247 mpu_clk_name = "dpll1_ck"; 248 mpu_clk_name = "dpll1_ck";
248 else if (cpu_is_omap44xx()) 249 else if (cpu_is_omap44xx())
249 mpu_clk_name = "dpll_mpu_ck"; 250 mpu_clk_name = "dpll_mpu_ck";
250 251
251 if (!mpu_clk_name) { 252 if (!mpu_clk_name) {
252 pr_err("%s: unsupported Silicon?\n", __func__); 253 pr_err("%s: unsupported Silicon?\n", __func__);
253 return -EINVAL; 254 return -EINVAL;
254 } 255 }
255 256
256 mpu_dev = omap_device_get_by_hwmod_name("mpu"); 257 mpu_dev = omap_device_get_by_hwmod_name("mpu");
257 if (!mpu_dev) { 258 if (!mpu_dev) {
258 pr_warning("%s: unable to get the mpu device\n", __func__); 259 pr_warning("%s: unable to get the mpu device\n", __func__);
259 return -EINVAL; 260 return -EINVAL;
260 } 261 }
261 262
262 return cpufreq_register_driver(&omap_driver); 263 return cpufreq_register_driver(&omap_driver);
263 } 264 }
264 265
265 static void __exit omap_cpufreq_exit(void) 266 static void __exit omap_cpufreq_exit(void)
266 { 267 {
267 cpufreq_unregister_driver(&omap_driver); 268 cpufreq_unregister_driver(&omap_driver);
268 } 269 }
269 270
270 MODULE_DESCRIPTION("cpufreq driver for OMAP SoCs"); 271 MODULE_DESCRIPTION("cpufreq driver for OMAP SoCs");
271 MODULE_LICENSE("GPL"); 272 MODULE_LICENSE("GPL");
272 module_init(omap_cpufreq_init); 273 module_init(omap_cpufreq_init);
273 module_exit(omap_cpufreq_exit); 274 module_exit(omap_cpufreq_exit);
274 275