blob: 08923e49b69e8ce6574d8febed507cbefbfdaa56 [file] [log] [blame]
Willie Ruan2635a852013-03-17 16:33:42 -07001/*
2 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 *
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
14#define pr_fmt(fmt) "%s: " fmt, __func__
15
16#include <linux/module.h>
17#include <linux/err.h>
18#include <linux/string.h>
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/io.h>
22#include <linux/bitops.h>
23#include <linux/slab.h>
24#include <linux/of.h>
25#include <linux/of_device.h>
26#include <linux/platform_device.h>
27#include <linux/regulator/driver.h>
28#include <linux/regulator/of_regulator.h>
29#include <linux/regulator/cpr-regulator.h>
30
31struct cpr_regulator {
32 struct regulator_desc rdesc;
33 struct regulator_dev *rdev;
34 bool enabled;
35 int corner;
36
37 /* Process voltage parameters */
38 phys_addr_t efuse_phys;
39 u32 num_efuse_bits;
40 u32 efuse_bit_pos[CPR_PVS_EFUSE_BITS_MAX];
41 u32 pvs_bin_process[CPR_PVS_EFUSE_BINS_MAX];
42 u32 pvs_corner_ceiling[NUM_APC_PVS][CPR_CORNER_MAX];
43 /* Process voltage variables */
44 u32 pvs_bin;
45 u32 pvs_process;
Willie Ruan6d502392013-03-27 15:40:28 -070046 u32 *corner_ceiling;
Willie Ruan2635a852013-03-17 16:33:42 -070047
48 /* APC voltage regulator */
49 struct regulator *vdd_apc;
Willie Ruan6d502392013-03-27 15:40:28 -070050
51 /* Dependency parameters */
52 struct regulator *vdd_mx;
53 int vdd_mx_vmax;
54 int vdd_mx_vmin_method;
55 int vdd_mx_vmin;
Willie Ruan2635a852013-03-17 16:33:42 -070056};
57
58static int cpr_regulator_is_enabled(struct regulator_dev *rdev)
59{
60 struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
61
62 return cpr_vreg->enabled;
63}
64
65static int cpr_regulator_enable(struct regulator_dev *rdev)
66{
67 struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
Willie Ruan6d502392013-03-27 15:40:28 -070068 int rc = 0;
69
70 /* Enable dependency power before vdd_apc */
71 if (cpr_vreg->vdd_mx) {
72 rc = regulator_enable(cpr_vreg->vdd_mx);
73 if (rc) {
74 pr_err("regulator_enable: vdd_mx: rc=%d\n", rc);
75 return rc;
76 }
77 }
Willie Ruan2635a852013-03-17 16:33:42 -070078
79 rc = regulator_enable(cpr_vreg->vdd_apc);
80 if (!rc)
81 cpr_vreg->enabled = true;
Willie Ruan6d502392013-03-27 15:40:28 -070082 else
83 pr_err("regulator_enable: vdd_apc: rc=%d\n", rc);
84
Willie Ruan2635a852013-03-17 16:33:42 -070085 return rc;
86}
87
88static int cpr_regulator_disable(struct regulator_dev *rdev)
89{
90 struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
91 int rc;
92
93 rc = regulator_disable(cpr_vreg->vdd_apc);
Willie Ruan6d502392013-03-27 15:40:28 -070094 if (!rc) {
95 if (cpr_vreg->vdd_mx)
96 rc = regulator_disable(cpr_vreg->vdd_mx);
97
98 if (rc)
99 pr_err("regulator_disable: vdd_mx: rc=%d\n", rc);
100 else
101 cpr_vreg->enabled = false;
102 } else {
103 pr_err("regulator_disable: vdd_apc: rc=%d\n", rc);
104 }
105
Willie Ruan2635a852013-03-17 16:33:42 -0700106 return rc;
107}
108
109static int cpr_regulator_set_voltage(struct regulator_dev *rdev,
110 int min_uV, int max_uV, unsigned *selector)
111{
112 struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
113 int rc;
Willie Ruan6d502392013-03-27 15:40:28 -0700114 int vdd_apc_min, vdd_apc_max, vdd_mx_vmin = 0;
115 int change_dir = 0;
Willie Ruan2635a852013-03-17 16:33:42 -0700116
Willie Ruan6d502392013-03-27 15:40:28 -0700117 if (cpr_vreg->vdd_mx) {
118 if (min_uV > cpr_vreg->corner)
119 change_dir = 1;
120 else if (min_uV < cpr_vreg->corner)
121 change_dir = -1;
122 }
123
124 vdd_apc_min = cpr_vreg->corner_ceiling[min_uV];
125 vdd_apc_max = cpr_vreg->corner_ceiling[CPR_CORNER_SUPER_TURBO];
126
127 if (change_dir) {
128 /* Determine the vdd_mx voltage */
129 switch (cpr_vreg->vdd_mx_vmin_method) {
130 case VDD_MX_VMIN_APC:
131 vdd_mx_vmin = vdd_apc_min;
132 break;
133 case VDD_MX_VMIN_APC_CORNER_CEILING:
134 vdd_mx_vmin = vdd_apc_min;
135 break;
136 case VDD_MX_VMIN_APC_SLOW_CORNER_CEILING:
137 vdd_mx_vmin = cpr_vreg->pvs_corner_ceiling
138 [APC_PVS_SLOW][min_uV];
139 break;
140 case VDD_MX_VMIN_MX_VMAX:
141 default:
142 vdd_mx_vmin = cpr_vreg->vdd_mx_vmax;
143 break;
144 }
145 }
146
147 if (change_dir > 0) {
148 if (vdd_mx_vmin < cpr_vreg->vdd_mx_vmin) {
149 /* Check and report the value in case */
150 pr_err("Up: but new %d < old %d uV\n", vdd_mx_vmin,
151 cpr_vreg->vdd_mx_vmin);
152 }
153
154 rc = regulator_set_voltage(cpr_vreg->vdd_mx, vdd_mx_vmin,
155 cpr_vreg->vdd_mx_vmax);
156 if (!rc) {
157 cpr_vreg->vdd_mx_vmin = vdd_mx_vmin;
158 } else {
159 pr_err("set: vdd_mx [%d] = %d uV: rc=%d\n",
160 min_uV, vdd_mx_vmin, rc);
161 return rc;
162 }
163 }
164
Willie Ruan2635a852013-03-17 16:33:42 -0700165 rc = regulator_set_voltage(cpr_vreg->vdd_apc,
166 vdd_apc_min, vdd_apc_max);
Willie Ruan6d502392013-03-27 15:40:28 -0700167 if (!rc) {
Willie Ruan2635a852013-03-17 16:33:42 -0700168 cpr_vreg->corner = min_uV;
Willie Ruan6d502392013-03-27 15:40:28 -0700169 } else {
170 pr_err("set: vdd_apc [%d] = %d uV: rc=%d\n",
171 min_uV, vdd_apc_min, rc);
172 return rc;
173 }
174
175 if (change_dir < 0) {
176 if (vdd_mx_vmin > cpr_vreg->vdd_mx_vmin) {
177 /* Check and report the value in case */
178 pr_err("Down: but new %d >= old %d uV\n", vdd_mx_vmin,
179 cpr_vreg->vdd_mx_vmin);
180 }
181
182 rc = regulator_set_voltage(cpr_vreg->vdd_mx, vdd_mx_vmin,
183 cpr_vreg->vdd_mx_vmax);
184 if (!rc) {
185 cpr_vreg->vdd_mx_vmin = vdd_mx_vmin;
186 } else {
187 pr_err("set: vdd_mx [%d] = %d uV: rc=%d\n",
188 min_uV, vdd_mx_vmin, rc);
189 return rc;
190 }
191 }
Willie Ruan2635a852013-03-17 16:33:42 -0700192
193 pr_debug("set [corner:%d] = %d uV: rc=%d\n", min_uV, vdd_apc_min, rc);
194 return rc;
195}
196
197static int cpr_regulator_get_voltage(struct regulator_dev *rdev)
198{
199 struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
200
201 return cpr_vreg->corner;
202}
203
204static struct regulator_ops cpr_corner_ops = {
205 .enable = cpr_regulator_enable,
206 .disable = cpr_regulator_disable,
207 .is_enabled = cpr_regulator_is_enabled,
208 .set_voltage = cpr_regulator_set_voltage,
209 .get_voltage = cpr_regulator_get_voltage,
210};
211
212static int __init cpr_regulator_pvs_init(struct cpr_regulator *cpr_vreg)
213{
214 void __iomem *efuse_base;
215 u32 efuse_bits;
216 int i, bit_pos;
217 u32 vmax;
218
219 efuse_base = ioremap(cpr_vreg->efuse_phys, 4);
220 if (!efuse_base) {
221 pr_err("Unable to map efuse_phys 0x%x\n",
222 cpr_vreg->efuse_phys);
223 return -EINVAL;
224 }
225
226 efuse_bits = readl_relaxed(efuse_base);
227
228 /* Construct PVS process # from the efuse bits */
229 for (i = 0; i < cpr_vreg->num_efuse_bits; i++) {
230 bit_pos = cpr_vreg->efuse_bit_pos[i];
231 cpr_vreg->pvs_bin |= (efuse_bits & BIT(bit_pos)) ? BIT(i) : 0;
232 }
233
234 cpr_vreg->pvs_process = cpr_vreg->pvs_bin_process[cpr_vreg->pvs_bin];
235 if (cpr_vreg->pvs_process >= NUM_APC_PVS)
236 cpr_vreg->pvs_process = APC_PVS_NO;
237
238 /* Use ceiling voltage of Turbo@Slow for all corners of APC_PVS_NO
239 but use SuperTurbo@Slow for its SuperTurbo */
240 vmax = cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW][CPR_CORNER_TURBO];
241 for (i = CPR_CORNER_SVS; i <= CPR_CORNER_TURBO; i++)
242 cpr_vreg->pvs_corner_ceiling[APC_PVS_NO][i] = vmax;
243 cpr_vreg->pvs_corner_ceiling[APC_PVS_NO][CPR_CORNER_SUPER_TURBO]
244 = cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW]
245 [CPR_CORNER_SUPER_TURBO];
246
Willie Ruan6d502392013-03-27 15:40:28 -0700247 cpr_vreg->corner_ceiling =
Willie Ruan2635a852013-03-17 16:33:42 -0700248 cpr_vreg->pvs_corner_ceiling[cpr_vreg->pvs_process];
249
250 iounmap(efuse_base);
251
252 pr_info("PVS Info: efuse_phys=0x%08X, n_bits=%d\n",
253 cpr_vreg->efuse_phys, cpr_vreg->num_efuse_bits);
254 pr_info("PVS Info: efuse=0x%08X, bin=%d, process=%d\n",
255 efuse_bits, cpr_vreg->pvs_bin, cpr_vreg->pvs_process);
256
257 return 0;
258}
259
260static int __init cpr_regulator_apc_init(struct platform_device *pdev,
261 struct cpr_regulator *cpr_vreg)
262{
Willie Ruan6d502392013-03-27 15:40:28 -0700263 struct device_node *of_node = pdev->dev.of_node;
264 int rc;
265
Willie Ruan2635a852013-03-17 16:33:42 -0700266 cpr_vreg->vdd_apc = devm_regulator_get(&pdev->dev, "vdd-apc");
267 if (IS_ERR_OR_NULL(cpr_vreg->vdd_apc)) {
Willie Ruan6d502392013-03-27 15:40:28 -0700268 rc = PTR_RET(cpr_vreg->vdd_apc);
269 if (rc != -EPROBE_DEFER)
270 pr_err("devm_regulator_get: rc=%d\n", rc);
271 return rc;
Willie Ruan2635a852013-03-17 16:33:42 -0700272 }
273
Willie Ruan6d502392013-03-27 15:40:28 -0700274 /* Check dependencies */
275 if (of_property_read_bool(of_node, "vdd-mx-supply")) {
276 cpr_vreg->vdd_mx = devm_regulator_get(&pdev->dev, "vdd-mx");
277 if (IS_ERR_OR_NULL(cpr_vreg->vdd_mx)) {
278 rc = PTR_RET(cpr_vreg->vdd_mx);
279 if (rc != -EPROBE_DEFER)
280 pr_err("devm_regulator_get: vdd-mx: rc=%d\n",
281 rc);
282 return rc;
283 }
284 }
285
286 /* Parse dependency parameters */
287 if (cpr_vreg->vdd_mx) {
288 rc = of_property_read_u32(of_node, "qcom,vdd-mx-vmax",
289 &cpr_vreg->vdd_mx_vmax);
290 if (rc < 0) {
291 pr_err("vdd-mx-vmax missing: rc=%d\n", rc);
292 return rc;
293 }
294
295 rc = of_property_read_u32(of_node, "qcom,vdd-mx-vmin-method",
296 &cpr_vreg->vdd_mx_vmin_method);
297 if (rc < 0) {
298 pr_err("vdd-mx-vmin-method missing: rc=%d\n", rc);
299 return rc;
300 }
301 if (cpr_vreg->vdd_mx_vmin_method > VDD_MX_VMIN_MX_VMAX) {
302 pr_err("Invalid vdd-mx-vmin-method(%d)\n",
303 cpr_vreg->vdd_mx_vmin_method);
304 return -EINVAL;
305 }
306 }
307
308 return 0;
Willie Ruan2635a852013-03-17 16:33:42 -0700309}
310
311static void cpr_regulator_apc_exit(struct cpr_regulator *cpr_vreg)
312{
Willie Ruan6d502392013-03-27 15:40:28 -0700313 if (cpr_vreg->enabled) {
Willie Ruan2635a852013-03-17 16:33:42 -0700314 regulator_disable(cpr_vreg->vdd_apc);
Willie Ruan6d502392013-03-27 15:40:28 -0700315
316 if (cpr_vreg->vdd_mx)
317 regulator_disable(cpr_vreg->vdd_mx);
318 }
Willie Ruan2635a852013-03-17 16:33:42 -0700319}
320
321static int __init cpr_regulator_parse_dt(struct platform_device *pdev,
322 struct cpr_regulator *cpr_vreg)
323{
324 struct device_node *of_node = pdev->dev.of_node;
325 struct resource *res;
326 int rc;
327 size_t pvs_bins;
328
329 /* Parse process voltage parameters */
330 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
331 "efuse_phys");
332 if (!res || !res->start) {
333 pr_err("efuse_phys missing: res=%p\n", res);
334 return -EINVAL;
335 }
336 cpr_vreg->efuse_phys = res->start;
337
338 rc = of_property_read_u32(of_node, "qcom,num-efuse-bits",
339 &cpr_vreg->num_efuse_bits);
340 if (rc < 0) {
341 pr_err("num-efuse-bits missing: rc=%d\n", rc);
342 return rc;
343 }
344
345 if (cpr_vreg->num_efuse_bits == 0 ||
346 cpr_vreg->num_efuse_bits > CPR_PVS_EFUSE_BITS_MAX) {
347 pr_err("invalid num-efuse-bits : %d\n",
348 cpr_vreg->num_efuse_bits);
349 return -EINVAL;
350 }
351
352 rc = of_property_read_u32_array(of_node, "qcom,efuse-bit-pos",
353 cpr_vreg->efuse_bit_pos,
354 cpr_vreg->num_efuse_bits);
355 if (rc < 0) {
356 pr_err("efuse-bit-pos missing: rc=%d\n", rc);
357 return rc;
358 }
359
360 pvs_bins = 1 << cpr_vreg->num_efuse_bits;
361 rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
362 cpr_vreg->pvs_bin_process,
363 pvs_bins);
364 if (rc < 0) {
365 pr_err("pvs-bin-process missing: rc=%d\n", rc);
366 return rc;
367 }
368
369 rc = of_property_read_u32_array(of_node,
370 "qcom,pvs-corner-ceiling-slow",
371 &cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW][CPR_CORNER_SVS],
372 CPR_CORNER_MAX - CPR_CORNER_SVS);
373 if (rc < 0) {
374 pr_err("pvs-corner-ceiling-slow missing: rc=%d\n", rc);
375 return rc;
376 }
377
378 rc = of_property_read_u32_array(of_node,
379 "qcom,pvs-corner-ceiling-nom",
380 &cpr_vreg->pvs_corner_ceiling[APC_PVS_NOM][CPR_CORNER_SVS],
381 CPR_CORNER_MAX - CPR_CORNER_SVS);
382 if (rc < 0) {
383 pr_err("pvs-corner-ceiling-norm missing: rc=%d\n", rc);
384 return rc;
385 }
386
387 rc = of_property_read_u32_array(of_node,
388 "qcom,pvs-corner-ceiling-fast",
389 &cpr_vreg->pvs_corner_ceiling[APC_PVS_FAST][CPR_CORNER_SVS],
390 CPR_CORNER_MAX - CPR_CORNER_SVS);
391 if (rc < 0) {
392 pr_err("pvs-corner-ceiling-fast missing: rc=%d\n", rc);
393 return rc;
394 }
395
396 return 0;
397}
398
399static int __devinit cpr_regulator_probe(struct platform_device *pdev)
400{
401 struct cpr_regulator *cpr_vreg;
402 struct regulator_desc *rdesc;
403 struct regulator_init_data *init_data = pdev->dev.platform_data;
404 int rc;
405
406 if (!pdev->dev.of_node) {
407 pr_err("Device tree node is missing\n");
408 return -EINVAL;
409 }
410
411 init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
412 if (!init_data) {
413 pr_err("regulator init data is missing\n");
414 return -EINVAL;
415 } else {
416 init_data->constraints.input_uV
417 = init_data->constraints.max_uV;
418 init_data->constraints.valid_ops_mask
419 |= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS;
420 }
421
422 cpr_vreg = devm_kzalloc(&pdev->dev, sizeof(struct cpr_regulator),
423 GFP_KERNEL);
424 if (!cpr_vreg) {
425 pr_err("Can't allocate cpr_regulator memory\n");
426 return -ENOMEM;
427 }
428
429 rc = cpr_regulator_parse_dt(pdev, cpr_vreg);
430 if (rc) {
431 pr_err("Wrong DT parameter specified: rc=%d\n", rc);
432 return rc;
433 }
434
435 rc = cpr_regulator_pvs_init(cpr_vreg);
436 if (rc) {
437 pr_err("Initialize PVS wrong: rc=%d\n", rc);
438 return rc;
439 }
440
441 rc = cpr_regulator_apc_init(pdev, cpr_vreg);
442 if (rc) {
443 if (rc != -EPROBE_DEFER)
444 pr_err("Initialize APC wrong: rc=%d\n", rc);
445 return rc;
446 }
447
448 rdesc = &cpr_vreg->rdesc;
449 rdesc->owner = THIS_MODULE;
450 rdesc->type = REGULATOR_VOLTAGE;
451 rdesc->ops = &cpr_corner_ops;
452 rdesc->name = init_data->constraints.name;
453
454 cpr_vreg->rdev = regulator_register(rdesc, &pdev->dev, init_data,
455 cpr_vreg, pdev->dev.of_node);
456 if (IS_ERR(cpr_vreg->rdev)) {
457 rc = PTR_ERR(cpr_vreg->rdev);
458 pr_err("regulator_register failed: rc=%d\n", rc);
459
460 cpr_regulator_apc_exit(cpr_vreg);
461 return rc;
462 }
463
464 platform_set_drvdata(pdev, cpr_vreg);
465
466 pr_info("PVS [%d %d %d %d] uV\n",
Willie Ruan6d502392013-03-27 15:40:28 -0700467 cpr_vreg->corner_ceiling[CPR_CORNER_SVS],
468 cpr_vreg->corner_ceiling[CPR_CORNER_NORMAL],
469 cpr_vreg->corner_ceiling[CPR_CORNER_TURBO],
470 cpr_vreg->corner_ceiling[CPR_CORNER_SUPER_TURBO]);
Willie Ruan2635a852013-03-17 16:33:42 -0700471
472 return 0;
473}
474
475static int __devexit cpr_regulator_remove(struct platform_device *pdev)
476{
477 struct cpr_regulator *cpr_vreg;
478
479 cpr_vreg = platform_get_drvdata(pdev);
480 if (cpr_vreg) {
481 cpr_regulator_apc_exit(cpr_vreg);
482 regulator_unregister(cpr_vreg->rdev);
483 }
484
485 return 0;
486}
487
488static struct of_device_id cpr_regulator_match_table[] = {
489 { .compatible = CPR_REGULATOR_DRIVER_NAME, },
490 {}
491};
492
493static struct platform_driver cpr_regulator_driver = {
494 .driver = {
495 .name = CPR_REGULATOR_DRIVER_NAME,
496 .of_match_table = cpr_regulator_match_table,
497 .owner = THIS_MODULE,
498 },
499 .probe = cpr_regulator_probe,
500 .remove = __devexit_p(cpr_regulator_remove),
501};
502
503/**
504 * cpr_regulator_init() - register cpr-regulator driver
505 *
506 * This initialization function should be called in systems in which driver
507 * registration ordering must be controlled precisely.
508 */
509int __init cpr_regulator_init(void)
510{
511 static bool initialized;
512
513 if (initialized)
514 return 0;
515 else
516 initialized = true;
517
518 return platform_driver_register(&cpr_regulator_driver);
519}
520EXPORT_SYMBOL(cpr_regulator_init);
521
522static void __exit cpr_regulator_exit(void)
523{
524 platform_driver_unregister(&cpr_regulator_driver);
525}
526
527MODULE_DESCRIPTION("CPR regulator driver");
528MODULE_LICENSE("GPL v2");
529
530arch_initcall(cpr_regulator_init);
531module_exit(cpr_regulator_exit);