blob: f663695b7c617e7dba7d4e666a351989e722c1ab [file] [log] [blame]
David Collins6f032ba2011-08-31 14:08:15 -07001/*
David Collins5779cea2012-01-05 15:09:21 -08002 * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
David Collins6f032ba2011-08-31 14:08:15 -070014#define pr_fmt(fmt) "%s: " fmt, __func__
15
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070016#include <linux/module.h>
17#include <linux/err.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
David Collins6f032ba2011-08-31 14:08:15 -070020#include <linux/slab.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021#include <linux/spinlock.h>
David Collins379b4b72012-05-14 16:33:51 -070022#include <linux/string.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070023#include <linux/platform_device.h>
24#include <linux/regulator/driver.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070025#include <mach/rpm.h>
26#include <mach/rpm-regulator.h>
David Collins379b4b72012-05-14 16:33:51 -070027#include <mach/rpm-regulator-smd.h>
David Collins6f032ba2011-08-31 14:08:15 -070028#include <mach/socinfo.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070029
30#include "rpm_resources.h"
David Collins6f032ba2011-08-31 14:08:15 -070031#include "rpm-regulator-private.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070032
33/* Debug Definitions */
34
35enum {
36 MSM_RPM_VREG_DEBUG_REQUEST = BIT(0),
37 MSM_RPM_VREG_DEBUG_VOTE = BIT(1),
38 MSM_RPM_VREG_DEBUG_DUPLICATE = BIT(2),
David Collins6f032ba2011-08-31 14:08:15 -070039 MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG = BIT(3),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040};
41
42static int msm_rpm_vreg_debug_mask;
43module_param_named(
44 debug_mask, msm_rpm_vreg_debug_mask, int, S_IRUSR | S_IWUSR
45);
46
David Collins379b4b72012-05-14 16:33:51 -070047/* Used for access via the rpm_regulator_* API. */
48struct rpm_regulator {
49 int vreg_id;
50 enum rpm_vreg_voter voter;
51 int sleep_also;
52 int min_uV;
53 int max_uV;
54};
55
David Collins6f032ba2011-08-31 14:08:15 -070056struct vreg_config *(*get_config[])(void) = {
57 [RPM_VREG_VERSION_8660] = get_config_8660,
58 [RPM_VREG_VERSION_8960] = get_config_8960,
David Collins6ef12bf2011-08-31 14:08:15 -070059 [RPM_VREG_VERSION_9615] = get_config_9615,
David Collins5779cea2012-01-05 15:09:21 -080060 [RPM_VREG_VERSION_8930] = get_config_8930,
David Collins6f032ba2011-08-31 14:08:15 -070061};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070062
David Collins379b4b72012-05-14 16:33:51 -070063static struct rpm_regulator_consumer_mapping *consumer_map;
64static int consumer_map_len;
65
David Collins6f032ba2011-08-31 14:08:15 -070066#define SET_PART(_vreg, _part, _val) \
67 _vreg->req[_vreg->part->_part.word].value \
68 = (_vreg->req[_vreg->part->_part.word].value \
David Collinsd8525e82011-11-21 14:54:25 -080069 & ~_vreg->part->_part.mask) \
70 | (((_val) << _vreg->part->_part.shift) \
71 & _vreg->part->_part.mask)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070072
David Collins6f032ba2011-08-31 14:08:15 -070073#define GET_PART(_vreg, _part) \
David Collinsd8525e82011-11-21 14:54:25 -080074 ((_vreg->req[_vreg->part->_part.word].value & _vreg->part->_part.mask) \
75 >> _vreg->part->_part.shift)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070076
David Collinsd8525e82011-11-21 14:54:25 -080077#define USES_PART(_vreg, _part) (_vreg->part->_part.mask)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070078
David Collins6f032ba2011-08-31 14:08:15 -070079#define vreg_err(vreg, fmt, ...) \
80 pr_err("%s: " fmt, vreg->rdesc.name, ##__VA_ARGS__)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070081
David Collins6f032ba2011-08-31 14:08:15 -070082#define RPM_VREG_PIN_CTRL_EN0 0x01
83#define RPM_VREG_PIN_CTRL_EN1 0x02
84#define RPM_VREG_PIN_CTRL_EN2 0x04
85#define RPM_VREG_PIN_CTRL_EN3 0x08
86#define RPM_VREG_PIN_CTRL_ALL 0x0F
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070087
David Collins6f032ba2011-08-31 14:08:15 -070088static const char *label_freq[] = {
89 [RPM_VREG_FREQ_NONE] = " N/A",
90 [RPM_VREG_FREQ_19p20] = "19.2",
91 [RPM_VREG_FREQ_9p60] = "9.60",
92 [RPM_VREG_FREQ_6p40] = "6.40",
93 [RPM_VREG_FREQ_4p80] = "4.80",
94 [RPM_VREG_FREQ_3p84] = "3.84",
95 [RPM_VREG_FREQ_3p20] = "3.20",
96 [RPM_VREG_FREQ_2p74] = "2.74",
97 [RPM_VREG_FREQ_2p40] = "2.40",
98 [RPM_VREG_FREQ_2p13] = "2.13",
99 [RPM_VREG_FREQ_1p92] = "1.92",
100 [RPM_VREG_FREQ_1p75] = "1.75",
101 [RPM_VREG_FREQ_1p60] = "1.60",
102 [RPM_VREG_FREQ_1p48] = "1.48",
103 [RPM_VREG_FREQ_1p37] = "1.37",
104 [RPM_VREG_FREQ_1p28] = "1.28",
105 [RPM_VREG_FREQ_1p20] = "1.20",
106};
David Collins0ac31fe2012-02-08 13:53:34 -0800107
108static const char *label_corner[] = {
109 [RPM_VREG_CORNER_NONE] = "NONE",
110 [RPM_VREG_CORNER_LOW] = "LOW",
111 [RPM_VREG_CORNER_NOMINAL] = "NOM",
112 [RPM_VREG_CORNER_HIGH] = "HIGH",
113};
114
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700115/*
116 * This is used when voting for LPM or HPM by subtracting or adding to the
117 * hpm_min_load of a regulator. It has units of uA.
118 */
David Collins6f032ba2011-08-31 14:08:15 -0700119#define LOAD_THRESHOLD_STEP 1000
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700120
David Collins6f032ba2011-08-31 14:08:15 -0700121/* rpm_version keeps track of the version for the currently running driver. */
122enum rpm_vreg_version rpm_version = -1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700123
David Collins6f032ba2011-08-31 14:08:15 -0700124/* config holds all configuration data of the currently running driver. */
125static struct vreg_config *config;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700126
David Collins6f032ba2011-08-31 14:08:15 -0700127/* These regulator ID values are specified in the board file. */
128static int vreg_id_vdd_mem, vreg_id_vdd_dig;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700129
David Collins6f032ba2011-08-31 14:08:15 -0700130static inline int vreg_id_is_vdd_mem_or_dig(int id)
131{
132 return id == vreg_id_vdd_mem || id == vreg_id_vdd_dig;
133}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700134
David Collins6f032ba2011-08-31 14:08:15 -0700135#define DEBUG_PRINT_BUFFER_SIZE 512
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700136
David Collins6f032ba2011-08-31 14:08:15 -0700137static void rpm_regulator_req(struct vreg *vreg, int set)
138{
139 int uV, mV, fm, pm, pc, pf, pd, freq, state, i;
140 const char *pf_label = "", *fm_label = "", *pc_total = "";
141 const char *pc_en[4] = {"", "", "", ""};
David Collins0ac31fe2012-02-08 13:53:34 -0800142 const char *pm_label = "", *freq_label = "", *corner_label = "";
David Collins6f032ba2011-08-31 14:08:15 -0700143 char buf[DEBUG_PRINT_BUFFER_SIZE];
144 size_t buflen = DEBUG_PRINT_BUFFER_SIZE;
145 int pos = 0;
146
147 /* Suppress VDD_MEM and VDD_DIG printing. */
148 if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG)
149 && vreg_id_is_vdd_mem_or_dig(vreg->id))
150 return;
151
152 uV = GET_PART(vreg, uV);
153 mV = GET_PART(vreg, mV);
154 if (vreg->type == RPM_REGULATOR_TYPE_NCP) {
155 uV = -uV;
156 mV = -mV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700157 }
158
David Collins6f032ba2011-08-31 14:08:15 -0700159 fm = GET_PART(vreg, fm);
160 pm = GET_PART(vreg, pm);
161 pc = GET_PART(vreg, pc);
162 pf = GET_PART(vreg, pf);
163 pd = GET_PART(vreg, pd);
164 freq = GET_PART(vreg, freq);
165 state = GET_PART(vreg, enable_state);
166
167 if (pf >= 0 && pf < config->label_pin_func_len)
168 pf_label = config->label_pin_func[pf];
169
170 if (fm >= 0 && fm < config->label_force_mode_len)
171 fm_label = config->label_force_mode[fm];
172
173 if (pm >= 0 && pm < config->label_power_mode_len)
174 pm_label = config->label_power_mode[pm];
175
176 if (freq >= 0 && freq < ARRAY_SIZE(label_freq))
177 freq_label = label_freq[freq];
178
179 for (i = 0; i < config->label_pin_ctrl_len; i++)
180 if (pc & (1 << i))
181 pc_en[i] = config->label_pin_ctrl[i];
182
183 if (pc == RPM_VREG_PIN_CTRL_NONE)
184 pc_total = " none";
185
186 pos += scnprintf(buf + pos, buflen - pos, "%s%s: ",
187 KERN_INFO, __func__);
188
189 pos += scnprintf(buf + pos, buflen - pos, "%s %-9s: s=%c",
190 (set == MSM_RPM_CTX_SET_0 ? "sending " : "buffered"),
191 vreg->rdesc.name,
192 (set == MSM_RPM_CTX_SET_0 ? 'A' : 'S'));
193
David Collins0ac31fe2012-02-08 13:53:34 -0800194 if (USES_PART(vreg, uV) && vreg->type != RPM_REGULATOR_TYPE_CORNER)
David Collins6f032ba2011-08-31 14:08:15 -0700195 pos += scnprintf(buf + pos, buflen - pos, ", v=%7d uV", uV);
196 if (USES_PART(vreg, mV))
197 pos += scnprintf(buf + pos, buflen - pos, ", v=%4d mV", mV);
198 if (USES_PART(vreg, enable_state))
199 pos += scnprintf(buf + pos, buflen - pos, ", state=%s (%d)",
200 (state == 1 ? "on" : "off"), state);
201 if (USES_PART(vreg, ip))
202 pos += scnprintf(buf + pos, buflen - pos,
203 ", ip=%4d mA", GET_PART(vreg, ip));
204 if (USES_PART(vreg, fm))
205 pos += scnprintf(buf + pos, buflen - pos,
206 ", fm=%s (%d)", fm_label, fm);
207 if (USES_PART(vreg, pc))
208 pos += scnprintf(buf + pos, buflen - pos,
209 ", pc=%s%s%s%s%s (%X)", pc_en[0], pc_en[1],
210 pc_en[2], pc_en[3], pc_total, pc);
211 if (USES_PART(vreg, pf))
212 pos += scnprintf(buf + pos, buflen - pos,
213 ", pf=%s (%d)", pf_label, pf);
214 if (USES_PART(vreg, pd))
215 pos += scnprintf(buf + pos, buflen - pos,
216 ", pd=%s (%d)", (pd == 1 ? "Y" : "N"), pd);
217 if (USES_PART(vreg, ia))
218 pos += scnprintf(buf + pos, buflen - pos,
219 ", ia=%4d mA", GET_PART(vreg, ia));
220 if (USES_PART(vreg, freq)) {
221 if (vreg->type == RPM_REGULATOR_TYPE_NCP)
222 pos += scnprintf(buf + pos, buflen - pos,
223 ", freq=%2d", freq);
224 else
225 pos += scnprintf(buf + pos, buflen - pos,
226 ", freq=%s MHz (%2d)", freq_label, freq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227 }
David Collins6f032ba2011-08-31 14:08:15 -0700228 if (USES_PART(vreg, pm))
229 pos += scnprintf(buf + pos, buflen - pos,
230 ", pm=%s (%d)", pm_label, pm);
231 if (USES_PART(vreg, freq_clk_src))
232 pos += scnprintf(buf + pos, buflen - pos,
233 ", clk_src=%d", GET_PART(vreg, freq_clk_src));
234 if (USES_PART(vreg, comp_mode))
235 pos += scnprintf(buf + pos, buflen - pos,
236 ", comp=%d", GET_PART(vreg, comp_mode));
237 if (USES_PART(vreg, hpm))
238 pos += scnprintf(buf + pos, buflen - pos,
239 ", hpm=%d", GET_PART(vreg, hpm));
David Collins0ac31fe2012-02-08 13:53:34 -0800240 if (USES_PART(vreg, uV) && vreg->type == RPM_REGULATOR_TYPE_CORNER) {
241 if (uV >= 0 && uV < (ARRAY_SIZE(label_corner) - 1))
242 corner_label = label_corner[uV+1];
243 pos += scnprintf(buf + pos, buflen - pos, ", corner=%s (%d)",
244 corner_label, uV);
245 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700246
David Collins6f032ba2011-08-31 14:08:15 -0700247 pos += scnprintf(buf + pos, buflen - pos, "; req[0]={%d, 0x%08X}",
248 vreg->req[0].id, vreg->req[0].value);
249 if (vreg->part->request_len > 1)
250 pos += scnprintf(buf + pos, buflen - pos,
251 ", req[1]={%d, 0x%08X}", vreg->req[1].id,
252 vreg->req[1].value);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700253
David Collins6f032ba2011-08-31 14:08:15 -0700254 pos += scnprintf(buf + pos, buflen - pos, "\n");
255 printk(buf);
256}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700257
David Collins6f032ba2011-08-31 14:08:15 -0700258static void rpm_regulator_vote(struct vreg *vreg, enum rpm_vreg_voter voter,
259 int set, int voter_uV, int aggregate_uV)
260{
261 /* Suppress VDD_MEM and VDD_DIG printing. */
262 if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG)
263 && vreg_id_is_vdd_mem_or_dig(vreg->id))
264 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700265
David Collins6f032ba2011-08-31 14:08:15 -0700266 pr_info("vote received %-9s: voter=%d, set=%c, v_voter=%7d uV, "
267 "v_aggregate=%7d uV\n", vreg->rdesc.name, voter,
268 (set == 0 ? 'A' : 'S'), voter_uV, aggregate_uV);
269}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270
David Collins6f032ba2011-08-31 14:08:15 -0700271static void rpm_regulator_duplicate(struct vreg *vreg, int set, int cnt)
272{
273 /* Suppress VDD_MEM and VDD_DIG printing. */
274 if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG)
275 && vreg_id_is_vdd_mem_or_dig(vreg->id))
276 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700277
David Collins6f032ba2011-08-31 14:08:15 -0700278 if (cnt == 2)
279 pr_info("ignored request %-9s: set=%c; req[0]={%d, 0x%08X}, "
280 "req[1]={%d, 0x%08X}\n", vreg->rdesc.name,
281 (set == 0 ? 'A' : 'S'),
282 vreg->req[0].id, vreg->req[0].value,
283 vreg->req[1].id, vreg->req[1].value);
284 else if (cnt == 1)
285 pr_info("ignored request %-9s: set=%c; req[0]={%d, 0x%08X}\n",
286 vreg->rdesc.name, (set == 0 ? 'A' : 'S'),
287 vreg->req[0].id, vreg->req[0].value);
288}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700289
290/* Spin lock needed for sleep-selectable regulators. */
David Collins6f032ba2011-08-31 14:08:15 -0700291static DEFINE_SPINLOCK(rpm_noirq_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700292
293static int voltage_from_req(struct vreg *vreg)
294{
David Collins6f032ba2011-08-31 14:08:15 -0700295 int uV = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700296
David Collins6f032ba2011-08-31 14:08:15 -0700297 if (vreg->part->uV.mask)
298 uV = GET_PART(vreg, uV);
David Collins13397f22012-02-06 13:53:29 -0800299 else if (vreg->part->mV.mask)
David Collins6f032ba2011-08-31 14:08:15 -0700300 uV = MILLI_TO_MICRO(GET_PART(vreg, mV));
David Collins13397f22012-02-06 13:53:29 -0800301 else if (vreg->part->enable_state.mask)
302 uV = GET_PART(vreg, enable_state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700303
David Collins6f032ba2011-08-31 14:08:15 -0700304 return uV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700305}
306
David Collins6f032ba2011-08-31 14:08:15 -0700307static void voltage_to_req(int uV, struct vreg *vreg)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308{
David Collins6f032ba2011-08-31 14:08:15 -0700309 if (vreg->part->uV.mask)
310 SET_PART(vreg, uV, uV);
David Collins13397f22012-02-06 13:53:29 -0800311 else if (vreg->part->mV.mask)
David Collins6f032ba2011-08-31 14:08:15 -0700312 SET_PART(vreg, mV, MICRO_TO_MILLI(uV));
David Collins13397f22012-02-06 13:53:29 -0800313 else if (vreg->part->enable_state.mask)
314 SET_PART(vreg, enable_state, uV);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700315}
316
317static int vreg_send_request(struct vreg *vreg, enum rpm_vreg_voter voter,
318 int set, unsigned mask0, unsigned val0,
319 unsigned mask1, unsigned val1, unsigned cnt,
320 int update_voltage)
321{
322 struct msm_rpm_iv_pair *prev_req;
David Collins6f032ba2011-08-31 14:08:15 -0700323 int rc = 0, max_uV_vote = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700324 unsigned prev0, prev1;
David Collins6f032ba2011-08-31 14:08:15 -0700325 int *min_uV_vote;
326 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700327
328 if (set == MSM_RPM_CTX_SET_0) {
David Collins6f032ba2011-08-31 14:08:15 -0700329 min_uV_vote = vreg->active_min_uV_vote;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700330 prev_req = vreg->prev_active_req;
331 } else {
David Collins6f032ba2011-08-31 14:08:15 -0700332 min_uV_vote = vreg->sleep_min_uV_vote;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700333 prev_req = vreg->prev_sleep_req;
334 }
335
336 prev0 = vreg->req[0].value;
337 vreg->req[0].value &= ~mask0;
338 vreg->req[0].value |= val0 & mask0;
339
340 prev1 = vreg->req[1].value;
341 vreg->req[1].value &= ~mask1;
342 vreg->req[1].value |= val1 & mask1;
343
David Collinsd1b7aea2012-03-19 10:27:55 -0700344 /* Set the force mode field based on which set is being requested. */
345 if (set == MSM_RPM_CTX_SET_0)
346 SET_PART(vreg, fm, vreg->pdata.force_mode);
347 else
348 SET_PART(vreg, fm, vreg->pdata.sleep_set_force_mode);
349
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700350 if (update_voltage)
David Collins6f032ba2011-08-31 14:08:15 -0700351 min_uV_vote[voter] = voltage_from_req(vreg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700352
353 /* Find the highest voltage voted for and use it. */
354 for (i = 0; i < RPM_VREG_VOTER_COUNT; i++)
David Collins6f032ba2011-08-31 14:08:15 -0700355 max_uV_vote = max(max_uV_vote, min_uV_vote[i]);
356 voltage_to_req(max_uV_vote, vreg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700357
358 if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_VOTE)
David Collins6f032ba2011-08-31 14:08:15 -0700359 rpm_regulator_vote(vreg, voter, set, min_uV_vote[voter],
360 max_uV_vote);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700361
362 /* Ignore duplicate requests */
363 if (vreg->req[0].value != prev_req[0].value ||
364 vreg->req[1].value != prev_req[1].value) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700365 rc = msm_rpmrs_set_noirq(set, vreg->req, cnt);
366 if (rc) {
367 vreg->req[0].value = prev0;
368 vreg->req[1].value = prev1;
369
David Collins6f032ba2011-08-31 14:08:15 -0700370 vreg_err(vreg, "msm_rpmrs_set_noirq failed - "
371 "set=%s, id=%d, rc=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700372 (set == MSM_RPM_CTX_SET_0 ? "active" : "sleep"),
373 vreg->req[0].id, rc);
374 } else {
375 /* Only save if nonzero and active set. */
David Collins6f032ba2011-08-31 14:08:15 -0700376 if (max_uV_vote && (set == MSM_RPM_CTX_SET_0))
377 vreg->save_uV = max_uV_vote;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700378 if (msm_rpm_vreg_debug_mask
379 & MSM_RPM_VREG_DEBUG_REQUEST)
David Collins6f032ba2011-08-31 14:08:15 -0700380 rpm_regulator_req(vreg, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700381 prev_req[0].value = vreg->req[0].value;
382 prev_req[1].value = vreg->req[1].value;
383 }
384 } else if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_DUPLICATE) {
David Collins6f032ba2011-08-31 14:08:15 -0700385 rpm_regulator_duplicate(vreg, set, cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700386 }
387
388 return rc;
389}
390
391static int vreg_set_noirq(struct vreg *vreg, enum rpm_vreg_voter voter,
392 int sleep, unsigned mask0, unsigned val0,
393 unsigned mask1, unsigned val1, unsigned cnt,
394 int update_voltage)
395{
David Collins6f032ba2011-08-31 14:08:15 -0700396 unsigned int s_mask[2] = {mask0, mask1}, s_val[2] = {val0, val1};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700397 unsigned long flags;
398 int rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700399
400 if (voter < 0 || voter >= RPM_VREG_VOTER_COUNT)
401 return -EINVAL;
402
David Collins6f032ba2011-08-31 14:08:15 -0700403 spin_lock_irqsave(&rpm_noirq_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404
405 /*
406 * Send sleep set request first so that subsequent set_mode, etc calls
407 * use the voltage from the active set.
408 */
409 if (sleep)
410 rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_SLEEP,
411 mask0, val0, mask1, val1, cnt, update_voltage);
412 else {
413 /*
414 * Vote for 0 V in the sleep set when active set-only is
415 * specified. This ensures that a disable vote will be issued
416 * at some point for the sleep set of the regulator.
417 */
David Collins6f032ba2011-08-31 14:08:15 -0700418 if (vreg->part->uV.mask) {
419 s_val[vreg->part->uV.word] = 0 << vreg->part->uV.shift;
420 s_mask[vreg->part->uV.word] = vreg->part->uV.mask;
David Collins13397f22012-02-06 13:53:29 -0800421 } else if (vreg->part->mV.mask) {
David Collins6f032ba2011-08-31 14:08:15 -0700422 s_val[vreg->part->mV.word] = 0 << vreg->part->mV.shift;
423 s_mask[vreg->part->mV.word] = vreg->part->mV.mask;
David Collins13397f22012-02-06 13:53:29 -0800424 } else if (vreg->part->enable_state.mask) {
425 s_val[vreg->part->enable_state.word]
426 = 0 << vreg->part->enable_state.shift;
427 s_mask[vreg->part->enable_state.word]
428 = vreg->part->enable_state.mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700429 }
430
431 rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_SLEEP,
David Collins6f032ba2011-08-31 14:08:15 -0700432 s_mask[0], s_val[0], s_mask[1], s_val[1],
433 cnt, update_voltage);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700434 }
435
436 rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_0, mask0, val0,
437 mask1, val1, cnt, update_voltage);
438
David Collins6f032ba2011-08-31 14:08:15 -0700439 spin_unlock_irqrestore(&rpm_noirq_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700440
441 return rc;
442}
443
444/**
445 * rpm_vreg_set_voltage - vote for a min_uV value of specified regualtor
446 * @vreg: ID for regulator
447 * @voter: ID for the voter
448 * @min_uV: minimum acceptable voltage (in uV) that is voted for
449 * @max_uV: maximum acceptable voltage (in uV) that is voted for
450 * @sleep_also: 0 for active set only, non-0 for active set and sleep set
451 *
452 * Returns 0 on success or errno.
453 *
454 * This function is used to vote for the voltage of a regulator without
455 * using the regulator framework. It is needed by consumers which hold spin
456 * locks or have interrupts disabled because the regulator framework can sleep.
457 * It is also needed by consumers which wish to only vote for active set
458 * regulator voltage.
459 *
460 * If sleep_also == 0, then a sleep-set value of 0V will be voted for.
461 *
462 * This function may only be called for regulators which have the sleep flag
463 * specified in their private data.
David Collins7462b9d2011-10-11 16:02:17 -0700464 *
465 * Consumers can vote to disable a regulator with this function by passing
466 * min_uV = 0 and max_uV = 0.
David Collins13397f22012-02-06 13:53:29 -0800467 *
468 * Voltage switch type regulators may be controlled via rpm_vreg_set_voltage
469 * as well. For this type of regulator, max_uV > 0 is treated as an enable
470 * request and max_uV == 0 is treated as a disable request.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700471 */
David Collins6f032ba2011-08-31 14:08:15 -0700472int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
473 int max_uV, int sleep_also)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700474{
David Collins6f032ba2011-08-31 14:08:15 -0700475 unsigned int mask[2] = {0}, val[2] = {0};
476 struct vreg_range *range;
477 struct vreg *vreg;
478 int uV = min_uV;
479 int lim_min_uV, lim_max_uV, i, rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700480
David Collins6f032ba2011-08-31 14:08:15 -0700481 if (!config) {
482 pr_err("rpm-regulator driver has not probed yet.\n");
483 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700484 }
485
David Collins6f032ba2011-08-31 14:08:15 -0700486 if (vreg_id < config->vreg_id_min || vreg_id > config->vreg_id_max) {
487 pr_err("invalid regulator id=%d\n", vreg_id);
488 return -EINVAL;
489 }
490
491 vreg = &config->vregs[vreg_id];
David Collins6f032ba2011-08-31 14:08:15 -0700492
493 if (!vreg->pdata.sleep_selectable) {
494 vreg_err(vreg, "regulator is not marked sleep selectable\n");
495 return -EINVAL;
496 }
497
David Collins7462b9d2011-10-11 16:02:17 -0700498 /* Allow min_uV == max_uV == 0 to represent a disable request. */
David Collins13397f22012-02-06 13:53:29 -0800499 if ((min_uV != 0 || max_uV != 0)
500 && (vreg->part->uV.mask || vreg->part->mV.mask)) {
David Collins7462b9d2011-10-11 16:02:17 -0700501 /*
502 * Check if request voltage is outside of allowed range. The
503 * regulator core has already checked that constraint range
504 * is inside of the physically allowed range.
505 */
506 lim_min_uV = vreg->pdata.init_data.constraints.min_uV;
507 lim_max_uV = vreg->pdata.init_data.constraints.max_uV;
David Collins6f032ba2011-08-31 14:08:15 -0700508
David Collins7462b9d2011-10-11 16:02:17 -0700509 if (uV < lim_min_uV && max_uV >= lim_min_uV)
510 uV = lim_min_uV;
David Collins6f032ba2011-08-31 14:08:15 -0700511
David Collins7462b9d2011-10-11 16:02:17 -0700512 if (uV < lim_min_uV || uV > lim_max_uV) {
513 vreg_err(vreg, "request v=[%d, %d] is outside allowed "
514 "v=[%d, %d]\n", min_uV, max_uV, lim_min_uV,
515 lim_max_uV);
516 return -EINVAL;
David Collins6f032ba2011-08-31 14:08:15 -0700517 }
David Collins6f032ba2011-08-31 14:08:15 -0700518
David Collins13397f22012-02-06 13:53:29 -0800519 range = &vreg->set_points->range[0];
David Collins7462b9d2011-10-11 16:02:17 -0700520 /* Find the range which uV is inside of. */
521 for (i = vreg->set_points->count - 1; i > 0; i--) {
522 if (uV > vreg->set_points->range[i - 1].max_uV) {
523 range = &vreg->set_points->range[i];
524 break;
525 }
526 }
527
528 /*
529 * Force uV to be an allowed set point and apply a ceiling
530 * function to non-set point values.
531 */
532 uV = (uV - range->min_uV + range->step_uV - 1) / range->step_uV;
533 uV = uV * range->step_uV + range->min_uV;
David Collins3974b612011-11-21 15:07:36 -0800534
535 if (uV > max_uV) {
536 vreg_err(vreg,
537 "request v=[%d, %d] cannot be met by any set point; "
538 "next set point: %d\n",
539 min_uV, max_uV, uV);
540 return -EINVAL;
541 }
David Collins7462b9d2011-10-11 16:02:17 -0700542 }
David Collins6f032ba2011-08-31 14:08:15 -0700543
David Collins0ac31fe2012-02-08 13:53:34 -0800544 if (vreg->type == RPM_REGULATOR_TYPE_CORNER) {
545 /*
546 * Translate from enum values which work as inputs in the
547 * rpm_vreg_set_voltage function to the actual corner values
548 * sent to the RPM.
549 */
550 if (uV > 0)
551 uV -= RPM_VREG_CORNER_NONE;
552 }
553
David Collins6f032ba2011-08-31 14:08:15 -0700554 if (vreg->part->uV.mask) {
555 val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
556 mask[vreg->part->uV.word] = vreg->part->uV.mask;
David Collins13397f22012-02-06 13:53:29 -0800557 } else if (vreg->part->mV.mask) {
David Collins6f032ba2011-08-31 14:08:15 -0700558 val[vreg->part->mV.word]
559 = MICRO_TO_MILLI(uV) << vreg->part->mV.shift;
560 mask[vreg->part->mV.word] = vreg->part->mV.mask;
David Collins13397f22012-02-06 13:53:29 -0800561 } else if (vreg->part->enable_state.mask) {
562 /*
563 * Translate max_uV > 0 into an enable request for regulator
564 * types which to not support voltage setting, e.g. voltage
565 * switches.
566 */
567 val[vreg->part->enable_state.word]
568 = (max_uV > 0 ? 1 : 0) << vreg->part->enable_state.shift;
569 mask[vreg->part->enable_state.word]
570 = vreg->part->enable_state.mask;
David Collins6f032ba2011-08-31 14:08:15 -0700571 }
572
573 rc = vreg_set_noirq(vreg, voter, sleep_also, mask[0], val[0], mask[1],
574 val[1], vreg->part->request_len, 1);
575 if (rc)
576 vreg_err(vreg, "vreg_set_noirq failed, rc=%d\n", rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700577
578 return rc;
579}
580EXPORT_SYMBOL_GPL(rpm_vreg_set_voltage);
581
582/**
583 * rpm_vreg_set_frequency - sets the frequency of a switching regulator
584 * @vreg: ID for regulator
David Collins6f032ba2011-08-31 14:08:15 -0700585 * @freq: enum corresponding to desired frequency
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700586 *
587 * Returns 0 on success or errno.
588 */
David Collins6f032ba2011-08-31 14:08:15 -0700589int rpm_vreg_set_frequency(int vreg_id, enum rpm_vreg_freq freq)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700590{
David Collins6f032ba2011-08-31 14:08:15 -0700591 unsigned int mask[2] = {0}, val[2] = {0};
592 struct vreg *vreg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700593 int rc;
594
David Collins6f032ba2011-08-31 14:08:15 -0700595 if (!config) {
596 pr_err("rpm-regulator driver has not probed yet.\n");
597 return -ENODEV;
598 }
599
600 if (vreg_id < config->vreg_id_min || vreg_id > config->vreg_id_max) {
601 pr_err("invalid regulator id=%d\n", vreg_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700602 return -EINVAL;
603 }
604
David Collins6f032ba2011-08-31 14:08:15 -0700605 vreg = &config->vregs[vreg_id];
606
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700607 if (freq < 0 || freq > RPM_VREG_FREQ_1p20) {
David Collins6f032ba2011-08-31 14:08:15 -0700608 vreg_err(vreg, "invalid frequency=%d\n", freq);
609 return -EINVAL;
610 }
611 if (!vreg->pdata.sleep_selectable) {
612 vreg_err(vreg, "regulator is not marked sleep selectable\n");
613 return -EINVAL;
614 }
615 if (!vreg->part->freq.mask) {
616 vreg_err(vreg, "frequency not supported\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700617 return -EINVAL;
618 }
619
David Collins6f032ba2011-08-31 14:08:15 -0700620 val[vreg->part->freq.word] = freq << vreg->part->freq.shift;
621 mask[vreg->part->freq.word] = vreg->part->freq.mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700622
David Collins6f032ba2011-08-31 14:08:15 -0700623 rc = vreg_set_noirq(vreg, RPM_VREG_VOTER_REG_FRAMEWORK, 1, mask[0],
624 val[0], mask[1], val[1], vreg->part->request_len, 0);
625 if (rc)
626 vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700627
628 return rc;
629}
630EXPORT_SYMBOL_GPL(rpm_vreg_set_frequency);
631
David Collins379b4b72012-05-14 16:33:51 -0700632#define MAX_NAME_LEN 64
633/**
634 * rpm_regulator_get() - lookup and obtain a handle to an RPM regulator
635 * @dev: device for regulator consumer
636 * @supply: supply name
637 *
638 * Returns a struct rpm_regulator corresponding to the regulator producer,
639 * or ERR_PTR() containing errno.
640 *
641 * This function may only be called from nonatomic context. The mapping between
642 * <dev, supply> tuples and rpm_regulators struct pointers is specified via
643 * rpm-regulator platform data.
644 */
645struct rpm_regulator *rpm_regulator_get(struct device *dev, const char *supply)
646{
647 struct rpm_regulator_consumer_mapping *mapping = NULL;
648 const char *devname = NULL;
649 struct rpm_regulator *regulator;
650 int i;
651
652 if (!config) {
653 pr_err("rpm-regulator driver has not probed yet.\n");
654 return ERR_PTR(-ENODEV);
655 }
656
657 if (consumer_map == NULL || consumer_map_len == 0) {
658 pr_err("No private consumer mapping has been specified.\n");
659 return ERR_PTR(-ENODEV);
660 }
661
662 if (supply == NULL) {
663 pr_err("supply name must be specified\n");
664 return ERR_PTR(-EINVAL);
665 }
666
667 if (dev)
668 devname = dev_name(dev);
669
670 for (i = 0; i < consumer_map_len; i++) {
671 /* If the mapping has a device set up it must match */
672 if (consumer_map[i].dev_name &&
673 (!devname || strncmp(consumer_map[i].dev_name, devname,
674 MAX_NAME_LEN)))
675 continue;
676
677 if (strncmp(consumer_map[i].supply, supply, MAX_NAME_LEN)
678 == 0) {
679 mapping = &consumer_map[i];
680 break;
681 }
682 }
683
684 if (mapping == NULL) {
685 pr_err("could not find mapping for dev=%s, supply=%s\n",
686 (devname ? devname : "(null)"), supply);
687 return ERR_PTR(-ENODEV);
688 }
689
690 regulator = kzalloc(sizeof(struct rpm_regulator), GFP_KERNEL);
691 if (regulator == NULL) {
692 pr_err("could not allocate memory for regulator\n");
693 return ERR_PTR(-ENOMEM);
694 }
695
696 regulator->vreg_id = mapping->vreg_id;
697 regulator->voter = mapping->voter;
698 regulator->sleep_also = mapping->sleep_also;
699
700 return regulator;
701}
702EXPORT_SYMBOL_GPL(rpm_regulator_get);
703
704static int rpm_regulator_check_input(struct rpm_regulator *regulator)
705{
706 int rc = 0;
707
708 if (regulator == NULL) {
709 rc = -EINVAL;
710 pr_err("invalid (null) rpm_regulator pointer\n");
711 } else if (IS_ERR(regulator)) {
712 rc = PTR_ERR(regulator);
713 pr_err("invalid rpm_regulator pointer, rc=%d\n", rc);
714 }
715
716 return rc;
717}
718
719/**
720 * rpm_regulator_put() - free the RPM regulator handle
721 * @regulator: RPM regulator handle
722 *
723 * Parameter reaggregation does not take place when rpm_regulator_put is called.
724 * Therefore, regulator enable state and voltage must be configured
725 * appropriately before calling rpm_regulator_put.
726 *
727 * This function may be called from either atomic or nonatomic context.
728 */
729void rpm_regulator_put(struct rpm_regulator *regulator)
730{
731 kfree(regulator);
732}
733EXPORT_SYMBOL_GPL(rpm_regulator_put);
734
735/**
736 * rpm_regulator_enable() - enable regulator output
737 * @regulator: RPM regulator handle
738 *
739 * Returns 0 on success or errno on failure.
740 *
741 * This function may be called from either atomic or nonatomic context. This
742 * function may only be called for regulators which have the sleep_selectable
743 * flag set in their configuration data.
744 *
745 * rpm_regulator_set_voltage must be called before rpm_regulator_enable because
746 * enabling is defined by the RPM interface to be requesting the desired
747 * non-zero regulator output voltage.
748 */
749int rpm_regulator_enable(struct rpm_regulator *regulator)
750{
751 int rc = rpm_regulator_check_input(regulator);
752 struct vreg *vreg;
753
754 if (rc)
755 return rc;
756
757 if (regulator->vreg_id < config->vreg_id_min
758 || regulator->vreg_id > config->vreg_id_max) {
759 pr_err("invalid regulator id=%d\n", regulator->vreg_id);
760 return -EINVAL;
761 }
762
763 vreg = &config->vregs[regulator->vreg_id];
764
765 /*
766 * Handle voltage switches which can be enabled without
767 * rpm_regulator_set_voltage ever being called.
768 */
769 if (regulator->min_uV == 0 && regulator->max_uV == 0
770 && vreg->part->uV.mask == 0 && vreg->part->mV.mask == 0) {
771 regulator->min_uV = 1;
772 regulator->max_uV = 1;
773 }
774
775 if (regulator->min_uV == 0 && regulator->max_uV == 0) {
776 pr_err("Voltage must be set with rpm_regulator_set_voltage "
777 "before calling rpm_regulator_enable; vreg_id=%d, "
778 "voter=%d\n", regulator->vreg_id, regulator->voter);
779 return -EINVAL;
780 }
781
782 rc = rpm_vreg_set_voltage(regulator->vreg_id, regulator->voter,
783 regulator->min_uV, regulator->max_uV, regulator->sleep_also);
784
785 if (rc)
786 pr_err("rpm_vreg_set_voltage failed, rc=%d\n", rc);
787
788 return rc;
789}
790EXPORT_SYMBOL_GPL(rpm_regulator_enable);
791
792/**
793 * rpm_regulator_disable() - disable regulator output
794 * @regulator: RPM regulator handle
795 *
796 * Returns 0 on success or errno on failure.
797 *
798 * The enable state of the regulator is determined by aggregating the requests
799 * of all consumers. Therefore, it is possible that the regulator will remain
800 * enabled even after rpm_regulator_disable is called.
801 *
802 * This function may be called from either atomic or nonatomic context. This
803 * function may only be called for regulators which have the sleep_selectable
804 * flag set in their configuration data.
805 */
806int rpm_regulator_disable(struct rpm_regulator *regulator)
807{
808 int rc = rpm_regulator_check_input(regulator);
809
810 if (rc)
811 return rc;
812
813 rc = rpm_vreg_set_voltage(regulator->vreg_id, regulator->voter, 0, 0,
814 regulator->sleep_also);
815
816 if (rc)
817 pr_err("rpm_vreg_set_voltage failed, rc=%d\n", rc);
818
819 return rc;
820}
821EXPORT_SYMBOL_GPL(rpm_regulator_disable);
822
823/**
824 * rpm_regulator_set_voltage() - set regulator output voltage
825 * @regulator: RPM regulator handle
826 * @min_uV: minimum required voltage in uV
827 * @max_uV: maximum acceptable voltage in uV
828 *
829 * Sets a voltage regulator to the desired output voltage. This can be set
830 * while the regulator is disabled or enabled. If the regulator is disabled,
831 * then rpm_regulator_set_voltage will both enable the regulator and set it to
832 * output at the requested voltage.
833 *
834 * The min_uV to max_uV voltage range requested must intersect with the
835 * voltage constraint range configured for the regulator.
836 *
837 * Returns 0 on success or errno on failure.
838 *
839 * The final voltage value that is sent to the RPM is aggregated based upon the
840 * values requested by all consumers of the regulator. This corresponds to the
841 * maximum min_uV value.
842 *
843 * This function may be called from either atomic or nonatomic context. This
844 * function may only be called for regulators which have the sleep_selectable
845 * flag set in their configuration data.
846 */
847int rpm_regulator_set_voltage(struct rpm_regulator *regulator, int min_uV,
848 int max_uV)
849{
850 int rc = rpm_regulator_check_input(regulator);
851
852 if (rc)
853 return rc;
854
855 rc = rpm_vreg_set_voltage(regulator->vreg_id, regulator->voter, min_uV,
856 max_uV, regulator->sleep_also);
857
858 if (rc) {
859 pr_err("rpm_vreg_set_voltage failed, rc=%d\n", rc);
860 } else {
861 regulator->min_uV = min_uV;
862 regulator->max_uV = max_uV;
863 }
864
865 return rc;
866}
867EXPORT_SYMBOL_GPL(rpm_regulator_set_voltage);
868
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700869static inline int vreg_hpm_min_uA(struct vreg *vreg)
870{
871 return vreg->hpm_min_load;
872}
873
874static inline int vreg_lpm_max_uA(struct vreg *vreg)
875{
876 return vreg->hpm_min_load - LOAD_THRESHOLD_STEP;
877}
878
David Collins6f032ba2011-08-31 14:08:15 -0700879static inline unsigned saturate_peak_load(struct vreg *vreg, unsigned load_uA)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700880{
David Collins6f032ba2011-08-31 14:08:15 -0700881 unsigned load_max
882 = MILLI_TO_MICRO(vreg->part->ip.mask >> vreg->part->ip.shift);
883
884 return (load_uA > load_max ? load_max : load_uA);
885}
886
887static inline unsigned saturate_avg_load(struct vreg *vreg, unsigned load_uA)
888{
889 unsigned load_max
890 = MILLI_TO_MICRO(vreg->part->ia.mask >> vreg->part->ia.shift);
891 return (load_uA > load_max ? load_max : load_uA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700892}
893
894/* Change vreg->req, but do not send it to the RPM. */
895static int vreg_store(struct vreg *vreg, unsigned mask0, unsigned val0,
896 unsigned mask1, unsigned val1)
897{
898 unsigned long flags = 0;
899
David Collins6f032ba2011-08-31 14:08:15 -0700900 if (vreg->pdata.sleep_selectable)
901 spin_lock_irqsave(&rpm_noirq_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700902
903 vreg->req[0].value &= ~mask0;
904 vreg->req[0].value |= val0 & mask0;
905
906 vreg->req[1].value &= ~mask1;
907 vreg->req[1].value |= val1 & mask1;
908
David Collins6f032ba2011-08-31 14:08:15 -0700909 if (vreg->pdata.sleep_selectable)
910 spin_unlock_irqrestore(&rpm_noirq_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700911
912 return 0;
913}
914
915static int vreg_set(struct vreg *vreg, unsigned mask0, unsigned val0,
916 unsigned mask1, unsigned val1, unsigned cnt)
917{
918 unsigned prev0 = 0, prev1 = 0;
919 int rc;
920
921 /*
922 * Bypass the normal route for regulators that can be called to change
923 * just the active set values.
924 */
David Collins6f032ba2011-08-31 14:08:15 -0700925 if (vreg->pdata.sleep_selectable)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700926 return vreg_set_noirq(vreg, RPM_VREG_VOTER_REG_FRAMEWORK, 1,
927 mask0, val0, mask1, val1, cnt, 1);
928
929 prev0 = vreg->req[0].value;
930 vreg->req[0].value &= ~mask0;
931 vreg->req[0].value |= val0 & mask0;
932
933 prev1 = vreg->req[1].value;
934 vreg->req[1].value &= ~mask1;
935 vreg->req[1].value |= val1 & mask1;
936
937 /* Ignore duplicate requests */
938 if (vreg->req[0].value == vreg->prev_active_req[0].value &&
939 vreg->req[1].value == vreg->prev_active_req[1].value) {
940 if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_DUPLICATE)
David Collins6f032ba2011-08-31 14:08:15 -0700941 rpm_regulator_duplicate(vreg, MSM_RPM_CTX_SET_0, cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700942 return 0;
943 }
944
945 rc = msm_rpm_set(MSM_RPM_CTX_SET_0, vreg->req, cnt);
946 if (rc) {
947 vreg->req[0].value = prev0;
948 vreg->req[1].value = prev1;
949
David Collins6f032ba2011-08-31 14:08:15 -0700950 vreg_err(vreg, "msm_rpm_set failed, set=active, id=%d, rc=%d\n",
951 vreg->req[0].id, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700952 } else {
953 if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_REQUEST)
David Collins6f032ba2011-08-31 14:08:15 -0700954 rpm_regulator_req(vreg, MSM_RPM_CTX_SET_0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700955 vreg->prev_active_req[0].value = vreg->req[0].value;
956 vreg->prev_active_req[1].value = vreg->req[1].value;
957 }
958
959 return rc;
960}
961
David Collins6f032ba2011-08-31 14:08:15 -0700962static int vreg_is_enabled(struct regulator_dev *rdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700963{
David Collins6f032ba2011-08-31 14:08:15 -0700964 struct vreg *vreg = rdev_get_drvdata(rdev);
965 int enabled;
966
967 mutex_lock(&vreg->pc_lock);
968 enabled = vreg->is_enabled;
969 mutex_unlock(&vreg->pc_lock);
970
971 return enabled;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700972}
973
David Collins6f032ba2011-08-31 14:08:15 -0700974static void set_enable(struct vreg *vreg, unsigned int *mask, unsigned int *val)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700975{
David Collins6f032ba2011-08-31 14:08:15 -0700976 switch (vreg->type) {
977 case RPM_REGULATOR_TYPE_LDO:
978 case RPM_REGULATOR_TYPE_SMPS:
David Collins0ac31fe2012-02-08 13:53:34 -0800979 case RPM_REGULATOR_TYPE_CORNER:
David Collins6f032ba2011-08-31 14:08:15 -0700980 /* Enable by setting a voltage. */
981 if (vreg->part->uV.mask) {
982 val[vreg->part->uV.word]
983 |= vreg->save_uV << vreg->part->uV.shift;
984 mask[vreg->part->uV.word] |= vreg->part->uV.mask;
985 } else {
986 val[vreg->part->mV.word]
987 |= MICRO_TO_MILLI(vreg->save_uV)
988 << vreg->part->mV.shift;
989 mask[vreg->part->mV.word] |= vreg->part->mV.mask;
990 }
991 break;
992 case RPM_REGULATOR_TYPE_VS:
993 case RPM_REGULATOR_TYPE_NCP:
994 /* Enable by setting enable_state. */
995 val[vreg->part->enable_state.word]
996 |= RPM_VREG_STATE_ON << vreg->part->enable_state.shift;
997 mask[vreg->part->enable_state.word]
998 |= vreg->part->enable_state.mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700999 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001000}
1001
David Collins0ac31fe2012-02-08 13:53:34 -08001002static int rpm_vreg_enable(struct regulator_dev *rdev)
David Collins6f032ba2011-08-31 14:08:15 -07001003{
1004 struct vreg *vreg = rdev_get_drvdata(rdev);
1005 unsigned int mask[2] = {0}, val[2] = {0};
1006 int rc = 0;
1007
1008 set_enable(vreg, mask, val);
1009
1010 mutex_lock(&vreg->pc_lock);
1011
1012 rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
1013 vreg->part->request_len);
1014 if (!rc)
1015 vreg->is_enabled = true;
1016
1017 mutex_unlock(&vreg->pc_lock);
1018
1019 if (rc)
1020 vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
1021
1022 return rc;
1023}
1024
1025static void set_disable(struct vreg *vreg, unsigned int *mask,
1026 unsigned int *val)
1027{
1028 switch (vreg->type) {
1029 case RPM_REGULATOR_TYPE_LDO:
1030 case RPM_REGULATOR_TYPE_SMPS:
David Collins0ac31fe2012-02-08 13:53:34 -08001031 case RPM_REGULATOR_TYPE_CORNER:
David Collins6f032ba2011-08-31 14:08:15 -07001032 /* Disable by setting a voltage of 0 uV. */
1033 if (vreg->part->uV.mask) {
1034 val[vreg->part->uV.word] |= 0 << vreg->part->uV.shift;
1035 mask[vreg->part->uV.word] |= vreg->part->uV.mask;
1036 } else {
1037 val[vreg->part->mV.word] |= 0 << vreg->part->mV.shift;
1038 mask[vreg->part->mV.word] |= vreg->part->mV.mask;
1039 }
1040 break;
1041 case RPM_REGULATOR_TYPE_VS:
1042 case RPM_REGULATOR_TYPE_NCP:
1043 /* Disable by setting enable_state. */
1044 val[vreg->part->enable_state.word]
1045 |= RPM_VREG_STATE_OFF << vreg->part->enable_state.shift;
1046 mask[vreg->part->enable_state.word]
1047 |= vreg->part->enable_state.mask;
1048 }
1049}
1050
David Collins0ac31fe2012-02-08 13:53:34 -08001051static int rpm_vreg_disable(struct regulator_dev *rdev)
David Collins6f032ba2011-08-31 14:08:15 -07001052{
1053 struct vreg *vreg = rdev_get_drvdata(rdev);
1054 unsigned int mask[2] = {0}, val[2] = {0};
1055 int rc = 0;
1056
1057 set_disable(vreg, mask, val);
1058
1059 mutex_lock(&vreg->pc_lock);
1060
1061 /* Only disable if pin control is not in use. */
1062 if (!vreg->is_enabled_pc)
1063 rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
1064 vreg->part->request_len);
1065
1066 if (!rc)
1067 vreg->is_enabled = false;
1068
1069 mutex_unlock(&vreg->pc_lock);
1070
1071 if (rc)
1072 vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
1073
1074 return rc;
1075}
1076
1077static int vreg_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001078 unsigned *selector)
1079{
David Collins6f032ba2011-08-31 14:08:15 -07001080 struct vreg *vreg = rdev_get_drvdata(rdev);
1081 struct vreg_range *range = &vreg->set_points->range[0];
1082 unsigned int mask[2] = {0}, val[2] = {0};
1083 int rc = 0, uV = min_uV;
1084 int lim_min_uV, lim_max_uV, i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001085
David Collins6f032ba2011-08-31 14:08:15 -07001086 /* Check if request voltage is outside of physically settable range. */
1087 lim_min_uV = vreg->set_points->range[0].min_uV;
1088 lim_max_uV =
1089 vreg->set_points->range[vreg->set_points->count - 1].max_uV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001090
David Collins6f032ba2011-08-31 14:08:15 -07001091 if (uV < lim_min_uV && max_uV >= lim_min_uV)
1092 uV = lim_min_uV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001093
David Collins6f032ba2011-08-31 14:08:15 -07001094 if (uV < lim_min_uV || uV > lim_max_uV) {
1095 vreg_err(vreg,
1096 "request v=[%d, %d] is outside possible v=[%d, %d]\n",
1097 min_uV, max_uV, lim_min_uV, lim_max_uV);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001098 return -EINVAL;
1099 }
1100
David Collins6f032ba2011-08-31 14:08:15 -07001101 /* Find the range which uV is inside of. */
1102 for (i = vreg->set_points->count - 1; i > 0; i--) {
1103 if (uV > vreg->set_points->range[i - 1].max_uV) {
1104 range = &vreg->set_points->range[i];
1105 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001106 }
1107 }
1108
David Collins6f032ba2011-08-31 14:08:15 -07001109 /*
1110 * Force uV to be an allowed set point and apply a ceiling function
1111 * to non-set point values.
1112 */
1113 uV = (uV - range->min_uV + range->step_uV - 1) / range->step_uV;
1114 uV = uV * range->step_uV + range->min_uV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001115
David Collins3974b612011-11-21 15:07:36 -08001116 if (uV > max_uV) {
1117 vreg_err(vreg,
1118 "request v=[%d, %d] cannot be met by any set point; "
1119 "next set point: %d\n",
1120 min_uV, max_uV, uV);
1121 return -EINVAL;
1122 }
1123
David Collins0ac31fe2012-02-08 13:53:34 -08001124 if (vreg->type == RPM_REGULATOR_TYPE_CORNER) {
1125 /*
1126 * Translate from enum values which work as inputs in the
1127 * regulator_set_voltage function to the actual corner values
1128 * sent to the RPM.
1129 */
1130 uV -= RPM_VREG_CORNER_NONE;
1131 }
1132
David Collins6f032ba2011-08-31 14:08:15 -07001133 if (vreg->part->uV.mask) {
1134 val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
1135 mask[vreg->part->uV.word] = vreg->part->uV.mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001136 } else {
David Collins6f032ba2011-08-31 14:08:15 -07001137 val[vreg->part->mV.word]
1138 = MICRO_TO_MILLI(uV) << vreg->part->mV.shift;
1139 mask[vreg->part->mV.word] = vreg->part->mV.mask;
1140 }
1141
1142 mutex_lock(&vreg->pc_lock);
1143
1144 /*
1145 * Only send a request for a new voltage if the regulator is currently
1146 * enabled. This will ensure that LDO and SMPS regulators are not
1147 * inadvertently turned on because voltage > 0 is equivalent to
1148 * enabling. For NCP, this just removes unnecessary RPM requests.
1149 */
1150 if (vreg->is_enabled) {
1151 rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
1152 vreg->part->request_len);
1153 if (rc)
1154 vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
1155 } else if (vreg->type == RPM_REGULATOR_TYPE_NCP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001156 /* Regulator is disabled; store but don't send new request. */
David Collins6f032ba2011-08-31 14:08:15 -07001157 rc = vreg_store(vreg, mask[0], val[0], mask[1], val[1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001158 }
1159
David Collins6f032ba2011-08-31 14:08:15 -07001160 if (!rc && (!vreg->pdata.sleep_selectable || !vreg->is_enabled))
1161 vreg->save_uV = uV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001162
David Collins6f032ba2011-08-31 14:08:15 -07001163 mutex_unlock(&vreg->pc_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001164
1165 return rc;
1166}
1167
David Collins6f032ba2011-08-31 14:08:15 -07001168static int vreg_get_voltage(struct regulator_dev *rdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001169{
David Collins6f032ba2011-08-31 14:08:15 -07001170 struct vreg *vreg = rdev_get_drvdata(rdev);
1171
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001172 return vreg->save_uV;
1173}
1174
David Collins6f032ba2011-08-31 14:08:15 -07001175static int vreg_list_voltage(struct regulator_dev *rdev, unsigned selector)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001176{
David Collins6f032ba2011-08-31 14:08:15 -07001177 struct vreg *vreg = rdev_get_drvdata(rdev);
1178 int uV = 0;
1179 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001180
David Collins6f032ba2011-08-31 14:08:15 -07001181 if (!vreg->set_points) {
1182 vreg_err(vreg, "no voltages available\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001183 return -EINVAL;
1184 }
1185
David Collins6f032ba2011-08-31 14:08:15 -07001186 if (selector >= vreg->set_points->n_voltages)
1187 return 0;
1188
1189 for (i = 0; i < vreg->set_points->count; i++) {
1190 if (selector < vreg->set_points->range[i].n_voltages) {
1191 uV = selector * vreg->set_points->range[i].step_uV
1192 + vreg->set_points->range[i].min_uV;
1193 break;
1194 } else {
1195 selector -= vreg->set_points->range[i].n_voltages;
1196 }
1197 }
1198
1199 return uV;
1200}
1201
1202static int vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
1203{
1204 struct vreg *vreg = rdev_get_drvdata(rdev);
1205 unsigned int mask[2] = {0}, val[2] = {0};
1206 int rc = 0;
1207 int peak_uA;
1208
1209 mutex_lock(&vreg->pc_lock);
1210
1211 peak_uA = MILLI_TO_MICRO((vreg->req[vreg->part->ip.word].value
1212 & vreg->part->ip.mask) >> vreg->part->ip.shift);
1213
1214 if (mode == config->mode_hpm) {
1215 /* Make sure that request currents are in HPM range. */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001216 if (peak_uA < vreg_hpm_min_uA(vreg)) {
David Collins6f032ba2011-08-31 14:08:15 -07001217 val[vreg->part->ip.word]
1218 = MICRO_TO_MILLI(vreg_hpm_min_uA(vreg))
1219 << vreg->part->ip.shift;
1220 mask[vreg->part->ip.word] = vreg->part->ip.mask;
1221
1222 if (config->ia_follows_ip) {
1223 val[vreg->part->ia.word]
1224 |= MICRO_TO_MILLI(vreg_hpm_min_uA(vreg))
1225 << vreg->part->ia.shift;
1226 mask[vreg->part->ia.word]
1227 |= vreg->part->ia.mask;
1228 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001229 }
David Collins6f032ba2011-08-31 14:08:15 -07001230 } else if (mode == config->mode_lpm) {
1231 /* Make sure that request currents are in LPM range. */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001232 if (peak_uA > vreg_lpm_max_uA(vreg)) {
David Collins6f032ba2011-08-31 14:08:15 -07001233 val[vreg->part->ip.word]
1234 = MICRO_TO_MILLI(vreg_lpm_max_uA(vreg))
1235 << vreg->part->ip.shift;
1236 mask[vreg->part->ip.word] = vreg->part->ip.mask;
1237
1238 if (config->ia_follows_ip) {
1239 val[vreg->part->ia.word]
1240 |= MICRO_TO_MILLI(vreg_lpm_max_uA(vreg))
1241 << vreg->part->ia.shift;
1242 mask[vreg->part->ia.word]
1243 |= vreg->part->ia.mask;
1244 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001245 }
David Collins6f032ba2011-08-31 14:08:15 -07001246 } else {
1247 vreg_err(vreg, "invalid mode: %u\n", mode);
1248 mutex_unlock(&vreg->pc_lock);
1249 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001250 }
1251
David Collins6f032ba2011-08-31 14:08:15 -07001252 if (vreg->is_enabled) {
1253 rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
1254 vreg->part->request_len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001255 } else {
1256 /* Regulator is disabled; store but don't send new request. */
David Collins6f032ba2011-08-31 14:08:15 -07001257 rc = vreg_store(vreg, mask[0], val[0], mask[1], val[1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001258 }
David Collins6f032ba2011-08-31 14:08:15 -07001259
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001260 if (rc)
David Collins6f032ba2011-08-31 14:08:15 -07001261 vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
1262 else
1263 vreg->mode = mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001264
David Collins6f032ba2011-08-31 14:08:15 -07001265 mutex_unlock(&vreg->pc_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001266
David Collins6f032ba2011-08-31 14:08:15 -07001267 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001268}
1269
David Collins6f032ba2011-08-31 14:08:15 -07001270static unsigned int vreg_get_mode(struct regulator_dev *rdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001271{
David Collins6f032ba2011-08-31 14:08:15 -07001272 struct vreg *vreg = rdev_get_drvdata(rdev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001273
David Collins6f032ba2011-08-31 14:08:15 -07001274 return vreg->mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001275}
1276
David Collins6f032ba2011-08-31 14:08:15 -07001277static unsigned int vreg_get_optimum_mode(struct regulator_dev *rdev,
1278 int input_uV, int output_uV, int load_uA)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001279{
David Collins6f032ba2011-08-31 14:08:15 -07001280 struct vreg *vreg = rdev_get_drvdata(rdev);
1281 unsigned int mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001282
David Collins6f032ba2011-08-31 14:08:15 -07001283 load_uA += vreg->pdata.system_uA;
1284
1285 mutex_lock(&vreg->pc_lock);
1286 SET_PART(vreg, ip, MICRO_TO_MILLI(saturate_peak_load(vreg, load_uA)));
1287 if (config->ia_follows_ip)
1288 SET_PART(vreg, ia,
1289 MICRO_TO_MILLI(saturate_avg_load(vreg, load_uA)));
1290 mutex_unlock(&vreg->pc_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001291
1292 if (load_uA >= vreg->hpm_min_load)
David Collins6f032ba2011-08-31 14:08:15 -07001293 mode = config->mode_hpm;
1294 else
1295 mode = config->mode_lpm;
1296
1297 return mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001298}
1299
David Collins6f032ba2011-08-31 14:08:15 -07001300static unsigned int vreg_legacy_get_optimum_mode(struct regulator_dev *rdev,
1301 int input_uV, int output_uV, int load_uA)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001302{
David Collins6f032ba2011-08-31 14:08:15 -07001303 struct vreg *vreg = rdev_get_drvdata(rdev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001304
David Collins6f032ba2011-08-31 14:08:15 -07001305 if (MICRO_TO_MILLI(load_uA) <= 0) {
1306 /*
1307 * vreg_legacy_get_optimum_mode is being called before consumers
1308 * have specified their load currents via
1309 * regulator_set_optimum_mode. Return whatever the existing mode
1310 * is.
1311 */
1312 return vreg->mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001313 }
1314
David Collins6f032ba2011-08-31 14:08:15 -07001315 return vreg_get_optimum_mode(rdev, input_uV, output_uV, load_uA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001316}
1317
1318/*
David Collins6f032ba2011-08-31 14:08:15 -07001319 * Returns the logical pin control enable state because the pin control options
1320 * present in the hardware out of restart could be different from those desired
1321 * by the consumer.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001322 */
David Collins6f032ba2011-08-31 14:08:15 -07001323static int vreg_pin_control_is_enabled(struct regulator_dev *rdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001324{
David Collins6f032ba2011-08-31 14:08:15 -07001325 struct vreg *vreg = rdev_get_drvdata(rdev);
1326
1327 return vreg->is_enabled_pc;
1328}
1329
1330static int vreg_pin_control_enable(struct regulator_dev *rdev)
1331{
1332 struct vreg *vreg = rdev_get_drvdata(rdev);
1333 unsigned int mask[2] = {0}, val[2] = {0};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001334 int rc;
1335
David Collins6f032ba2011-08-31 14:08:15 -07001336 mutex_lock(&vreg->pc_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001337
David Collins6f032ba2011-08-31 14:08:15 -07001338 val[vreg->part->pc.word]
1339 |= vreg->pdata.pin_ctrl << vreg->part->pc.shift;
1340 mask[vreg->part->pc.word] |= vreg->part->pc.mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001341
David Collins6f032ba2011-08-31 14:08:15 -07001342 val[vreg->part->pf.word] |= vreg->pdata.pin_fn << vreg->part->pf.shift;
1343 mask[vreg->part->pf.word] |= vreg->part->pf.mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001344
David Collins6f032ba2011-08-31 14:08:15 -07001345 if (!vreg->is_enabled)
1346 set_enable(vreg, mask, val);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001347
David Collins6f032ba2011-08-31 14:08:15 -07001348 rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
1349 vreg->part->request_len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001350
David Collins6f032ba2011-08-31 14:08:15 -07001351 if (!rc)
1352 vreg->is_enabled_pc = true;
1353
1354 mutex_unlock(&vreg->pc_lock);
1355
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001356 if (rc)
David Collins6f032ba2011-08-31 14:08:15 -07001357 vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001358
David Collins6f032ba2011-08-31 14:08:15 -07001359 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001360}
1361
David Collins6f032ba2011-08-31 14:08:15 -07001362static int vreg_pin_control_disable(struct regulator_dev *rdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001363{
David Collins6f032ba2011-08-31 14:08:15 -07001364 struct vreg *vreg = rdev_get_drvdata(rdev);
1365 unsigned int mask[2] = {0}, val[2] = {0};
1366 int pin_fn, rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001367
David Collins6f032ba2011-08-31 14:08:15 -07001368 mutex_lock(&vreg->pc_lock);
1369
1370 val[vreg->part->pc.word]
1371 |= RPM_VREG_PIN_CTRL_NONE << vreg->part->pc.shift;
1372 mask[vreg->part->pc.word] |= vreg->part->pc.mask;
1373
1374 pin_fn = config->pin_func_none;
1375 if (vreg->pdata.pin_fn == config->pin_func_sleep_b)
1376 pin_fn = config->pin_func_sleep_b;
1377 val[vreg->part->pf.word] |= pin_fn << vreg->part->pf.shift;
1378 mask[vreg->part->pf.word] |= vreg->part->pf.mask;
1379
1380 if (!vreg->is_enabled)
1381 set_disable(vreg, mask, val);
1382
1383 rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
1384 vreg->part->request_len);
1385
1386 if (!rc)
1387 vreg->is_enabled_pc = false;
1388
1389 mutex_unlock(&vreg->pc_lock);
1390
1391 if (rc)
1392 vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
1393
1394 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001395}
1396
David Collins6f032ba2011-08-31 14:08:15 -07001397static int vreg_enable_time(struct regulator_dev *rdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001398{
David Collins6f032ba2011-08-31 14:08:15 -07001399 struct vreg *vreg = rdev_get_drvdata(rdev);
1400
1401 return vreg->pdata.enable_time;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001402}
1403
David Collins6f032ba2011-08-31 14:08:15 -07001404/* Real regulator operations. */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001405static struct regulator_ops ldo_ops = {
David Collins0ac31fe2012-02-08 13:53:34 -08001406 .enable = rpm_vreg_enable,
1407 .disable = rpm_vreg_disable,
David Collins6f032ba2011-08-31 14:08:15 -07001408 .is_enabled = vreg_is_enabled,
1409 .set_voltage = vreg_set_voltage,
1410 .get_voltage = vreg_get_voltage,
1411 .list_voltage = vreg_list_voltage,
1412 .set_mode = vreg_set_mode,
1413 .get_mode = vreg_get_mode,
1414 .get_optimum_mode = vreg_get_optimum_mode,
1415 .enable_time = vreg_enable_time,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001416};
1417
1418static struct regulator_ops smps_ops = {
David Collins0ac31fe2012-02-08 13:53:34 -08001419 .enable = rpm_vreg_enable,
1420 .disable = rpm_vreg_disable,
David Collins6f032ba2011-08-31 14:08:15 -07001421 .is_enabled = vreg_is_enabled,
1422 .set_voltage = vreg_set_voltage,
1423 .get_voltage = vreg_get_voltage,
1424 .list_voltage = vreg_list_voltage,
1425 .set_mode = vreg_set_mode,
1426 .get_mode = vreg_get_mode,
1427 .get_optimum_mode = vreg_get_optimum_mode,
1428 .enable_time = vreg_enable_time,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001429};
1430
1431static struct regulator_ops switch_ops = {
David Collins0ac31fe2012-02-08 13:53:34 -08001432 .enable = rpm_vreg_enable,
1433 .disable = rpm_vreg_disable,
David Collins6f032ba2011-08-31 14:08:15 -07001434 .is_enabled = vreg_is_enabled,
1435 .enable_time = vreg_enable_time,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001436};
1437
1438static struct regulator_ops ncp_ops = {
David Collins0ac31fe2012-02-08 13:53:34 -08001439 .enable = rpm_vreg_enable,
1440 .disable = rpm_vreg_disable,
1441 .is_enabled = vreg_is_enabled,
1442 .set_voltage = vreg_set_voltage,
1443 .get_voltage = vreg_get_voltage,
1444 .list_voltage = vreg_list_voltage,
1445 .enable_time = vreg_enable_time,
1446};
1447
1448static struct regulator_ops corner_ops = {
1449 .enable = rpm_vreg_enable,
1450 .disable = rpm_vreg_disable,
David Collins6f032ba2011-08-31 14:08:15 -07001451 .is_enabled = vreg_is_enabled,
1452 .set_voltage = vreg_set_voltage,
1453 .get_voltage = vreg_get_voltage,
1454 .list_voltage = vreg_list_voltage,
1455 .enable_time = vreg_enable_time,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001456};
1457
David Collins6f032ba2011-08-31 14:08:15 -07001458/* Pin control regulator operations. */
1459static struct regulator_ops pin_control_ops = {
1460 .enable = vreg_pin_control_enable,
1461 .disable = vreg_pin_control_disable,
1462 .is_enabled = vreg_pin_control_is_enabled,
1463};
1464
1465struct regulator_ops *vreg_ops[] = {
1466 [RPM_REGULATOR_TYPE_LDO] = &ldo_ops,
1467 [RPM_REGULATOR_TYPE_SMPS] = &smps_ops,
1468 [RPM_REGULATOR_TYPE_VS] = &switch_ops,
1469 [RPM_REGULATOR_TYPE_NCP] = &ncp_ops,
David Collins0ac31fe2012-02-08 13:53:34 -08001470 [RPM_REGULATOR_TYPE_CORNER] = &corner_ops,
David Collins6f032ba2011-08-31 14:08:15 -07001471};
1472
1473static int __devinit
1474rpm_vreg_init_regulator(const struct rpm_regulator_init_data *pdata,
1475 struct device *dev)
1476{
1477 struct regulator_desc *rdesc = NULL;
1478 struct regulator_dev *rdev;
1479 struct vreg *vreg;
1480 unsigned pin_ctrl;
1481 int id, pin_fn;
1482 int rc = 0;
1483
1484 if (!pdata) {
1485 pr_err("platform data missing\n");
1486 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001487 }
1488
David Collins6f032ba2011-08-31 14:08:15 -07001489 id = pdata->id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001490
David Collins6f032ba2011-08-31 14:08:15 -07001491 if (id < config->vreg_id_min || id > config->vreg_id_max) {
1492 pr_err("invalid regulator id: %d\n", id);
1493 return -ENODEV;
1494 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001495
David Collins6f032ba2011-08-31 14:08:15 -07001496 if (!config->is_real_id(pdata->id))
1497 id = config->pc_id_to_real_id(pdata->id);
1498 vreg = &config->vregs[id];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001499
David Collins6f032ba2011-08-31 14:08:15 -07001500 if (config->is_real_id(pdata->id))
1501 rdesc = &vreg->rdesc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001502 else
David Collins6f032ba2011-08-31 14:08:15 -07001503 rdesc = &vreg->rdesc_pc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001504
David Collins6f032ba2011-08-31 14:08:15 -07001505 if (vreg->type < 0 || vreg->type > RPM_REGULATOR_TYPE_MAX) {
1506 pr_err("%s: invalid regulator type: %d\n",
1507 vreg->rdesc.name, vreg->type);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001508 return -EINVAL;
David Collins6f032ba2011-08-31 14:08:15 -07001509 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001510
David Collins6f032ba2011-08-31 14:08:15 -07001511 mutex_lock(&vreg->pc_lock);
1512
1513 if (vreg->set_points)
1514 rdesc->n_voltages = vreg->set_points->n_voltages;
1515 else
1516 rdesc->n_voltages = 0;
1517
1518 rdesc->id = pdata->id;
1519 rdesc->owner = THIS_MODULE;
1520 rdesc->type = REGULATOR_VOLTAGE;
1521
1522 if (config->is_real_id(pdata->id)) {
1523 /*
1524 * Real regulator; do not modify pin control and pin function
1525 * values.
1526 */
1527 rdesc->ops = vreg_ops[vreg->type];
1528 pin_ctrl = vreg->pdata.pin_ctrl;
1529 pin_fn = vreg->pdata.pin_fn;
1530 memcpy(&(vreg->pdata), pdata,
1531 sizeof(struct rpm_regulator_init_data));
1532 vreg->pdata.pin_ctrl = pin_ctrl;
1533 vreg->pdata.pin_fn = pin_fn;
1534
1535 vreg->save_uV = vreg->pdata.default_uV;
1536 if (vreg->pdata.peak_uA >= vreg->hpm_min_load)
1537 vreg->mode = config->mode_hpm;
1538 else
1539 vreg->mode = config->mode_lpm;
1540
1541 /* Initialize the RPM request. */
1542 SET_PART(vreg, ip,
1543 MICRO_TO_MILLI(saturate_peak_load(vreg, vreg->pdata.peak_uA)));
1544 SET_PART(vreg, fm, vreg->pdata.force_mode);
1545 SET_PART(vreg, pm, vreg->pdata.power_mode);
1546 SET_PART(vreg, pd, vreg->pdata.pull_down_enable);
1547 SET_PART(vreg, ia,
1548 MICRO_TO_MILLI(saturate_avg_load(vreg, vreg->pdata.avg_uA)));
1549 SET_PART(vreg, freq, vreg->pdata.freq);
1550 SET_PART(vreg, freq_clk_src, 0);
1551 SET_PART(vreg, comp_mode, 0);
1552 SET_PART(vreg, hpm, 0);
1553 if (!vreg->is_enabled_pc) {
1554 SET_PART(vreg, pf, config->pin_func_none);
1555 SET_PART(vreg, pc, RPM_VREG_PIN_CTRL_NONE);
1556 }
1557 } else {
1558 if ((pdata->pin_ctrl & RPM_VREG_PIN_CTRL_ALL)
1559 == RPM_VREG_PIN_CTRL_NONE
1560 && pdata->pin_fn != config->pin_func_sleep_b) {
1561 pr_err("%s: no pin control input specified\n",
1562 vreg->rdesc.name);
1563 mutex_unlock(&vreg->pc_lock);
1564 return -EINVAL;
1565 }
1566 rdesc->ops = &pin_control_ops;
1567 vreg->pdata.pin_ctrl = pdata->pin_ctrl;
1568 vreg->pdata.pin_fn = pdata->pin_fn;
1569
1570 /* Initialize the RPM request. */
1571 pin_fn = config->pin_func_none;
1572 /* Allow pf=sleep_b to be specified by platform data. */
1573 if (vreg->pdata.pin_fn == config->pin_func_sleep_b)
1574 pin_fn = config->pin_func_sleep_b;
1575 SET_PART(vreg, pf, pin_fn);
1576 SET_PART(vreg, pc, RPM_VREG_PIN_CTRL_NONE);
1577 }
1578
1579 mutex_unlock(&vreg->pc_lock);
1580
1581 if (rc)
1582 goto bail;
1583
Rajendra Nayak11eafc62011-11-18 16:47:19 +05301584 rdev = regulator_register(rdesc, dev, &(pdata->init_data), vreg, NULL);
David Collins6f032ba2011-08-31 14:08:15 -07001585 if (IS_ERR(rdev)) {
1586 rc = PTR_ERR(rdev);
1587 pr_err("regulator_register failed: %s, rc=%d\n",
1588 vreg->rdesc.name, rc);
1589 return rc;
1590 } else {
1591 if (config->is_real_id(pdata->id))
1592 vreg->rdev = rdev;
1593 else
1594 vreg->rdev_pc = rdev;
1595 }
1596
1597bail:
1598 if (rc)
1599 pr_err("error for %s, rc=%d\n", vreg->rdesc.name, rc);
1600
1601 return rc;
1602}
1603
1604static void rpm_vreg_set_point_init(void)
1605{
1606 struct vreg_set_points **set_points;
1607 int i, j, temp;
1608
1609 set_points = config->set_points;
1610
1611 /* Calculate the number of set points available for each regulator. */
1612 for (i = 0; i < config->set_points_len; i++) {
1613 temp = 0;
1614 for (j = 0; j < set_points[i]->count; j++) {
1615 set_points[i]->range[j].n_voltages
1616 = (set_points[i]->range[j].max_uV
1617 - set_points[i]->range[j].min_uV)
1618 / set_points[i]->range[j].step_uV + 1;
1619 temp += set_points[i]->range[j].n_voltages;
1620 }
1621 set_points[i]->n_voltages = temp;
1622 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001623}
1624
1625static int __devinit rpm_vreg_probe(struct platform_device *pdev)
1626{
David Collins6f032ba2011-08-31 14:08:15 -07001627 struct rpm_regulator_platform_data *platform_data;
David Collins379b4b72012-05-14 16:33:51 -07001628 static struct rpm_regulator_consumer_mapping *prev_consumer_map;
1629 static int prev_consumer_map_len;
David Collins6f032ba2011-08-31 14:08:15 -07001630 int rc = 0;
1631 int i, id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001632
David Collins6f032ba2011-08-31 14:08:15 -07001633 platform_data = pdev->dev.platform_data;
1634 if (!platform_data) {
1635 pr_err("rpm-regulator requires platform data\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001636 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001637 }
1638
David Collins6f032ba2011-08-31 14:08:15 -07001639 if (rpm_version >= 0 && rpm_version <= RPM_VREG_VERSION_MAX
1640 && platform_data->version != rpm_version) {
1641 pr_err("rpm version %d does not match previous version %d\n",
1642 platform_data->version, rpm_version);
1643 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001644 }
1645
David Collins6f032ba2011-08-31 14:08:15 -07001646 if (platform_data->version < 0
1647 || platform_data->version > RPM_VREG_VERSION_MAX) {
1648 pr_err("rpm version %d is invalid\n", platform_data->version);
1649 return -EINVAL;
1650 }
1651
1652 if (rpm_version < 0 || rpm_version > RPM_VREG_VERSION_MAX) {
1653 rpm_version = platform_data->version;
1654 config = get_config[platform_data->version]();
1655 vreg_id_vdd_mem = platform_data->vreg_id_vdd_mem;
1656 vreg_id_vdd_dig = platform_data->vreg_id_vdd_dig;
1657 if (!config) {
1658 pr_err("rpm version %d is not available\n",
1659 platform_data->version);
1660 return -ENODEV;
1661 }
1662 if (config->use_legacy_optimum_mode)
1663 for (i = 0; i < ARRAY_SIZE(vreg_ops); i++)
1664 vreg_ops[i]->get_optimum_mode
1665 = vreg_legacy_get_optimum_mode;
1666 rpm_vreg_set_point_init();
1667 /* First time probed; initialize pin control mutexes. */
1668 for (i = 0; i < config->vregs_len; i++)
1669 mutex_init(&config->vregs[i].pc_lock);
1670 }
1671
David Collins379b4b72012-05-14 16:33:51 -07001672 /* Copy the list of private API consumers. */
1673 if (platform_data->consumer_map_len > 0) {
1674 if (consumer_map_len == 0) {
1675 consumer_map_len = platform_data->consumer_map_len;
1676 consumer_map = kmemdup(platform_data->consumer_map,
1677 sizeof(struct rpm_regulator_consumer_mapping)
1678 * consumer_map_len, GFP_KERNEL);
1679 if (consumer_map == NULL) {
1680 pr_err("memory allocation failed\n");
1681 consumer_map_len = 0;
1682 return -ENOMEM;
1683 }
1684 } else {
1685 /* Concatenate new map with the existing one. */
1686 prev_consumer_map = consumer_map;
1687 prev_consumer_map_len = consumer_map_len;
1688 consumer_map_len += platform_data->consumer_map_len;
1689 consumer_map = kmalloc(
1690 sizeof(struct rpm_regulator_consumer_mapping)
1691 * consumer_map_len, GFP_KERNEL);
1692 if (consumer_map == NULL) {
1693 pr_err("memory allocation failed\n");
1694 consumer_map_len = 0;
1695 return -ENOMEM;
1696 }
1697 memcpy(consumer_map, prev_consumer_map,
1698 sizeof(struct rpm_regulator_consumer_mapping)
1699 * prev_consumer_map_len);
1700 memcpy(&consumer_map[prev_consumer_map_len],
1701 platform_data->consumer_map,
1702 sizeof(struct rpm_regulator_consumer_mapping)
1703 * platform_data->consumer_map_len);
1704 }
1705
1706 }
1707
David Collins6f032ba2011-08-31 14:08:15 -07001708 /* Initialize all of the regulators listed in the platform data. */
1709 for (i = 0; i < platform_data->num_regulators; i++) {
1710 rc = rpm_vreg_init_regulator(&platform_data->init_data[i],
1711 &pdev->dev);
1712 if (rc) {
1713 pr_err("rpm_vreg_init_regulator failed, rc=%d\n", rc);
1714 goto remove_regulators;
1715 }
1716 }
1717
1718 platform_set_drvdata(pdev, platform_data);
1719
1720 return rc;
1721
1722remove_regulators:
1723 /* Unregister all regulators added before the erroring one. */
1724 for (; i >= 0; i--) {
1725 id = platform_data->init_data[i].id;
1726 if (config->is_real_id(id)) {
1727 regulator_unregister(config->vregs[id].rdev);
1728 config->vregs[id].rdev = NULL;
1729 } else {
1730 regulator_unregister(config->vregs[
1731 config->pc_id_to_real_id(id)].rdev_pc);
1732 config->vregs[id].rdev_pc = NULL;
1733 }
1734 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001735
1736 return rc;
1737}
1738
1739static int __devexit rpm_vreg_remove(struct platform_device *pdev)
1740{
David Collins6f032ba2011-08-31 14:08:15 -07001741 struct rpm_regulator_platform_data *platform_data;
1742 int i, id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001743
David Collins6f032ba2011-08-31 14:08:15 -07001744 platform_data = platform_get_drvdata(pdev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001745 platform_set_drvdata(pdev, NULL);
David Collins6f032ba2011-08-31 14:08:15 -07001746
1747 if (platform_data) {
1748 for (i = 0; i < platform_data->num_regulators; i++) {
1749 id = platform_data->init_data[i].id;
1750 if (config->is_real_id(id)) {
1751 regulator_unregister(config->vregs[id].rdev);
1752 config->vregs[id].rdev = NULL;
1753 } else {
1754 regulator_unregister(config->vregs[
1755 config->pc_id_to_real_id(id)].rdev_pc);
1756 config->vregs[id].rdev_pc = NULL;
1757 }
1758 }
1759 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001760
1761 return 0;
1762}
1763
1764static struct platform_driver rpm_vreg_driver = {
1765 .probe = rpm_vreg_probe,
1766 .remove = __devexit_p(rpm_vreg_remove),
1767 .driver = {
David Collins6f032ba2011-08-31 14:08:15 -07001768 .name = RPM_REGULATOR_DEV_NAME,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001769 .owner = THIS_MODULE,
1770 },
1771};
1772
1773static int __init rpm_vreg_init(void)
1774{
1775 return platform_driver_register(&rpm_vreg_driver);
1776}
1777
1778static void __exit rpm_vreg_exit(void)
1779{
David Collins6f032ba2011-08-31 14:08:15 -07001780 int i;
1781
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001782 platform_driver_unregister(&rpm_vreg_driver);
David Collins6f032ba2011-08-31 14:08:15 -07001783
David Collins379b4b72012-05-14 16:33:51 -07001784 kfree(consumer_map);
1785
David Collins6f032ba2011-08-31 14:08:15 -07001786 for (i = 0; i < config->vregs_len; i++)
1787 mutex_destroy(&config->vregs[i].pc_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001788}
1789
1790postcore_initcall(rpm_vreg_init);
1791module_exit(rpm_vreg_exit);
1792
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001793MODULE_LICENSE("GPL v2");
David Collins6f032ba2011-08-31 14:08:15 -07001794MODULE_DESCRIPTION("MSM RPM regulator driver");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001795MODULE_VERSION("1.0");
David Collins6f032ba2011-08-31 14:08:15 -07001796MODULE_ALIAS("platform:" RPM_REGULATOR_DEV_NAME);