blob: 923e647f874871d2a1be091d669808dc6e4a2ebe [file] [log] [blame]
David Collins9deea5b2013-03-05 10:16:01 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
David Collinsc7642322012-04-04 10:19:12 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "%s: " fmt, __func__
14
15#include <linux/module.h>
16#include <linux/err.h>
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/slab.h>
20#include <linux/spinlock.h>
21#include <linux/string.h>
22#include <linux/of.h>
23#include <linux/of_device.h>
24#include <linux/platform_device.h>
25#include <linux/regulator/driver.h>
26#include <linux/regulator/machine.h>
27#include <linux/regulator/of_regulator.h>
28#include <mach/rpm-smd.h>
29#include <mach/rpm-regulator-smd.h>
30#include <mach/socinfo.h>
31
32/* Debug Definitions */
33
34enum {
35 RPM_VREG_DEBUG_REQUEST = BIT(0),
36 RPM_VREG_DEBUG_FULL_REQUEST = BIT(1),
37 RPM_VREG_DEBUG_DUPLICATE = BIT(2),
38};
39
40static int rpm_vreg_debug_mask;
41module_param_named(
42 debug_mask, rpm_vreg_debug_mask, int, S_IRUSR | S_IWUSR
43);
44
45#define vreg_err(req, fmt, ...) \
46 pr_err("%s: " fmt, req->rdesc.name, ##__VA_ARGS__)
47
48/* RPM regulator request types */
49enum rpm_regulator_smd_type {
50 RPM_REGULATOR_SMD_TYPE_LDO,
51 RPM_REGULATOR_SMD_TYPE_SMPS,
52 RPM_REGULATOR_SMD_TYPE_VS,
53 RPM_REGULATOR_SMD_TYPE_NCP,
54 RPM_REGULATOR_SMD_TYPE_MAX,
55};
56
57/* RPM resource parameters */
58enum rpm_regulator_param_index {
59 RPM_REGULATOR_PARAM_ENABLE,
60 RPM_REGULATOR_PARAM_VOLTAGE,
61 RPM_REGULATOR_PARAM_CURRENT,
62 RPM_REGULATOR_PARAM_MODE_LDO,
63 RPM_REGULATOR_PARAM_MODE_SMPS,
64 RPM_REGULATOR_PARAM_PIN_CTRL_ENABLE,
65 RPM_REGULATOR_PARAM_PIN_CTRL_MODE,
66 RPM_REGULATOR_PARAM_FREQUENCY,
67 RPM_REGULATOR_PARAM_HEAD_ROOM,
68 RPM_REGULATOR_PARAM_QUIET_MODE,
69 RPM_REGULATOR_PARAM_FREQ_REASON,
David Collins4208ce32012-06-15 13:33:13 -070070 RPM_REGULATOR_PARAM_CORNER,
David Collins85b71992012-07-18 12:00:14 -070071 RPM_REGULATOR_PARAM_BYPASS,
David Collins9deea5b2013-03-05 10:16:01 -080072 RPM_REGULATOR_PARAM_FLOOR_CORNER,
David Collinsc7642322012-04-04 10:19:12 -070073 RPM_REGULATOR_PARAM_MAX,
74};
75
David Collinsf0a12792013-03-26 14:49:12 -070076enum rpm_regulator_smps_mode {
77 RPM_REGULATOR_SMPS_MODE_AUTO = 0,
78 RPM_REGULATOR_SMPS_MODE_IPEAK = 1,
79 RPM_REGULATOR_SMPS_MODE_PWM = 2,
80};
81
82enum rpm_regulator_ldo_mode {
83 RPM_REGULATOR_LDO_MODE_IPEAK = 0,
84 RPM_REGULATOR_LDO_MODE_HPM = 1,
85};
86
David Collinsc7642322012-04-04 10:19:12 -070087#define RPM_SET_CONFIG_ACTIVE BIT(0)
88#define RPM_SET_CONFIG_SLEEP BIT(1)
89#define RPM_SET_CONFIG_BOTH (RPM_SET_CONFIG_ACTIVE \
90 | RPM_SET_CONFIG_SLEEP)
91struct rpm_regulator_param {
92 char *name;
93 char *property_name;
94 u32 key;
95 u32 min;
96 u32 max;
97 u32 supported_regulator_types;
98};
99
100#define PARAM(_idx, _support_ldo, _support_smps, _support_vs, _support_ncp, \
101 _name, _min, _max, _property_name) \
102 [RPM_REGULATOR_PARAM_##_idx] = { \
103 .name = _name, \
104 .property_name = _property_name, \
105 .min = _min, \
106 .max = _max, \
107 .supported_regulator_types = \
108 _support_ldo << RPM_REGULATOR_SMD_TYPE_LDO | \
109 _support_smps << RPM_REGULATOR_SMD_TYPE_SMPS | \
110 _support_vs << RPM_REGULATOR_SMD_TYPE_VS | \
111 _support_ncp << RPM_REGULATOR_SMD_TYPE_NCP, \
112 }
113
114static struct rpm_regulator_param params[RPM_REGULATOR_PARAM_MAX] = {
115 /* ID LDO SMPS VS NCP name min max property-name */
116 PARAM(ENABLE, 1, 1, 1, 1, "swen", 0, 1, "qcom,init-enable"),
117 PARAM(VOLTAGE, 1, 1, 0, 1, "uv", 0, 0x7FFFFFF, "qcom,init-voltage"),
118 PARAM(CURRENT, 1, 1, 0, 0, "ma", 0, 0x1FFF, "qcom,init-current"),
119 PARAM(MODE_LDO, 1, 0, 0, 0, "lsmd", 0, 1, "qcom,init-ldo-mode"),
120 PARAM(MODE_SMPS, 0, 1, 0, 0, "ssmd", 0, 2, "qcom,init-smps-mode"),
121 PARAM(PIN_CTRL_ENABLE, 1, 1, 1, 0, "pcen", 0, 0xF, "qcom,init-pin-ctrl-enable"),
122 PARAM(PIN_CTRL_MODE, 1, 1, 1, 0, "pcmd", 0, 0x1F, "qcom,init-pin-ctrl-mode"),
David Collinsd1247e02013-03-05 11:15:30 -0800123 PARAM(FREQUENCY, 0, 1, 0, 1, "freq", 0, 31, "qcom,init-frequency"),
David Collinsc7642322012-04-04 10:19:12 -0700124 PARAM(HEAD_ROOM, 1, 0, 0, 1, "hr", 0, 0x7FFFFFFF, "qcom,init-head-room"),
125 PARAM(QUIET_MODE, 0, 1, 0, 0, "qm", 0, 2, "qcom,init-quiet-mode"),
126 PARAM(FREQ_REASON, 0, 1, 0, 1, "resn", 0, 8, "qcom,init-freq-reason"),
David Collins23c96cd2012-10-05 17:12:00 -0700127 PARAM(CORNER, 1, 1, 0, 0, "corn", 0, 6, "qcom,init-voltage-corner"),
David Collins85b71992012-07-18 12:00:14 -0700128 PARAM(BYPASS, 1, 0, 0, 0, "bypa", 0, 1, "qcom,init-disallow-bypass"),
David Collins9deea5b2013-03-05 10:16:01 -0800129 PARAM(FLOOR_CORNER, 1, 1, 0, 0, "vfc", 0, 6, "qcom,init-voltage-floor-corner"),
David Collinsc7642322012-04-04 10:19:12 -0700130};
131
David Collinsf0a12792013-03-26 14:49:12 -0700132struct rpm_regulator_mode_map {
133 int ldo_mode;
134 int smps_mode;
135};
136
137static struct rpm_regulator_mode_map mode_mapping[] = {
138 [RPM_REGULATOR_MODE_AUTO]
139 = {-1, RPM_REGULATOR_SMPS_MODE_AUTO},
140 [RPM_REGULATOR_MODE_IPEAK]
141 = {RPM_REGULATOR_LDO_MODE_IPEAK, RPM_REGULATOR_SMPS_MODE_IPEAK},
142 [RPM_REGULATOR_MODE_HPM]
143 = {RPM_REGULATOR_LDO_MODE_HPM, RPM_REGULATOR_SMPS_MODE_PWM},
144};
145
David Collinsc7642322012-04-04 10:19:12 -0700146struct rpm_vreg_request {
147 u32 param[RPM_REGULATOR_PARAM_MAX];
148 u32 valid;
149 u32 modified;
150};
151
152struct rpm_vreg {
153 struct rpm_vreg_request aggr_req_active;
154 struct rpm_vreg_request aggr_req_sleep;
155 struct list_head reg_list;
156 const char *resource_name;
157 u32 resource_id;
158 bool allow_atomic;
159 int regulator_type;
160 int hpm_min_load;
161 int enable_time;
162 struct spinlock slock;
163 struct mutex mlock;
164 unsigned long flags;
165 bool sleep_request_sent;
166 struct msm_rpm_request *handle_active;
167 struct msm_rpm_request *handle_sleep;
168};
169
170struct rpm_regulator {
171 struct regulator_desc rdesc;
172 struct regulator_dev *rdev;
173 struct rpm_vreg *rpm_vreg;
174 struct list_head list;
175 bool set_active;
176 bool set_sleep;
David Collins409a9fa2013-03-05 10:54:25 -0800177 bool always_send_voltage;
178 bool always_send_current;
David Collinsc7642322012-04-04 10:19:12 -0700179 struct rpm_vreg_request req;
180 int system_load;
181 int min_uV;
182 int max_uV;
183};
184
185/*
186 * This voltage in uV is returned by get_voltage functions when there is no way
187 * to determine the current voltage level. It is needed because the regulator
188 * framework treats a 0 uV voltage as an error.
189 */
190#define VOLTAGE_UNKNOWN 1
191
192/*
193 * Regulator requests sent in the active set take effect immediately. Requests
194 * sent in the sleep set take effect when the Apps processor transitions into
195 * RPM assisted power collapse. For any given regulator, if an active set
196 * request is present, but not a sleep set request, then the active set request
197 * is used at all times, even when the Apps processor is power collapsed.
198 *
199 * The rpm-regulator-smd takes advantage of this default usage of the active set
200 * request by only sending a sleep set request if it differs from the
201 * corresponding active set request.
202 */
203#define RPM_SET_ACTIVE MSM_RPM_CTX_ACTIVE_SET
204#define RPM_SET_SLEEP MSM_RPM_CTX_SLEEP_SET
205
206static u32 rpm_vreg_string_to_int(const u8 *str)
207{
208 int i, len;
209 u32 output = 0;
210
211 len = strnlen(str, sizeof(u32));
212 for (i = 0; i < len; i++)
213 output |= str[i] << (i * 8);
214
215 return output;
216}
217
218static inline void rpm_vreg_lock(struct rpm_vreg *rpm_vreg)
219{
220 if (rpm_vreg->allow_atomic)
221 spin_lock_irqsave(&rpm_vreg->slock, rpm_vreg->flags);
222 else
223 mutex_lock(&rpm_vreg->mlock);
224}
225
226static inline void rpm_vreg_unlock(struct rpm_vreg *rpm_vreg)
227{
228 if (rpm_vreg->allow_atomic)
229 spin_unlock_irqrestore(&rpm_vreg->slock, rpm_vreg->flags);
230 else
231 mutex_unlock(&rpm_vreg->mlock);
232}
233
234static inline bool rpm_vreg_active_or_sleep_enabled(struct rpm_vreg *rpm_vreg)
235{
236 return (rpm_vreg->aggr_req_active.param[RPM_REGULATOR_PARAM_ENABLE]
237 && (rpm_vreg->aggr_req_active.valid
238 & BIT(RPM_REGULATOR_PARAM_ENABLE)))
239 || ((rpm_vreg->aggr_req_sleep.param[RPM_REGULATOR_PARAM_ENABLE])
240 && (rpm_vreg->aggr_req_sleep.valid
241 & BIT(RPM_REGULATOR_PARAM_ENABLE)));
242}
243
244/*
245 * This is used when voting for LPM or HPM by subtracting or adding to the
246 * hpm_min_load of a regulator. It has units of uA.
247 */
248#define LOAD_THRESHOLD_STEP 1000
249
250static inline int rpm_vreg_hpm_min_uA(struct rpm_vreg *rpm_vreg)
251{
252 return rpm_vreg->hpm_min_load;
253}
254
255static inline int rpm_vreg_lpm_max_uA(struct rpm_vreg *rpm_vreg)
256{
257 return rpm_vreg->hpm_min_load - LOAD_THRESHOLD_STEP;
258}
259
260#define MICRO_TO_MILLI(uV) ((uV) / 1000)
261#define MILLI_TO_MICRO(uV) ((uV) * 1000)
262
263#define DEBUG_PRINT_BUFFER_SIZE 512
264#define REQ_SENT 0
265#define REQ_PREV 1
266#define REQ_CACHED 2
267#define REQ_TYPES 3
268
269static void rpm_regulator_req(struct rpm_regulator *regulator, int set,
270 bool sent)
271{
272 char buf[DEBUG_PRINT_BUFFER_SIZE];
273 size_t buflen = DEBUG_PRINT_BUFFER_SIZE;
274 struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;
275 struct rpm_vreg_request *aggr;
276 bool first;
277 u32 mask[REQ_TYPES] = {0, 0, 0};
278 const char *req_names[REQ_TYPES] = {"sent", "prev", "cached"};
279 int pos = 0;
280 int i, j;
281
282 aggr = (set == RPM_SET_ACTIVE)
283 ? &rpm_vreg->aggr_req_active : &rpm_vreg->aggr_req_sleep;
284
285 if (rpm_vreg_debug_mask & RPM_VREG_DEBUG_DUPLICATE) {
286 mask[REQ_SENT] = aggr->modified;
287 mask[REQ_PREV] = aggr->valid & ~aggr->modified;
288 } else if (sent
289 && (rpm_vreg_debug_mask & RPM_VREG_DEBUG_FULL_REQUEST)) {
290 mask[REQ_SENT] = aggr->modified;
291 mask[REQ_PREV] = aggr->valid & ~aggr->modified;
292 } else if (sent && (rpm_vreg_debug_mask & RPM_VREG_DEBUG_REQUEST)) {
293 mask[REQ_SENT] = aggr->modified;
294 }
295
296 if (!(mask[REQ_SENT] | mask[REQ_PREV]))
297 return;
298
299 if (set == RPM_SET_SLEEP && !rpm_vreg->sleep_request_sent) {
300 mask[REQ_CACHED] = mask[REQ_SENT] | mask[REQ_PREV];
301 mask[REQ_SENT] = 0;
302 mask[REQ_PREV] = 0;
303 }
304
305 pos += scnprintf(buf + pos, buflen - pos, "%s%s: ",
306 KERN_INFO, __func__);
307
308 pos += scnprintf(buf + pos, buflen - pos, "%s %u (%s): s=%s",
309 rpm_vreg->resource_name, rpm_vreg->resource_id,
310 regulator->rdesc.name,
311 (set == RPM_SET_ACTIVE ? "act" : "slp"));
312
313 for (i = 0; i < REQ_TYPES; i++) {
314 if (mask[i])
315 pos += scnprintf(buf + pos, buflen - pos, "; %s: ",
316 req_names[i]);
317
318 first = true;
319 for (j = 0; j < RPM_REGULATOR_PARAM_MAX; j++) {
320 if (mask[i] & BIT(j)) {
321 pos += scnprintf(buf + pos, buflen - pos,
322 "%s%s=%u", (first ? "" : ", "),
323 params[j].name, aggr->param[j]);
324 first = false;
325 }
326 }
327 }
328
329 pos += scnprintf(buf + pos, buflen - pos, "\n");
330 printk(buf);
331}
332
333#define RPM_VREG_SET_PARAM(_regulator, _param, _val) \
334{ \
335 (_regulator)->req.param[RPM_REGULATOR_PARAM_##_param] = _val; \
336 (_regulator)->req.modified |= BIT(RPM_REGULATOR_PARAM_##_param); \
337} \
338
339static int rpm_vreg_add_kvp_to_request(struct rpm_vreg *rpm_vreg,
340 const u32 *param, int idx, u32 set)
341{
342 struct msm_rpm_request *handle;
343
344 handle = (set == RPM_SET_ACTIVE ? rpm_vreg->handle_active
345 : rpm_vreg->handle_sleep);
346
347 if (rpm_vreg->allow_atomic)
348 return msm_rpm_add_kvp_data_noirq(handle, params[idx].key,
349 (u8 *)&param[idx], 4);
350 else
351 return msm_rpm_add_kvp_data(handle, params[idx].key,
352 (u8 *)&param[idx], 4);
353}
354
355static void rpm_vreg_check_modified_requests(const u32 *prev_param,
356 const u32 *param, u32 prev_valid, u32 *modified)
357{
358 u32 value_changed = 0;
359 int i;
360
361 for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++) {
362 if (param[i] != prev_param[i])
363 value_changed |= BIT(i);
364 }
365
366 /*
367 * Only keep bits that are for changed parameters or previously
368 * invalid parameters.
369 */
370 *modified &= value_changed | ~prev_valid;
371}
372
373static int rpm_vreg_add_modified_requests(struct rpm_regulator *regulator,
374 u32 set, const u32 *param, u32 modified)
375{
376 struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;
377 int rc = 0;
378 int i;
379
380 for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++) {
381 /* Only send requests for modified parameters. */
382 if (modified & BIT(i)) {
383 rc = rpm_vreg_add_kvp_to_request(rpm_vreg, param, i,
384 set);
385 if (rc) {
386 vreg_err(regulator,
387 "add KVP failed: %s %u; %s, rc=%d\n",
388 rpm_vreg->resource_name,
389 rpm_vreg->resource_id, params[i].name,
390 rc);
391 return rc;
392 }
393 }
394 }
395
396 return rc;
397}
398
399static int rpm_vreg_send_request(struct rpm_regulator *regulator, u32 set)
400{
401 struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;
402 struct msm_rpm_request *handle
403 = (set == RPM_SET_ACTIVE ? rpm_vreg->handle_active
404 : rpm_vreg->handle_sleep);
405 int rc;
406
407 if (rpm_vreg->allow_atomic)
408 rc = msm_rpm_wait_for_ack_noirq(msm_rpm_send_request_noirq(
409 handle));
410 else
411 rc = msm_rpm_wait_for_ack(msm_rpm_send_request(handle));
412
413 if (rc)
414 vreg_err(regulator, "msm rpm send failed: %s %u; set=%s, "
415 "rc=%d\n", rpm_vreg->resource_name,
416 rpm_vreg->resource_id,
417 (set == RPM_SET_ACTIVE ? "act" : "slp"), rc);
418
419 return rc;
420}
421
David Collinsd1247e02013-03-05 11:15:30 -0800422#define RPM_VREG_AGGR_MIN(_idx, _param_aggr, _param_reg) \
423{ \
424 _param_aggr[RPM_REGULATOR_PARAM_##_idx] \
425 = min(_param_aggr[RPM_REGULATOR_PARAM_##_idx], \
426 _param_reg[RPM_REGULATOR_PARAM_##_idx]); \
427}
428
David Collinsc7642322012-04-04 10:19:12 -0700429#define RPM_VREG_AGGR_MAX(_idx, _param_aggr, _param_reg) \
430{ \
431 _param_aggr[RPM_REGULATOR_PARAM_##_idx] \
432 = max(_param_aggr[RPM_REGULATOR_PARAM_##_idx], \
433 _param_reg[RPM_REGULATOR_PARAM_##_idx]); \
434}
435
436#define RPM_VREG_AGGR_SUM(_idx, _param_aggr, _param_reg) \
437{ \
438 _param_aggr[RPM_REGULATOR_PARAM_##_idx] \
439 += _param_reg[RPM_REGULATOR_PARAM_##_idx]; \
440}
441
442#define RPM_VREG_AGGR_OR(_idx, _param_aggr, _param_reg) \
443{ \
444 _param_aggr[RPM_REGULATOR_PARAM_##_idx] \
445 |= _param_reg[RPM_REGULATOR_PARAM_##_idx]; \
446}
447
448/*
David Collinsc7642322012-04-04 10:19:12 -0700449 * Aggregation is performed on each parameter based on the way that the RPM
450 * aggregates that type internally between RPM masters.
451 */
452static void rpm_vreg_aggregate_params(u32 *param_aggr, const u32 *param_reg)
453{
454 RPM_VREG_AGGR_MAX(ENABLE, param_aggr, param_reg);
455 RPM_VREG_AGGR_MAX(VOLTAGE, param_aggr, param_reg);
456 RPM_VREG_AGGR_SUM(CURRENT, param_aggr, param_reg);
457 RPM_VREG_AGGR_MAX(MODE_LDO, param_aggr, param_reg);
458 RPM_VREG_AGGR_MAX(MODE_SMPS, param_aggr, param_reg);
459 RPM_VREG_AGGR_OR(PIN_CTRL_ENABLE, param_aggr, param_reg);
460 RPM_VREG_AGGR_OR(PIN_CTRL_MODE, param_aggr, param_reg);
David Collinsd1247e02013-03-05 11:15:30 -0800461 RPM_VREG_AGGR_MIN(FREQUENCY, param_aggr, param_reg);
David Collinsc7642322012-04-04 10:19:12 -0700462 RPM_VREG_AGGR_MAX(HEAD_ROOM, param_aggr, param_reg);
463 RPM_VREG_AGGR_MAX(QUIET_MODE, param_aggr, param_reg);
464 RPM_VREG_AGGR_MAX(FREQ_REASON, param_aggr, param_reg);
David Collins4208ce32012-06-15 13:33:13 -0700465 RPM_VREG_AGGR_MAX(CORNER, param_aggr, param_reg);
David Collins85b71992012-07-18 12:00:14 -0700466 RPM_VREG_AGGR_MAX(BYPASS, param_aggr, param_reg);
David Collins9deea5b2013-03-05 10:16:01 -0800467 RPM_VREG_AGGR_MAX(FLOOR_CORNER, param_aggr, param_reg);
David Collinsc7642322012-04-04 10:19:12 -0700468}
469
470static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)
471{
472 struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;
473 u32 param_active[RPM_REGULATOR_PARAM_MAX];
474 u32 param_sleep[RPM_REGULATOR_PARAM_MAX];
475 u32 modified_active, modified_sleep;
476 struct rpm_regulator *reg;
477 bool sleep_set_differs = false;
478 bool send_active = false;
479 bool send_sleep = false;
480 int rc = 0;
481 int i;
482
483 memset(param_active, 0, sizeof(param_active));
484 memset(param_sleep, 0, sizeof(param_sleep));
485 modified_active = rpm_vreg->aggr_req_active.modified;
486 modified_sleep = rpm_vreg->aggr_req_sleep.modified;
487
488 /*
489 * Aggregate all of the requests for this regulator in both active
490 * and sleep sets.
491 */
492 list_for_each_entry(reg, &rpm_vreg->reg_list, list) {
493 if (reg->set_active) {
494 rpm_vreg_aggregate_params(param_active, reg->req.param);
495 modified_active |= reg->req.modified;
496 }
497 if (reg->set_sleep) {
498 rpm_vreg_aggregate_params(param_sleep, reg->req.param);
499 modified_sleep |= reg->req.modified;
500 }
501 }
502
503 /*
504 * Check if the aggregated sleep set parameter values differ from the
505 * aggregated active set parameter values.
506 */
507 if (!rpm_vreg->sleep_request_sent) {
508 for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++) {
509 if ((param_active[i] != param_sleep[i])
510 && (modified_sleep & BIT(i))) {
511 sleep_set_differs = true;
512 break;
513 }
514 }
515 }
516
517 /* Add KVPs to the active set RPM request if they have new values. */
518 rpm_vreg_check_modified_requests(rpm_vreg->aggr_req_active.param,
519 param_active, rpm_vreg->aggr_req_active.valid,
520 &modified_active);
521 rc = rpm_vreg_add_modified_requests(regulator, RPM_SET_ACTIVE,
522 param_active, modified_active);
523 if (rc)
524 return rc;
525 send_active = modified_active;
526
527 /*
528 * Sleep set configurations are only sent if they differ from the
529 * active set values. This is because the active set values will take
530 * effect during rpm assisted power collapse in the absence of sleep set
531 * values.
532 *
533 * However, once a sleep set request is sent for a given regulator,
534 * additional sleep set requests must be sent in the future even if they
535 * match the corresponding active set requests.
536 */
537 if (rpm_vreg->sleep_request_sent || sleep_set_differs) {
538 /* Add KVPs to the sleep set RPM request if they are new. */
539 rpm_vreg_check_modified_requests(rpm_vreg->aggr_req_sleep.param,
540 param_sleep, rpm_vreg->aggr_req_sleep.valid,
541 &modified_sleep);
542 rc = rpm_vreg_add_modified_requests(regulator, RPM_SET_SLEEP,
543 param_sleep, modified_sleep);
544 if (rc)
545 return rc;
546 send_sleep = modified_sleep;
547 }
548
549 /* Send active set request to the RPM if it contains new KVPs. */
550 if (send_active) {
551 rc = rpm_vreg_send_request(regulator, RPM_SET_ACTIVE);
552 if (rc)
553 return rc;
554 rpm_vreg->aggr_req_active.valid |= modified_active;
555 }
556 /* Store the results of the aggregation. */
557 rpm_vreg->aggr_req_active.modified = modified_active;
558 memcpy(rpm_vreg->aggr_req_active.param, param_active,
559 sizeof(param_active));
560
561 /* Handle debug printing of the active set request. */
562 rpm_regulator_req(regulator, RPM_SET_ACTIVE, send_active);
563 if (send_active)
564 rpm_vreg->aggr_req_active.modified = 0;
565
566 /* Send sleep set request to the RPM if it contains new KVPs. */
567 if (send_sleep) {
568 rc = rpm_vreg_send_request(regulator, RPM_SET_SLEEP);
569 if (rc)
570 return rc;
571 else
572 rpm_vreg->sleep_request_sent = true;
573 rpm_vreg->aggr_req_sleep.valid |= modified_sleep;
574 }
575 /* Store the results of the aggregation. */
576 rpm_vreg->aggr_req_sleep.modified = modified_sleep;
577 memcpy(rpm_vreg->aggr_req_sleep.param, param_sleep,
578 sizeof(param_sleep));
579
580 /* Handle debug printing of the sleep set request. */
581 rpm_regulator_req(regulator, RPM_SET_SLEEP, send_sleep);
582 if (send_sleep)
583 rpm_vreg->aggr_req_sleep.modified = 0;
584
585 /*
586 * Loop over all requests for this regulator to update the valid and
587 * modified values for use in future aggregation.
588 */
589 list_for_each_entry(reg, &rpm_vreg->reg_list, list) {
590 reg->req.valid |= reg->req.modified;
591 reg->req.modified = 0;
592 }
593
594 return rc;
595}
596
597static int rpm_vreg_is_enabled(struct regulator_dev *rdev)
598{
599 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
600
601 return reg->req.param[RPM_REGULATOR_PARAM_ENABLE];
602}
603
604static int rpm_vreg_enable(struct regulator_dev *rdev)
605{
606 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
607 int rc;
608 u32 prev_enable;
609
610 rpm_vreg_lock(reg->rpm_vreg);
611
612 prev_enable = reg->req.param[RPM_REGULATOR_PARAM_ENABLE];
613 RPM_VREG_SET_PARAM(reg, ENABLE, 1);
614 rc = rpm_vreg_aggregate_requests(reg);
615 if (rc) {
616 vreg_err(reg, "enable failed, rc=%d", rc);
617 RPM_VREG_SET_PARAM(reg, ENABLE, prev_enable);
618 }
619
620 rpm_vreg_unlock(reg->rpm_vreg);
621
622 return rc;
623}
624
625static int rpm_vreg_disable(struct regulator_dev *rdev)
626{
627 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
628 int rc;
629 u32 prev_enable;
630
631 rpm_vreg_lock(reg->rpm_vreg);
632
633 prev_enable = reg->req.param[RPM_REGULATOR_PARAM_ENABLE];
634 RPM_VREG_SET_PARAM(reg, ENABLE, 0);
635 rc = rpm_vreg_aggregate_requests(reg);
636 if (rc) {
637 vreg_err(reg, "enable failed, rc=%d", rc);
638 RPM_VREG_SET_PARAM(reg, ENABLE, prev_enable);
639 }
640
641 rpm_vreg_unlock(reg->rpm_vreg);
642
643 return rc;
644}
645
646static int rpm_vreg_set_voltage(struct regulator_dev *rdev, int min_uV,
647 int max_uV, unsigned *selector)
648{
649 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
650 int rc = 0;
651 u32 prev_voltage;
652
653 rpm_vreg_lock(reg->rpm_vreg);
654
655 prev_voltage = reg->req.param[RPM_REGULATOR_PARAM_VOLTAGE];
656 RPM_VREG_SET_PARAM(reg, VOLTAGE, min_uV);
657
David Collins409a9fa2013-03-05 10:54:25 -0800658 /*
659 * Only send a new voltage if the regulator is currently enabled or
660 * if the regulator has been configured to always send voltage updates.
661 */
662 if (reg->always_send_voltage
663 || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
David Collinsc7642322012-04-04 10:19:12 -0700664 rc = rpm_vreg_aggregate_requests(reg);
665
666 if (rc) {
667 vreg_err(reg, "set voltage failed, rc=%d", rc);
668 RPM_VREG_SET_PARAM(reg, VOLTAGE, prev_voltage);
669 }
670
671 rpm_vreg_unlock(reg->rpm_vreg);
672
673 return rc;
674}
675
676static int rpm_vreg_get_voltage(struct regulator_dev *rdev)
677{
678 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
679 int uV;
680
681 uV = reg->req.param[RPM_REGULATOR_PARAM_VOLTAGE];
682 if (uV == 0)
683 uV = VOLTAGE_UNKNOWN;
684
685 return uV;
686}
687
David Collins4208ce32012-06-15 13:33:13 -0700688static int rpm_vreg_set_voltage_corner(struct regulator_dev *rdev, int min_uV,
689 int max_uV, unsigned *selector)
690{
691 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
692 int rc = 0;
693 int corner;
694 u32 prev_corner;
695
696 /*
697 * Translate from values which work as inputs in the
698 * regulator_set_voltage function to the actual corner values
699 * sent to the RPM.
700 */
David Collins71c18992012-07-18 11:25:24 -0700701 corner = min_uV - RPM_REGULATOR_CORNER_NONE;
David Collins4208ce32012-06-15 13:33:13 -0700702
703 if (corner < params[RPM_REGULATOR_PARAM_CORNER].min
704 || corner > params[RPM_REGULATOR_PARAM_CORNER].max) {
705 vreg_err(reg, "corner=%d is not within allowed range: [%u, %u]\n",
706 corner, params[RPM_REGULATOR_PARAM_CORNER].min,
707 params[RPM_REGULATOR_PARAM_CORNER].max);
708 return -EINVAL;
709 }
710
711 rpm_vreg_lock(reg->rpm_vreg);
712
713 prev_corner = reg->req.param[RPM_REGULATOR_PARAM_CORNER];
714 RPM_VREG_SET_PARAM(reg, CORNER, corner);
715
David Collins409a9fa2013-03-05 10:54:25 -0800716 /*
717 * Only send a new voltage corner if the regulator is currently enabled
718 * or if the regulator has been configured to always send voltage
719 * updates.
720 */
721 if (reg->always_send_voltage
722 || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
David Collins4208ce32012-06-15 13:33:13 -0700723 rc = rpm_vreg_aggregate_requests(reg);
724
725 if (rc) {
726 vreg_err(reg, "set voltage corner failed, rc=%d", rc);
727 RPM_VREG_SET_PARAM(reg, CORNER, prev_corner);
728 }
729
730 rpm_vreg_unlock(reg->rpm_vreg);
731
732 return rc;
733}
734
735static int rpm_vreg_get_voltage_corner(struct regulator_dev *rdev)
736{
737 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
738
739 return reg->req.param[RPM_REGULATOR_PARAM_CORNER]
David Collins71c18992012-07-18 11:25:24 -0700740 + RPM_REGULATOR_CORNER_NONE;
David Collins4208ce32012-06-15 13:33:13 -0700741}
742
David Collins9deea5b2013-03-05 10:16:01 -0800743static int rpm_vreg_set_voltage_floor_corner(struct regulator_dev *rdev,
744 int min_uV, int max_uV, unsigned *selector)
745{
746 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
747 int rc = 0;
748 int corner;
749 u32 prev_corner;
750
751 /*
752 * Translate from values which work as inputs in the
753 * regulator_set_voltage function to the actual corner values
754 * sent to the RPM.
755 */
756 corner = min_uV - RPM_REGULATOR_CORNER_NONE;
757
758 if (corner < params[RPM_REGULATOR_PARAM_FLOOR_CORNER].min
759 || corner > params[RPM_REGULATOR_PARAM_FLOOR_CORNER].max) {
760 vreg_err(reg, "corner=%d is not within allowed range: [%u, %u]\n",
761 corner, params[RPM_REGULATOR_PARAM_FLOOR_CORNER].min,
762 params[RPM_REGULATOR_PARAM_FLOOR_CORNER].max);
763 return -EINVAL;
764 }
765
766 rpm_vreg_lock(reg->rpm_vreg);
767
768 prev_corner = reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER];
769 RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, corner);
770
David Collins409a9fa2013-03-05 10:54:25 -0800771 /*
772 * Only send a new voltage floor corner if the regulator is currently
773 * enabled or if the regulator has been configured to always send
774 * voltage updates.
775 */
776 if (reg->always_send_voltage
777 || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
David Collins9deea5b2013-03-05 10:16:01 -0800778 rc = rpm_vreg_aggregate_requests(reg);
779
780 if (rc) {
781 vreg_err(reg, "set voltage corner failed, rc=%d", rc);
782 RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, prev_corner);
783 }
784
785 rpm_vreg_unlock(reg->rpm_vreg);
786
787 return rc;
788}
789
790static int rpm_vreg_get_voltage_floor_corner(struct regulator_dev *rdev)
791{
792 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
793
794 return reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER]
795 + RPM_REGULATOR_CORNER_NONE;
796}
797
David Collinsc7642322012-04-04 10:19:12 -0700798static int rpm_vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
799{
800 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
801 int rc = 0;
802 u32 prev_current;
803 int prev_uA;
804
805 rpm_vreg_lock(reg->rpm_vreg);
806
807 prev_current = reg->req.param[RPM_REGULATOR_PARAM_CURRENT];
808 prev_uA = MILLI_TO_MICRO(prev_current);
809
810 if (mode == REGULATOR_MODE_NORMAL) {
811 /* Make sure that request current is in HPM range. */
812 if (prev_uA < rpm_vreg_hpm_min_uA(reg->rpm_vreg))
813 RPM_VREG_SET_PARAM(reg, CURRENT,
814 MICRO_TO_MILLI(rpm_vreg_hpm_min_uA(reg->rpm_vreg)));
815 } else if (REGULATOR_MODE_IDLE) {
816 /* Make sure that request current is in LPM range. */
817 if (prev_uA > rpm_vreg_lpm_max_uA(reg->rpm_vreg))
818 RPM_VREG_SET_PARAM(reg, CURRENT,
819 MICRO_TO_MILLI(rpm_vreg_lpm_max_uA(reg->rpm_vreg)));
820 } else {
821 vreg_err(reg, "invalid mode: %u\n", mode);
822 rpm_vreg_unlock(reg->rpm_vreg);
823 return -EINVAL;
824 }
825
David Collins409a9fa2013-03-05 10:54:25 -0800826 /*
827 * Only send a new load current value if the regulator is currently
828 * enabled or if the regulator has been configured to always send
829 * current updates.
830 */
831 if (reg->always_send_current
832 || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
David Collinsc7642322012-04-04 10:19:12 -0700833 rc = rpm_vreg_aggregate_requests(reg);
834
835 if (rc) {
836 vreg_err(reg, "set mode failed, rc=%d", rc);
837 RPM_VREG_SET_PARAM(reg, CURRENT, prev_current);
838 }
839
840 rpm_vreg_unlock(reg->rpm_vreg);
841
842 return rc;
843}
844
845static unsigned int rpm_vreg_get_mode(struct regulator_dev *rdev)
846{
847 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
848
849 return (reg->req.param[RPM_REGULATOR_PARAM_CURRENT]
850 >= MICRO_TO_MILLI(reg->rpm_vreg->hpm_min_load))
851 ? REGULATOR_MODE_NORMAL : REGULATOR_MODE_IDLE;
852}
853
854static unsigned int rpm_vreg_get_optimum_mode(struct regulator_dev *rdev,
855 int input_uV, int output_uV, int load_uA)
856{
857 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
858 u32 load_mA;
859
860 load_uA += reg->system_load;
861
862 load_mA = MICRO_TO_MILLI(load_uA);
863 if (load_mA > params[RPM_REGULATOR_PARAM_CURRENT].max)
864 load_mA = params[RPM_REGULATOR_PARAM_CURRENT].max;
865
866 rpm_vreg_lock(reg->rpm_vreg);
867 RPM_VREG_SET_PARAM(reg, CURRENT, MICRO_TO_MILLI(load_uA));
868 rpm_vreg_unlock(reg->rpm_vreg);
869
870 return (load_uA >= reg->rpm_vreg->hpm_min_load)
871 ? REGULATOR_MODE_NORMAL : REGULATOR_MODE_IDLE;
872}
873
874static int rpm_vreg_enable_time(struct regulator_dev *rdev)
875{
876 struct rpm_regulator *reg = rdev_get_drvdata(rdev);
877
878 return reg->rpm_vreg->enable_time;
879}
880
881/**
882 * rpm_regulator_get() - lookup and obtain a handle to an RPM regulator
883 * @dev: device for regulator consumer
884 * @supply: supply name
885 *
886 * Returns a struct rpm_regulator corresponding to the regulator producer,
887 * or ERR_PTR() containing errno.
888 *
889 * This function may only be called from nonatomic context.
890 */
891struct rpm_regulator *rpm_regulator_get(struct device *dev, const char *supply)
892{
893 struct rpm_regulator *framework_reg;
894 struct rpm_regulator *priv_reg = NULL;
895 struct regulator *regulator;
896 struct rpm_vreg *rpm_vreg;
897
898 regulator = regulator_get(dev, supply);
David Collins29ba0282012-06-18 10:01:52 -0700899 if (IS_ERR(regulator)) {
900 pr_err("could not find regulator for: dev=%s, supply=%s, rc=%ld\n",
901 (dev ? dev_name(dev) : ""), (supply ? supply : ""),
902 PTR_ERR(regulator));
903 return ERR_CAST(regulator);
David Collinsc7642322012-04-04 10:19:12 -0700904 }
905
906 framework_reg = regulator_get_drvdata(regulator);
907 if (framework_reg == NULL) {
908 pr_err("regulator structure not found.\n");
909 regulator_put(regulator);
910 return ERR_PTR(-ENODEV);
911 }
912 regulator_put(regulator);
913
914 rpm_vreg = framework_reg->rpm_vreg;
915
916 priv_reg = kzalloc(sizeof(struct rpm_regulator), GFP_KERNEL);
917 if (priv_reg == NULL) {
918 vreg_err(framework_reg, "could not allocate memory for "
919 "regulator\n");
920 rpm_vreg_unlock(rpm_vreg);
921 return ERR_PTR(-ENOMEM);
922 }
923
924 /*
925 * Allocate a regulator_dev struct so that framework callback functions
926 * can be called from the private API functions.
927 */
928 priv_reg->rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
929 if (priv_reg->rdev == NULL) {
930 vreg_err(framework_reg, "could not allocate memory for "
931 "regulator_dev\n");
932 kfree(priv_reg);
933 rpm_vreg_unlock(rpm_vreg);
934 return ERR_PTR(-ENOMEM);
935 }
936 priv_reg->rdev->reg_data = priv_reg;
937 priv_reg->rpm_vreg = rpm_vreg;
938 priv_reg->rdesc.name = framework_reg->rdesc.name;
David Collins4208ce32012-06-15 13:33:13 -0700939 priv_reg->rdesc.ops = framework_reg->rdesc.ops;
David Collinsc7642322012-04-04 10:19:12 -0700940 priv_reg->set_active = framework_reg->set_active;
941 priv_reg->set_sleep = framework_reg->set_sleep;
942 priv_reg->min_uV = framework_reg->min_uV;
943 priv_reg->max_uV = framework_reg->max_uV;
944 priv_reg->system_load = framework_reg->system_load;
945
946 might_sleep_if(!rpm_vreg->allow_atomic);
947 rpm_vreg_lock(rpm_vreg);
948 list_add(&priv_reg->list, &rpm_vreg->reg_list);
949 rpm_vreg_unlock(rpm_vreg);
950
951 return priv_reg;
952}
953EXPORT_SYMBOL_GPL(rpm_regulator_get);
954
955static int rpm_regulator_check_input(struct rpm_regulator *regulator)
956{
David Collins29ba0282012-06-18 10:01:52 -0700957 if (IS_ERR_OR_NULL(regulator) || regulator->rpm_vreg == NULL) {
David Collinsc7642322012-04-04 10:19:12 -0700958 pr_err("invalid rpm_regulator pointer\n");
959 return -EINVAL;
960 }
961
962 might_sleep_if(!regulator->rpm_vreg->allow_atomic);
963
964 return 0;
965}
966
967/**
968 * rpm_regulator_put() - free the RPM regulator handle
969 * @regulator: RPM regulator handle
970 *
971 * Parameter reaggregation does not take place when rpm_regulator_put is called.
972 * Therefore, regulator enable state and voltage must be configured
973 * appropriately before calling rpm_regulator_put.
974 *
975 * This function may be called from either atomic or nonatomic context. If this
976 * function is called from atomic context, then the regulator being operated on
977 * must be configured via device tree with qcom,allow-atomic == 1.
978 */
979void rpm_regulator_put(struct rpm_regulator *regulator)
980{
981 struct rpm_vreg *rpm_vreg;
982 int rc = rpm_regulator_check_input(regulator);
983
984 if (rc)
985 return;
986
987 rpm_vreg = regulator->rpm_vreg;
988
989 might_sleep_if(!rpm_vreg->allow_atomic);
990 rpm_vreg_lock(rpm_vreg);
991 list_del(&regulator->list);
992 rpm_vreg_unlock(rpm_vreg);
993
994 kfree(regulator->rdev);
995 kfree(regulator);
996}
997EXPORT_SYMBOL_GPL(rpm_regulator_put);
998
999/**
1000 * rpm_regulator_enable() - enable regulator output
1001 * @regulator: RPM regulator handle
1002 *
1003 * Returns 0 on success or errno on failure.
1004 *
1005 * This function may be called from either atomic or nonatomic context. If this
1006 * function is called from atomic context, then the regulator being operated on
1007 * must be configured via device tree with qcom,allow-atomic == 1.
1008 */
1009int rpm_regulator_enable(struct rpm_regulator *regulator)
1010{
1011 int rc = rpm_regulator_check_input(regulator);
1012
1013 if (rc)
1014 return rc;
1015
1016 return rpm_vreg_enable(regulator->rdev);
1017}
1018EXPORT_SYMBOL_GPL(rpm_regulator_enable);
1019
1020/**
1021 * rpm_regulator_disable() - disable regulator output
1022 * @regulator: RPM regulator handle
1023 *
1024 * Returns 0 on success or errno on failure.
1025 *
1026 * The enable state of the regulator is determined by aggregating the requests
1027 * of all consumers. Therefore, it is possible that the regulator will remain
1028 * enabled even after rpm_regulator_disable is called.
1029 *
1030 * This function may be called from either atomic or nonatomic context. If this
1031 * function is called from atomic context, then the regulator being operated on
1032 * must be configured via device tree with qcom,allow-atomic == 1.
1033 */
1034int rpm_regulator_disable(struct rpm_regulator *regulator)
1035{
1036 int rc = rpm_regulator_check_input(regulator);
1037
1038 if (rc)
1039 return rc;
1040
1041 return rpm_vreg_disable(regulator->rdev);
1042}
1043EXPORT_SYMBOL_GPL(rpm_regulator_disable);
1044
1045/**
1046 * rpm_regulator_set_voltage() - set regulator output voltage
1047 * @regulator: RPM regulator handle
1048 * @min_uV: minimum required voltage in uV
1049 * @max_uV: maximum acceptable voltage in uV
1050 *
1051 * Sets a voltage regulator to the desired output voltage. This can be set
1052 * while the regulator is disabled or enabled. If the regulator is enabled then
1053 * the voltage will change to the new value immediately; otherwise, if the
1054 * regulator is disabled, then the regulator will output at the new voltage when
1055 * enabled.
1056 *
1057 * The min_uV to max_uV voltage range requested must intersect with the
1058 * voltage constraint range configured for the regulator.
1059 *
1060 * Returns 0 on success or errno on failure.
1061 *
1062 * The final voltage value that is sent to the RPM is aggregated based upon the
1063 * values requested by all consumers of the regulator. This corresponds to the
1064 * maximum min_uV value.
1065 *
1066 * This function may be called from either atomic or nonatomic context. If this
1067 * function is called from atomic context, then the regulator being operated on
1068 * must be configured via device tree with qcom,allow-atomic == 1.
1069 */
1070int rpm_regulator_set_voltage(struct rpm_regulator *regulator, int min_uV,
1071 int max_uV)
1072{
1073 int rc = rpm_regulator_check_input(regulator);
1074 int uV = min_uV;
1075
1076 if (rc)
1077 return rc;
1078
1079 if (regulator->rpm_vreg->regulator_type == RPM_REGULATOR_SMD_TYPE_VS) {
1080 vreg_err(regulator, "unsupported regulator type: %d\n",
1081 regulator->rpm_vreg->regulator_type);
1082 return -EINVAL;
1083 }
1084
1085 if (min_uV > max_uV) {
1086 vreg_err(regulator, "min_uV=%d must be less than max_uV=%d\n",
1087 min_uV, max_uV);
1088 return -EINVAL;
1089 }
1090
1091 if (uV < regulator->min_uV && max_uV >= regulator->min_uV)
1092 uV = regulator->min_uV;
1093
1094 if (uV < regulator->min_uV || uV > regulator->max_uV) {
1095 vreg_err(regulator, "request v=[%d, %d] is outside allowed "
1096 "v=[%d, %d]\n", min_uV, max_uV, regulator->min_uV,
1097 regulator->max_uV);
1098 return -EINVAL;
1099 }
1100
David Collins4208ce32012-06-15 13:33:13 -07001101 return regulator->rdesc.ops->set_voltage(regulator->rdev, uV, uV, NULL);
David Collinsc7642322012-04-04 10:19:12 -07001102}
1103EXPORT_SYMBOL_GPL(rpm_regulator_set_voltage);
1104
David Collinsf0a12792013-03-26 14:49:12 -07001105/**
1106 * rpm_regulator_set_mode() - set regulator operating mode
1107 * @regulator: RPM regulator handle
1108 * @mode: operating mode requested for the regulator
1109 *
1110 * Requests that the mode of the regulator be set to the mode specified. This
1111 * parameter is aggregated using a max function such that AUTO < IPEAK < HPM.
1112 *
1113 * Returns 0 on success or errno on failure.
1114 */
1115int rpm_regulator_set_mode(struct rpm_regulator *regulator,
1116 enum rpm_regulator_mode mode)
1117{
1118 int index = 0;
1119 u32 new_mode, prev_mode;
1120 int rc;
1121
1122 rc = rpm_regulator_check_input(regulator);
1123 if (rc)
1124 return rc;
1125
1126 if (mode < 0 || mode >= ARRAY_SIZE(mode_mapping)) {
1127 vreg_err(regulator, "invalid mode requested: %d\n", mode);
1128 return -EINVAL;
1129 }
1130
1131 switch (regulator->rpm_vreg->regulator_type) {
1132 case RPM_REGULATOR_SMD_TYPE_SMPS:
1133 index = RPM_REGULATOR_PARAM_MODE_SMPS;
1134 new_mode = mode_mapping[mode].smps_mode;
1135 break;
1136 case RPM_REGULATOR_SMD_TYPE_LDO:
1137 index = RPM_REGULATOR_PARAM_MODE_LDO;
1138 new_mode = mode_mapping[mode].ldo_mode;
1139 break;
1140 default:
1141 vreg_err(regulator, "unsupported regulator type: %d\n",
1142 regulator->rpm_vreg->regulator_type);
1143 return -EINVAL;
1144 };
1145
1146 if (new_mode < params[index].min || new_mode > params[index].max) {
1147 vreg_err(regulator, "invalid mode requested: %d for type: %d\n",
1148 mode, regulator->rpm_vreg->regulator_type);
1149 return -EINVAL;
1150 }
1151
1152 rpm_vreg_lock(regulator->rpm_vreg);
1153
1154 prev_mode = regulator->req.param[index];
1155 regulator->req.param[index] = new_mode;
1156 regulator->req.modified |= BIT(index);
1157
1158 rc = rpm_vreg_aggregate_requests(regulator);
1159 if (rc) {
1160 vreg_err(regulator, "set mode failed, rc=%d", rc);
1161 regulator->req.param[index] = prev_mode;
1162 }
1163
1164 rpm_vreg_unlock(regulator->rpm_vreg);
1165
1166 return rc;
1167}
1168EXPORT_SYMBOL_GPL(rpm_regulator_set_mode);
1169
David Collinsc7642322012-04-04 10:19:12 -07001170static struct regulator_ops ldo_ops = {
1171 .enable = rpm_vreg_enable,
1172 .disable = rpm_vreg_disable,
1173 .is_enabled = rpm_vreg_is_enabled,
1174 .set_voltage = rpm_vreg_set_voltage,
1175 .get_voltage = rpm_vreg_get_voltage,
David Collinsc7642322012-04-04 10:19:12 -07001176 .set_mode = rpm_vreg_set_mode,
1177 .get_mode = rpm_vreg_get_mode,
1178 .get_optimum_mode = rpm_vreg_get_optimum_mode,
1179 .enable_time = rpm_vreg_enable_time,
1180};
1181
David Collins23c96cd2012-10-05 17:12:00 -07001182static struct regulator_ops ldo_corner_ops = {
1183 .enable = rpm_vreg_enable,
1184 .disable = rpm_vreg_disable,
1185 .is_enabled = rpm_vreg_is_enabled,
1186 .set_voltage = rpm_vreg_set_voltage_corner,
1187 .get_voltage = rpm_vreg_get_voltage_corner,
David Collins23c96cd2012-10-05 17:12:00 -07001188 .set_mode = rpm_vreg_set_mode,
1189 .get_mode = rpm_vreg_get_mode,
1190 .get_optimum_mode = rpm_vreg_get_optimum_mode,
1191 .enable_time = rpm_vreg_enable_time,
1192};
1193
David Collins9deea5b2013-03-05 10:16:01 -08001194static struct regulator_ops ldo_floor_corner_ops = {
1195 .enable = rpm_vreg_enable,
1196 .disable = rpm_vreg_disable,
1197 .is_enabled = rpm_vreg_is_enabled,
1198 .set_voltage = rpm_vreg_set_voltage_floor_corner,
1199 .get_voltage = rpm_vreg_get_voltage_floor_corner,
1200 .set_mode = rpm_vreg_set_mode,
1201 .get_mode = rpm_vreg_get_mode,
1202 .get_optimum_mode = rpm_vreg_get_optimum_mode,
1203 .enable_time = rpm_vreg_enable_time,
1204};
1205
David Collinsc7642322012-04-04 10:19:12 -07001206static struct regulator_ops smps_ops = {
1207 .enable = rpm_vreg_enable,
1208 .disable = rpm_vreg_disable,
1209 .is_enabled = rpm_vreg_is_enabled,
1210 .set_voltage = rpm_vreg_set_voltage,
1211 .get_voltage = rpm_vreg_get_voltage,
David Collinsc7642322012-04-04 10:19:12 -07001212 .set_mode = rpm_vreg_set_mode,
1213 .get_mode = rpm_vreg_get_mode,
1214 .get_optimum_mode = rpm_vreg_get_optimum_mode,
1215 .enable_time = rpm_vreg_enable_time,
1216};
1217
David Collins4208ce32012-06-15 13:33:13 -07001218static struct regulator_ops smps_corner_ops = {
1219 .enable = rpm_vreg_enable,
1220 .disable = rpm_vreg_disable,
1221 .is_enabled = rpm_vreg_is_enabled,
1222 .set_voltage = rpm_vreg_set_voltage_corner,
1223 .get_voltage = rpm_vreg_get_voltage_corner,
David Collins4208ce32012-06-15 13:33:13 -07001224 .set_mode = rpm_vreg_set_mode,
1225 .get_mode = rpm_vreg_get_mode,
1226 .get_optimum_mode = rpm_vreg_get_optimum_mode,
1227 .enable_time = rpm_vreg_enable_time,
1228};
1229
David Collins9deea5b2013-03-05 10:16:01 -08001230static struct regulator_ops smps_floor_corner_ops = {
1231 .enable = rpm_vreg_enable,
1232 .disable = rpm_vreg_disable,
1233 .is_enabled = rpm_vreg_is_enabled,
1234 .set_voltage = rpm_vreg_set_voltage_floor_corner,
1235 .get_voltage = rpm_vreg_get_voltage_floor_corner,
1236 .set_mode = rpm_vreg_set_mode,
1237 .get_mode = rpm_vreg_get_mode,
1238 .get_optimum_mode = rpm_vreg_get_optimum_mode,
1239 .enable_time = rpm_vreg_enable_time,
1240};
1241
David Collinsc7642322012-04-04 10:19:12 -07001242static struct regulator_ops switch_ops = {
1243 .enable = rpm_vreg_enable,
1244 .disable = rpm_vreg_disable,
1245 .is_enabled = rpm_vreg_is_enabled,
1246 .enable_time = rpm_vreg_enable_time,
1247};
1248
1249static struct regulator_ops ncp_ops = {
1250 .enable = rpm_vreg_enable,
1251 .disable = rpm_vreg_disable,
1252 .is_enabled = rpm_vreg_is_enabled,
1253 .set_voltage = rpm_vreg_set_voltage,
1254 .get_voltage = rpm_vreg_get_voltage,
David Collinsc7642322012-04-04 10:19:12 -07001255 .enable_time = rpm_vreg_enable_time,
1256};
1257
1258static struct regulator_ops *vreg_ops[] = {
1259 [RPM_REGULATOR_SMD_TYPE_LDO] = &ldo_ops,
1260 [RPM_REGULATOR_SMD_TYPE_SMPS] = &smps_ops,
1261 [RPM_REGULATOR_SMD_TYPE_VS] = &switch_ops,
1262 [RPM_REGULATOR_SMD_TYPE_NCP] = &ncp_ops,
1263};
1264
1265static int __devexit rpm_vreg_device_remove(struct platform_device *pdev)
1266{
1267 struct device *dev = &pdev->dev;
1268 struct rpm_regulator *reg;
1269
1270 reg = platform_get_drvdata(pdev);
1271 if (reg) {
1272 rpm_vreg_lock(reg->rpm_vreg);
1273 regulator_unregister(reg->rdev);
1274 list_del(&reg->list);
1275 kfree(reg);
1276 rpm_vreg_unlock(reg->rpm_vreg);
1277 } else {
1278 dev_err(dev, "%s: drvdata missing\n", __func__);
1279 return -EINVAL;
1280 }
1281
1282 platform_set_drvdata(pdev, NULL);
1283
1284 return 0;
1285}
1286
1287static int __devexit rpm_vreg_resource_remove(struct platform_device *pdev)
1288{
1289 struct device *dev = &pdev->dev;
1290 struct rpm_regulator *reg, *reg_temp;
1291 struct rpm_vreg *rpm_vreg;
1292
1293 rpm_vreg = platform_get_drvdata(pdev);
1294 if (rpm_vreg) {
1295 rpm_vreg_lock(rpm_vreg);
1296 list_for_each_entry_safe(reg, reg_temp, &rpm_vreg->reg_list,
1297 list) {
1298 /* Only touch data for private consumers. */
1299 if (reg->rdev->desc == NULL) {
1300 list_del(&reg->list);
1301 kfree(reg->rdev);
1302 kfree(reg);
1303 } else {
1304 dev_err(dev, "%s: not all child devices have "
1305 "been removed\n", __func__);
1306 }
1307 }
1308 rpm_vreg_unlock(rpm_vreg);
1309
1310 msm_rpm_free_request(rpm_vreg->handle_active);
1311 msm_rpm_free_request(rpm_vreg->handle_sleep);
1312
1313 kfree(rpm_vreg);
1314 } else {
1315 dev_err(dev, "%s: drvdata missing\n", __func__);
1316 return -EINVAL;
1317 }
1318
1319 platform_set_drvdata(pdev, NULL);
1320
1321 return 0;
1322}
1323
1324/*
1325 * This probe is called for child rpm-regulator devices which have
1326 * properties which are required to configure individual regulator
1327 * framework regulators for a given RPM regulator resource.
1328 */
1329static int __devinit rpm_vreg_device_probe(struct platform_device *pdev)
1330{
1331 struct device *dev = &pdev->dev;
1332 struct device_node *node = dev->of_node;
1333 struct regulator_init_data *init_data;
1334 struct rpm_vreg *rpm_vreg;
1335 struct rpm_regulator *reg;
1336 int rc = 0;
1337 int i, regulator_type;
1338 u32 val;
1339
1340 if (!dev->of_node) {
1341 dev_err(dev, "%s: device tree information missing\n", __func__);
1342 return -ENODEV;
1343 }
1344
1345 if (pdev->dev.parent == NULL) {
1346 dev_err(dev, "%s: parent device missing\n", __func__);
1347 return -ENODEV;
1348 }
1349
1350 rpm_vreg = dev_get_drvdata(pdev->dev.parent);
1351 if (rpm_vreg == NULL) {
1352 dev_err(dev, "%s: rpm_vreg not found in parent device\n",
1353 __func__);
1354 return -ENODEV;
1355 }
1356
1357 reg = kzalloc(sizeof(struct rpm_regulator), GFP_KERNEL);
1358 if (reg == NULL) {
1359 dev_err(dev, "%s: could not allocate memory for reg\n",
1360 __func__);
1361 return -ENOMEM;
1362 }
1363
1364 regulator_type = rpm_vreg->regulator_type;
1365 reg->rpm_vreg = rpm_vreg;
1366 reg->rdesc.ops = vreg_ops[regulator_type];
1367 reg->rdesc.owner = THIS_MODULE;
1368 reg->rdesc.type = REGULATOR_VOLTAGE;
1369
David Collins4208ce32012-06-15 13:33:13 -07001370 /*
1371 * Switch to voltage corner regulator ops if qcom,use-voltage-corner
David Collins23c96cd2012-10-05 17:12:00 -07001372 * is specified in the device node (SMPS and LDO only).
David Collins4208ce32012-06-15 13:33:13 -07001373 */
David Collins23c96cd2012-10-05 17:12:00 -07001374 if (of_property_read_bool(node, "qcom,use-voltage-corner")) {
David Collins9deea5b2013-03-05 10:16:01 -08001375 if (of_property_read_bool(node,
1376 "qcom,use-voltage-floor-corner")) {
1377 dev_err(dev, "%s: invalid properties: both qcom,use-voltage-corner and qcom,use-voltage-floor-corner specified\n",
1378 __func__);
1379 goto fail_free_reg;
1380 }
1381
David Collins23c96cd2012-10-05 17:12:00 -07001382 if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
1383 reg->rdesc.ops = &smps_corner_ops;
1384 else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
1385 reg->rdesc.ops = &ldo_corner_ops;
David Collins9deea5b2013-03-05 10:16:01 -08001386 } else if (of_property_read_bool(node,
1387 "qcom,use-voltage-floor-corner")) {
1388 if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
1389 reg->rdesc.ops = &smps_floor_corner_ops;
1390 else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
1391 reg->rdesc.ops = &ldo_floor_corner_ops;
David Collins23c96cd2012-10-05 17:12:00 -07001392 }
David Collins4208ce32012-06-15 13:33:13 -07001393
David Collins409a9fa2013-03-05 10:54:25 -08001394 reg->always_send_voltage
1395 = of_property_read_bool(node, "qcom,always-send-voltage");
1396 reg->always_send_current
1397 = of_property_read_bool(node, "qcom,always-send-current");
1398
David Collinsc7642322012-04-04 10:19:12 -07001399 if (regulator_type == RPM_REGULATOR_SMD_TYPE_VS)
1400 reg->rdesc.n_voltages = 0;
1401 else
1402 reg->rdesc.n_voltages = 2;
1403
1404 rc = of_property_read_u32(node, "qcom,set", &val);
1405 if (rc) {
1406 dev_err(dev, "%s: sleep set and/or active set must be "
1407 "configured via qcom,set property, rc=%d\n", __func__,
1408 rc);
1409 goto fail_free_reg;
1410 } else if (!(val & RPM_SET_CONFIG_BOTH)) {
1411 dev_err(dev, "%s: qcom,set=%u property is invalid\n", __func__,
1412 val);
1413 rc = -EINVAL;
1414 goto fail_free_reg;
1415 }
1416
1417 reg->set_active = !!(val & RPM_SET_CONFIG_ACTIVE);
1418 reg->set_sleep = !!(val & RPM_SET_CONFIG_SLEEP);
1419
David Collins4853ae42012-06-12 09:37:19 -07001420 init_data = of_get_regulator_init_data(dev, node);
David Collinsc7642322012-04-04 10:19:12 -07001421 if (init_data == NULL) {
1422 dev_err(dev, "%s: unable to allocate memory\n", __func__);
1423 rc = -ENOMEM;
1424 goto fail_free_reg;
1425 }
1426 if (init_data->constraints.name == NULL) {
1427 dev_err(dev, "%s: regulator name not specified\n", __func__);
1428 rc = -EINVAL;
1429 goto fail_free_reg;
1430 }
1431
1432 init_data->constraints.input_uV = init_data->constraints.max_uV;
1433
1434 if (of_get_property(node, "parent-supply", NULL))
1435 init_data->supply_regulator = "parent";
1436
1437 /*
1438 * Fill in ops and mode masks based on callbacks specified for
1439 * this type of regulator.
1440 */
1441 if (reg->rdesc.ops->enable)
1442 init_data->constraints.valid_ops_mask
1443 |= REGULATOR_CHANGE_STATUS;
1444 if (reg->rdesc.ops->get_voltage)
1445 init_data->constraints.valid_ops_mask
1446 |= REGULATOR_CHANGE_VOLTAGE;
1447 if (reg->rdesc.ops->get_mode) {
1448 init_data->constraints.valid_ops_mask
1449 |= REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_DRMS;
1450 init_data->constraints.valid_modes_mask
1451 |= REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE;
1452 }
1453
1454 reg->rdesc.name = init_data->constraints.name;
1455 reg->min_uV = init_data->constraints.min_uV;
1456 reg->max_uV = init_data->constraints.max_uV;
1457
1458 /* Initialize the param array based on optional properties. */
1459 for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++) {
1460 rc = of_property_read_u32(node, params[i].property_name, &val);
1461 if (rc == 0) {
1462 if (params[i].supported_regulator_types
1463 & BIT(regulator_type)) {
1464 if (val < params[i].min
1465 || val > params[i].max) {
1466 pr_warn("%s: device tree property: "
1467 "%s=%u is outsided allowed "
1468 "range [%u, %u]\n",
1469 reg->rdesc.name,
1470 params[i].property_name, val,
1471 params[i].min, params[i].max);
1472 continue;
1473 }
1474 reg->req.param[i] = val;
1475 reg->req.modified |= BIT(i);
1476 } else {
1477 pr_warn("%s: regulator type=%d does not support"
1478 " device tree property: %s\n",
1479 reg->rdesc.name, regulator_type,
1480 params[i].property_name);
1481 }
1482 }
1483 }
1484
David Collinsa3e70de2012-10-05 14:38:13 -07001485 of_property_read_u32(node, "qcom,system-load", &reg->system_load);
David Collinsc7642322012-04-04 10:19:12 -07001486
1487 rpm_vreg_lock(rpm_vreg);
1488 list_add(&reg->list, &rpm_vreg->reg_list);
1489 rpm_vreg_unlock(rpm_vreg);
1490
1491 reg->rdev = regulator_register(&reg->rdesc, dev, init_data, reg, node);
1492 if (IS_ERR(reg->rdev)) {
1493 rc = PTR_ERR(reg->rdev);
1494 reg->rdev = NULL;
1495 pr_err("regulator_register failed: %s, rc=%d\n",
1496 reg->rdesc.name, rc);
1497 goto fail_remove_from_list;
1498 }
1499
1500 platform_set_drvdata(pdev, reg);
1501
1502 pr_debug("successfully probed: %s\n", reg->rdesc.name);
1503
1504 return 0;
1505
1506fail_remove_from_list:
1507 rpm_vreg_lock(rpm_vreg);
1508 list_del(&reg->list);
1509 rpm_vreg_unlock(rpm_vreg);
1510
1511fail_free_reg:
1512 kfree(reg);
1513 return rc;
1514}
1515
1516/*
1517 * This probe is called for parent rpm-regulator devices which have
1518 * properties which are required to identify a given RPM resource.
1519 */
1520static int __devinit rpm_vreg_resource_probe(struct platform_device *pdev)
1521{
1522 struct device *dev = &pdev->dev;
1523 struct device_node *node = dev->of_node;
1524 struct rpm_vreg *rpm_vreg;
1525 int val = 0;
1526 u32 resource_type;
1527 int rc;
1528
1529 if (!dev->of_node) {
1530 dev_err(dev, "%s: device tree information missing\n", __func__);
1531 return -ENODEV;
1532 }
1533
1534 /* Create new rpm_vreg entry. */
1535 rpm_vreg = kzalloc(sizeof(struct rpm_vreg), GFP_KERNEL);
1536 if (rpm_vreg == NULL) {
1537 dev_err(dev, "%s: could not allocate memory for vreg\n",
1538 __func__);
1539 return -ENOMEM;
1540 }
1541
1542 /* Required device tree properties: */
1543 rc = of_property_read_string(node, "qcom,resource-name",
1544 &rpm_vreg->resource_name);
1545 if (rc) {
1546 dev_err(dev, "%s: qcom,resource-name missing in DT node\n",
1547 __func__);
1548 goto fail_free_vreg;
1549 }
1550 resource_type = rpm_vreg_string_to_int(rpm_vreg->resource_name);
1551
1552 rc = of_property_read_u32(node, "qcom,resource-id",
1553 &rpm_vreg->resource_id);
1554 if (rc) {
1555 dev_err(dev, "%s: qcom,resource-id missing in DT node\n",
1556 __func__);
1557 goto fail_free_vreg;
1558 }
1559
1560 rc = of_property_read_u32(node, "qcom,regulator-type",
1561 &rpm_vreg->regulator_type);
1562 if (rc) {
1563 dev_err(dev, "%s: qcom,regulator-type missing in DT node\n",
1564 __func__);
1565 goto fail_free_vreg;
1566 }
1567
1568 if ((rpm_vreg->regulator_type < 0)
1569 || (rpm_vreg->regulator_type >= RPM_REGULATOR_SMD_TYPE_MAX)) {
1570 dev_err(dev, "%s: invalid regulator type: %d\n", __func__,
1571 rpm_vreg->regulator_type);
1572 rc = -EINVAL;
1573 goto fail_free_vreg;
1574 }
1575
1576 /* Optional device tree properties: */
1577 of_property_read_u32(node, "qcom,allow-atomic", &val);
1578 rpm_vreg->allow_atomic = !!val;
1579 of_property_read_u32(node, "qcom,enable-time", &rpm_vreg->enable_time);
1580 of_property_read_u32(node, "qcom,hpm-min-load",
1581 &rpm_vreg->hpm_min_load);
1582
1583 rpm_vreg->handle_active = msm_rpm_create_request(RPM_SET_ACTIVE,
1584 resource_type, rpm_vreg->resource_id, RPM_REGULATOR_PARAM_MAX);
1585 if (rpm_vreg->handle_active == NULL
1586 || IS_ERR(rpm_vreg->handle_active)) {
1587 rc = PTR_ERR(rpm_vreg->handle_active);
1588 dev_err(dev, "%s: failed to create active RPM handle, rc=%d\n",
1589 __func__, rc);
1590 goto fail_free_vreg;
1591 }
1592
1593 rpm_vreg->handle_sleep = msm_rpm_create_request(RPM_SET_SLEEP,
1594 resource_type, rpm_vreg->resource_id, RPM_REGULATOR_PARAM_MAX);
1595 if (rpm_vreg->handle_sleep == NULL || IS_ERR(rpm_vreg->handle_sleep)) {
1596 rc = PTR_ERR(rpm_vreg->handle_sleep);
1597 dev_err(dev, "%s: failed to create sleep RPM handle, rc=%d\n",
1598 __func__, rc);
1599 goto fail_free_handle_active;
1600 }
1601
1602 INIT_LIST_HEAD(&rpm_vreg->reg_list);
1603
1604 if (rpm_vreg->allow_atomic)
1605 spin_lock_init(&rpm_vreg->slock);
1606 else
1607 mutex_init(&rpm_vreg->mlock);
1608
1609 platform_set_drvdata(pdev, rpm_vreg);
1610
1611 rc = of_platform_populate(node, NULL, NULL, dev);
1612 if (rc) {
1613 dev_err(dev, "%s: failed to add child nodes, rc=%d\n", __func__,
1614 rc);
1615 goto fail_unset_drvdata;
1616 }
1617
1618 pr_debug("successfully probed: %s (%08X) %u\n", rpm_vreg->resource_name,
1619 resource_type, rpm_vreg->resource_id);
1620
1621 return rc;
1622
1623fail_unset_drvdata:
1624 platform_set_drvdata(pdev, NULL);
1625 msm_rpm_free_request(rpm_vreg->handle_sleep);
1626
1627fail_free_handle_active:
1628 msm_rpm_free_request(rpm_vreg->handle_active);
1629
1630fail_free_vreg:
1631 kfree(rpm_vreg);
1632
1633 return rc;
1634}
1635
1636static struct of_device_id rpm_vreg_match_table_device[] = {
1637 { .compatible = "qcom,rpm-regulator-smd", },
1638 {}
1639};
1640
1641static struct of_device_id rpm_vreg_match_table_resource[] = {
1642 { .compatible = "qcom,rpm-regulator-smd-resource", },
1643 {}
1644};
1645
1646static struct platform_driver rpm_vreg_device_driver = {
1647 .probe = rpm_vreg_device_probe,
1648 .remove = __devexit_p(rpm_vreg_device_remove),
1649 .driver = {
1650 .name = "qcom,rpm-regulator-smd",
1651 .owner = THIS_MODULE,
1652 .of_match_table = rpm_vreg_match_table_device,
1653 },
1654};
1655
1656static struct platform_driver rpm_vreg_resource_driver = {
1657 .probe = rpm_vreg_resource_probe,
1658 .remove = __devexit_p(rpm_vreg_resource_remove),
1659 .driver = {
1660 .name = "qcom,rpm-regulator-smd-resource",
1661 .owner = THIS_MODULE,
1662 .of_match_table = rpm_vreg_match_table_resource,
1663 },
1664};
1665
1666/**
1667 * rpm_regulator_smd_driver_init() - initialized SMD RPM regulator driver
1668 *
1669 * This function registers the SMD RPM regulator platform drivers.
1670 *
1671 * Returns 0 on success or errno on failure.
1672 */
1673int __init rpm_regulator_smd_driver_init(void)
1674{
1675 static bool initialized;
1676 int i, rc;
1677
1678 if (initialized)
1679 return 0;
1680 else
1681 initialized = true;
1682
1683 /* Store parameter string names as integers */
1684 for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++)
1685 params[i].key = rpm_vreg_string_to_int(params[i].name);
1686
1687 rc = platform_driver_register(&rpm_vreg_device_driver);
1688 if (rc)
1689 return rc;
1690
1691 return platform_driver_register(&rpm_vreg_resource_driver);
1692}
1693EXPORT_SYMBOL_GPL(rpm_regulator_smd_driver_init);
1694
1695static void __exit rpm_vreg_exit(void)
1696{
1697 platform_driver_unregister(&rpm_vreg_device_driver);
1698 platform_driver_unregister(&rpm_vreg_resource_driver);
1699}
1700
1701module_init(rpm_regulator_smd_driver_init);
1702module_exit(rpm_vreg_exit);
1703
1704MODULE_LICENSE("GPL v2");
1705MODULE_DESCRIPTION("MSM SMD RPM regulator driver");