blob: 9014f376564f0a7f8c3998297141589802b45cba [file] [log] [blame]
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -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
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -080013#define pr_fmt(fmt) "PDN %s: " fmt, __func__
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -070014
15#include <linux/err.h>
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/delay.h>
20#include <linux/slab.h>
21#include <linux/string.h>
22#include <linux/io.h>
23#include <linux/of.h>
24#include <linux/of_device.h>
25#include <linux/platform_device.h>
26#include <linux/regulator/driver.h>
27#include <linux/regulator/machine.h>
28#include <linux/regulator/of_regulator.h>
29#include <linux/regulator/krait-regulator.h>
Abhijeet Dharmapurikar37c47a82013-01-08 18:44:21 -080030#include <linux/debugfs.h>
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -070031#include <linux/syscore_ops.h>
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -070032#include <mach/msm_iomap.h>
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -070033
34#include "spm.h"
Abhijeet Dharmapurikar295c4dc2013-01-08 12:59:01 -080035#include "pm.h"
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -070036
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070037/*
38 * supply
39 * from
40 * pmic
41 * gang
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -080042 * |
43 * |________________________________
44 * | | |
45 * ___|___ | |
46 * | | | |
47 * | | / /
48 * | LDO | / /LDO BYP [6]
49 * | | / BHS[6] /(bypass is a weak BHS
50 * |_______| | | needs to be on when in
51 * | | | BHS mode)
52 * |________________|_______________|
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070053 * |
54 * ________|________
55 * | |
56 * | KRAIT |
57 * |_________________|
58 */
59
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -070060#define PMIC_VOLTAGE_MIN 350000
61#define PMIC_VOLTAGE_MAX 1355000
62#define LV_RANGE_STEP 5000
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -070063
Patrick Cain92f4fa12013-04-22 16:23:19 -070064#define CORE_VOLTAGE_BOOTUP 900000
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -070065
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070066#define KRAIT_LDO_VOLTAGE_MIN 465000
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -070067#define KRAIT_LDO_VOLTAGE_OFFSET 465000
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070068#define KRAIT_LDO_STEP 5000
69
70#define BHS_SETTLING_DELAY_US 1
71#define LDO_SETTLING_DELAY_US 1
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -080072#define MDD_SETTLING_DELAY_US 5
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070073
74#define _KRAIT_MASK(BITS, POS) (((u32)(1 << (BITS)) - 1) << POS)
75#define KRAIT_MASK(LEFT_BIT_POS, RIGHT_BIT_POS) \
76 _KRAIT_MASK(LEFT_BIT_POS - RIGHT_BIT_POS + 1, RIGHT_BIT_POS)
77
78#define APC_SECURE 0x00000000
79#define CPU_PWR_CTL 0x00000004
80#define APC_PWR_STATUS 0x00000008
81#define APC_TEST_BUS_SEL 0x0000000C
82#define CPU_TRGTD_DBG_RST 0x00000010
83#define APC_PWR_GATE_CTL 0x00000014
84#define APC_LDO_VREF_SET 0x00000018
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -070085#define APC_PWR_GATE_MODE 0x0000001C
86#define APC_PWR_GATE_DLY 0x00000020
87
88#define PWR_GATE_CONFIG 0x00000044
89#define VERSION 0x00000FD0
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070090
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -080091/* MDD register group */
92#define MDD_CONFIG_CTL 0x00000000
93#define MDD_MODE 0x00000010
94
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070095/* bit definitions for APC_PWR_GATE_CTL */
96#define BHS_CNT_BIT_POS 24
97#define BHS_CNT_MASK KRAIT_MASK(31, 24)
98#define BHS_CNT_DEFAULT 64
99
100#define CLK_SRC_SEL_BIT_POS 15
101#define CLK_SRC_SEL_MASK KRAIT_MASK(15, 15)
102#define CLK_SRC_DEFAULT 0
103
104#define LDO_PWR_DWN_BIT_POS 16
105#define LDO_PWR_DWN_MASK KRAIT_MASK(21, 16)
106
107#define LDO_BYP_BIT_POS 8
108#define LDO_BYP_MASK KRAIT_MASK(13, 8)
109
110#define BHS_SEG_EN_BIT_POS 1
111#define BHS_SEG_EN_MASK KRAIT_MASK(6, 1)
112#define BHS_SEG_EN_DEFAULT 0x3F
113
114#define BHS_EN_BIT_POS 0
115#define BHS_EN_MASK KRAIT_MASK(0, 0)
116
117/* bit definitions for APC_LDO_VREF_SET register */
118#define VREF_RET_POS 8
119#define VREF_RET_MASK KRAIT_MASK(14, 8)
120
121#define VREF_LDO_BIT_POS 0
122#define VREF_LDO_MASK KRAIT_MASK(6, 0)
123
Abhijeet Dharmapurikar37c47a82013-01-08 18:44:21 -0800124#define LDO_HDROOM_MIN 50000
125#define LDO_HDROOM_MAX 250000
126
127#define LDO_UV_MIN 465000
128#define LDO_UV_MAX 750000
129
130#define LDO_TH_MIN 600000
131#define LDO_TH_MAX 900000
132
133#define LDO_DELTA_MIN 10000
134#define LDO_DELTA_MAX 100000
135
Mahesh Sivasubramanian3dca48e2013-04-12 14:29:57 -0600136#define MSM_L2_SAW_PHYS 0xf9012000
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700137/**
138 * struct pmic_gang_vreg -
139 * @name: the string used to represent the gang
140 * @pmic_vmax_uV: the current pmic gang voltage
141 * @pmic_phase_count: the number of phases turned on in the gang
142 * @krait_power_vregs: a list of krait consumers this gang supplies to
143 * @krait_power_vregs_lock: lock to prevent simultaneous access to the list
144 * and its nodes. This needs to be taken by each
145 * regulator's callback functions to prevent
146 * simultaneous updates to the pmic's phase
147 * voltage.
Patrick Cain92f4fa12013-04-22 16:23:19 -0700148 * @apcs_gcc_base: virtual address of the APCS GCC registers
149 * @manage_phases: begin phase control
150 * @pfm_threshold: the sum of coefficients below which PFM can be
151 * enabled
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700152 */
153struct pmic_gang_vreg {
154 const char *name;
155 int pmic_vmax_uV;
156 int pmic_phase_count;
157 struct list_head krait_power_vregs;
158 struct mutex krait_power_vregs_lock;
Abhijeet Dharmapurikar6a42ef82012-10-18 19:37:36 -0700159 bool pfm_mode;
Abhijeet Dharmapurikar295c4dc2013-01-08 12:59:01 -0800160 int pmic_min_uV_for_retention;
161 bool retention_enabled;
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -0800162 bool use_phase_switching;
Stepan Moskovchenko7663b782013-03-08 20:13:06 -0800163 void __iomem *apcs_gcc_base;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700164 bool manage_phases;
165 int pfm_threshold;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700166};
167
168static struct pmic_gang_vreg *the_gang;
169
170enum krait_supply_mode {
171 HS_MODE = REGULATOR_MODE_NORMAL,
172 LDO_MODE = REGULATOR_MODE_IDLE,
173};
174
Patrick Cain955d3522013-04-22 16:25:24 -0700175#define WAIT_FOR_LOAD 0x2
176#define WAIT_FOR_VOLTAGE 0x1
177
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700178struct krait_power_vreg {
179 struct list_head link;
180 struct regulator_desc desc;
181 struct regulator_dev *rdev;
182 const char *name;
183 struct pmic_gang_vreg *pvreg;
184 int uV;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700185 int load;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700186 enum krait_supply_mode mode;
187 void __iomem *reg_base;
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800188 void __iomem *mdd_base;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700189 int ldo_default_uV;
190 int retention_uV;
191 int headroom_uV;
192 int ldo_threshold_uV;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800193 int ldo_delta_uV;
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -0800194 int cpu_num;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700195 int coeff1;
196 int coeff2;
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800197 bool online;
Patrick Cain955d3522013-04-22 16:25:24 -0700198 int online_at_probe;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700199};
200
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -0800201DEFINE_PER_CPU(struct krait_power_vreg *, krait_vregs);
202
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700203static u32 version;
204
Abhijeet Dharmapurikar37c47a82013-01-08 18:44:21 -0800205static int is_between(int left, int right, int value)
206{
207 if (left >= right && left >= value && value >= right)
208 return 1;
209 if (left <= right && left <= value && value <= right)
210 return 1;
211 return 0;
212}
213
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700214static void krait_masked_write(struct krait_power_vreg *kvreg,
215 int reg, uint32_t mask, uint32_t val)
216{
217 uint32_t reg_val;
218
219 reg_val = readl_relaxed(kvreg->reg_base + reg);
220 reg_val &= ~mask;
221 reg_val |= (val & mask);
222 writel_relaxed(reg_val, kvreg->reg_base + reg);
223
224 /*
225 * Barrier to ensure that the reads and writes from
226 * other regulator regions (they are 1k apart) execute in
227 * order to the above write.
228 */
229 mb();
230}
231
Abhijeet Dharmapurikar37c47a82013-01-08 18:44:21 -0800232static int get_krait_retention_ldo_uv(struct krait_power_vreg *kvreg)
233{
234 uint32_t reg_val;
235 int uV;
236
237 reg_val = readl_relaxed(kvreg->reg_base + APC_LDO_VREF_SET);
238 reg_val &= VREF_RET_MASK;
239 reg_val >>= VREF_RET_POS;
240
241 if (reg_val == 0)
242 uV = 0;
243 else
244 uV = KRAIT_LDO_VOLTAGE_OFFSET + reg_val * KRAIT_LDO_STEP;
245
246 return uV;
247}
248
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700249static int get_krait_ldo_uv(struct krait_power_vreg *kvreg)
250{
251 uint32_t reg_val;
252 int uV;
253
254 reg_val = readl_relaxed(kvreg->reg_base + APC_LDO_VREF_SET);
255 reg_val &= VREF_LDO_MASK;
256 reg_val >>= VREF_LDO_BIT_POS;
257
258 if (reg_val == 0)
259 uV = 0;
260 else
261 uV = KRAIT_LDO_VOLTAGE_OFFSET + reg_val * KRAIT_LDO_STEP;
262
263 return uV;
264}
265
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700266static int set_krait_retention_uv(struct krait_power_vreg *kvreg, int uV)
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700267{
268 uint32_t reg_val;
269
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700270 reg_val = DIV_ROUND_UP(uV - KRAIT_LDO_VOLTAGE_OFFSET, KRAIT_LDO_STEP);
271 krait_masked_write(kvreg, APC_LDO_VREF_SET, VREF_RET_MASK,
272 reg_val << VREF_RET_POS);
273
274 return 0;
275}
276
277static int set_krait_ldo_uv(struct krait_power_vreg *kvreg, int uV)
278{
279 uint32_t reg_val;
280
281 reg_val = DIV_ROUND_UP(uV - KRAIT_LDO_VOLTAGE_OFFSET, KRAIT_LDO_STEP);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700282 krait_masked_write(kvreg, APC_LDO_VREF_SET, VREF_LDO_MASK,
283 reg_val << VREF_LDO_BIT_POS);
284
285 return 0;
286}
287
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -0800288static int __krait_power_mdd_enable(struct krait_power_vreg *kvreg, bool on)
289{
290 if (on) {
291 writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
292 /* complete the above write before the delay */
293 mb();
294 udelay(MDD_SETTLING_DELAY_US);
295 } else {
296 writel_relaxed(0x00000000, kvreg->mdd_base + MDD_MODE);
297 /*
298 * complete the above write before other accesses
299 * to krait regulator
300 */
301 mb();
302 }
303 return 0;
304}
305
Patrick Cain92f4fa12013-04-22 16:23:19 -0700306#define COEFF2_UV_THRESHOLD 850000
307static int get_coeff2(int krait_uV)
308{
309 int coeff2 = 0;
310 int krait_mV = krait_uV / 1000;
311
312 if (krait_uV <= COEFF2_UV_THRESHOLD)
313 coeff2 = (612229 * krait_mV) / 1000 - 211258;
314 else
315 coeff2 = (892564 * krait_mV) / 1000 - 449543;
316
317 return coeff2;
318}
319
320static int get_coeff1(int actual_uV, int requested_uV, int load)
321{
322 int ratio = actual_uV * 1000 / requested_uV;
323 int coeff1 = 330 * load + (load * 673 * ratio / 1000);
324
325 return coeff1;
326}
327
328static int get_coeff_total(struct krait_power_vreg *from)
329{
330 int coeff_total = 0;
331 struct krait_power_vreg *kvreg;
332 struct pmic_gang_vreg *pvreg = from->pvreg;
333
334 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
335 if (!kvreg->online)
336 continue;
337
338 if (kvreg->mode == LDO_MODE) {
339 kvreg->coeff1 =
340 get_coeff1(kvreg->uV - kvreg->ldo_delta_uV,
341 kvreg->uV, kvreg->load);
342 kvreg->coeff2 =
343 get_coeff2(kvreg->uV - kvreg->ldo_delta_uV);
344 } else {
345 kvreg->coeff1 =
346 get_coeff1(pvreg->pmic_vmax_uV,
347 kvreg->uV, kvreg->load);
348 kvreg->coeff2 = get_coeff2(pvreg->pmic_vmax_uV);
349 }
350 coeff_total += kvreg->coeff1 + kvreg->coeff2;
351 }
352
353 return coeff_total;
354}
355
356static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
357{
358 pr_debug("programming phase_count = %d\n", phase_count);
359 if (pvreg->use_phase_switching)
360 /*
361 * note the PMIC sets the phase count to one more than
362 * the value in the register - hence subtract 1 from it
363 */
364 return msm_spm_apcs_set_phase(phase_count - 1);
365 else
366 return 0;
367}
368
369static int num_online(struct pmic_gang_vreg *pvreg)
370{
371 int online_total = 0;
372 struct krait_power_vreg *kvreg;
373
374 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
375 if (kvreg->online)
376 online_total++;
377 }
378 return online_total;
379}
380
381static int get_total_load(struct krait_power_vreg *from)
382{
383 int load_total = 0;
384 struct krait_power_vreg *kvreg;
385 struct pmic_gang_vreg *pvreg = from->pvreg;
386
387 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
388 if (!kvreg->online)
389 continue;
390 load_total += kvreg->load;
391 }
392
393 return load_total;
394}
395
Patrick Cain955d3522013-04-22 16:25:24 -0700396static bool enable_phase_management(struct pmic_gang_vreg *pvreg)
397{
398 struct krait_power_vreg *kvreg;
399
400 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
401 pr_debug("%s online_at_probe:0x%x\n", kvreg->name,
402 kvreg->online_at_probe);
403 if (kvreg->online_at_probe)
404 return false;
405 }
406 return true;
407}
408
Patrick Cain92f4fa12013-04-22 16:23:19 -0700409#define PMIC_FTS_MODE_PFM 0x00
410#define PMIC_FTS_MODE_PWM 0x80
411#define ONE_PHASE_COEFF 1000000
412#define TWO_PHASE_COEFF 2000000
413
Willie Ruanaf5b68b2013-04-24 12:08:00 -0700414#define PWM_SETTLING_TIME_US 50
415#define PHASE_SETTLING_TIME_US 50
Patrick Cain92f4fa12013-04-22 16:23:19 -0700416static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
417 int coeff_total)
418{
419 struct pmic_gang_vreg *pvreg = from->pvreg;
420 int phase_count;
421 int rc = 0;
422 int n_online = num_online(pvreg);
423 int load_total;
424
425 load_total = get_total_load(from);
426
Patrick Cain955d3522013-04-22 16:25:24 -0700427 if (pvreg->manage_phases == false) {
428 if (enable_phase_management(pvreg))
429 pvreg->manage_phases = true;
430 else
431 return 0;
432 }
Patrick Cain92f4fa12013-04-22 16:23:19 -0700433
434 /* First check if the coeff is low for PFM mode */
435 if (load_total <= pvreg->pfm_threshold && n_online == 1) {
436 if (!pvreg->pfm_mode) {
437 rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
438 if (rc) {
439 pr_err("%s PFM en failed load_t %d rc = %d\n",
440 from->name, load_total, rc);
441 return rc;
442 } else {
443 pvreg->pfm_mode = true;
444 }
445 }
446 return rc;
447 }
448
449 /* coeff is high switch to PWM mode before changing phases */
450 if (pvreg->pfm_mode) {
451 rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
452 if (rc) {
453 pr_err("%s PFM exit failed load %d rc = %d\n",
454 from->name, coeff_total, rc);
455 return rc;
456 } else {
457 pvreg->pfm_mode = false;
Willie Ruanaf5b68b2013-04-24 12:08:00 -0700458 udelay(PWM_SETTLING_TIME_US);
Patrick Cain92f4fa12013-04-22 16:23:19 -0700459 }
460 }
461
462 /* calculate phases */
463 if (coeff_total < ONE_PHASE_COEFF)
464 phase_count = 1;
465 else if (coeff_total < TWO_PHASE_COEFF)
466 phase_count = 2;
467 else
468 phase_count = 4;
469
470 /* don't increase the phase count higher than number of online cpus */
471 if (phase_count > n_online)
472 phase_count = n_online;
473
474 if (phase_count != pvreg->pmic_phase_count) {
475 rc = set_pmic_gang_phases(pvreg, phase_count);
476 if (rc < 0) {
477 pr_err("%s failed set phase %d rc = %d\n",
478 from->name, phase_count, rc);
479 return rc;
480 }
481
482 /* complete the writes before the delay */
483 mb();
484
485 /*
486 * delay until the phases are settled when
487 * the count is raised
488 */
489 if (phase_count > pvreg->pmic_phase_count)
490 udelay(PHASE_SETTLING_TIME_US);
491
492 pvreg->pmic_phase_count = phase_count;
493 }
494
495 return rc;
496}
497
498static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
499 int input_uV, int output_uV, int load)
500{
501 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
502 int coeff_total;
503 int rc;
504
Patrick Cain955d3522013-04-22 16:25:24 -0700505 kvreg->online_at_probe &= ~WAIT_FOR_LOAD;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700506 coeff_total = get_coeff_total(kvreg);
507
508 rc = pmic_gang_set_phases(kvreg, coeff_total);
509 if (rc < 0) {
510 dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
511 kvreg->name, coeff_total, rc);
512 }
513
514 return kvreg->mode;
515}
516
517static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
518 int input_uV, int output_uV, int load_uA)
519{
520 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
521 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
522 int rc;
523
524 mutex_lock(&pvreg->krait_power_vregs_lock);
525 kvreg->load = load_uA;
526 if (!kvreg->online) {
527 mutex_unlock(&pvreg->krait_power_vregs_lock);
528 return kvreg->mode;
529 }
530
531 rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
532 mutex_unlock(&pvreg->krait_power_vregs_lock);
533
534 return rc;
535}
536
537static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
538{
539 return 0;
540}
541
542static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
543{
544 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
545
546 return kvreg->mode;
547}
548
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700549static int switch_to_using_hs(struct krait_power_vreg *kvreg)
550{
551 if (kvreg->mode == HS_MODE)
552 return 0;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700553 /* enable bhs */
Matt Wagantall5a58f452013-04-26 12:59:49 -0700554 krait_masked_write(kvreg, APC_PWR_GATE_CTL, BHS_EN_MASK, BHS_EN_MASK);
555 /* complete the above write before the delay */
556 mb();
557 /* wait for the bhs to settle */
558 udelay(BHS_SETTLING_DELAY_US);
559
560 /* Turn on BHS segments */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800561 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
Matt Wagantall5a58f452013-04-26 12:59:49 -0700562 BHS_SEG_EN_MASK, BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800563
564 /* complete the above write before the delay */
565 mb();
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700566
567 /*
568 * wait for the bhs to settle - note that
569 * after the voltage has settled both BHS and LDO are supplying power
570 * to the krait. This avoids glitches during switching
571 */
572 udelay(BHS_SETTLING_DELAY_US);
573
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800574 /*
575 * enable ldo bypass - the krait is powered still by LDO since
576 * LDO is enabled
577 */
578 krait_masked_write(kvreg, APC_PWR_GATE_CTL, LDO_BYP_MASK, LDO_BYP_MASK);
579
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700580 /* disable ldo - only the BHS provides voltage to the cpu after this */
581 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
582 LDO_PWR_DWN_MASK, LDO_PWR_DWN_MASK);
583
584 kvreg->mode = HS_MODE;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800585 pr_debug("%s using BHS\n", kvreg->name);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700586 return 0;
587}
588
589static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
590{
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800591 if (kvreg->mode == LDO_MODE
592 && get_krait_ldo_uv(kvreg) == kvreg->uV - kvreg->ldo_delta_uV)
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700593 return 0;
594
595 /*
596 * if the krait is in ldo mode and a voltage change is requested on the
597 * ldo switch to using hs before changing ldo voltage
598 */
599 if (kvreg->mode == LDO_MODE)
600 switch_to_using_hs(kvreg);
601
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800602 set_krait_ldo_uv(kvreg, kvreg->uV - kvreg->ldo_delta_uV);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700603
604 /*
605 * enable ldo - note that both LDO and BHS are are supplying voltage to
606 * the cpu after this. This avoids glitches during switching from BHS
607 * to LDO.
608 */
609 krait_masked_write(kvreg, APC_PWR_GATE_CTL, LDO_PWR_DWN_MASK, 0);
610
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800611 /* complete the writes before the delay */
612 mb();
613
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700614 /* wait for the ldo to settle */
615 udelay(LDO_SETTLING_DELAY_US);
616
617 /*
618 * disable BHS and disable LDO bypass seperate from enabling
619 * the LDO above.
620 */
621 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
622 BHS_EN_MASK | LDO_BYP_MASK, 0);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800623 krait_masked_write(kvreg, APC_PWR_GATE_CTL, BHS_SEG_EN_MASK, 0);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700624
625 kvreg->mode = LDO_MODE;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800626 pr_debug("%s using LDO\n", kvreg->name);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700627 return 0;
628}
629
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800630static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700631{
632 int setpoint;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800633 int rc;
634
635 if (pvreg->pmic_vmax_uV == uV)
636 return 0;
637
638 pr_debug("%d\n", uV);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700639
640 if (uV < PMIC_VOLTAGE_MIN) {
641 pr_err("requested %d < %d, restricting it to %d\n",
642 uV, PMIC_VOLTAGE_MIN, PMIC_VOLTAGE_MIN);
643 uV = PMIC_VOLTAGE_MIN;
644 }
645 if (uV > PMIC_VOLTAGE_MAX) {
646 pr_err("requested %d > %d, restricting it to %d\n",
647 uV, PMIC_VOLTAGE_MAX, PMIC_VOLTAGE_MAX);
648 uV = PMIC_VOLTAGE_MAX;
649 }
650
Abhijeet Dharmapurikar295c4dc2013-01-08 12:59:01 -0800651 if (uV < pvreg->pmic_min_uV_for_retention) {
652 if (pvreg->retention_enabled) {
653 pr_debug("Disabling Retention pmic = %duV, pmic_min_uV_for_retention = %duV",
654 uV, pvreg->pmic_min_uV_for_retention);
655 msm_pm_enable_retention(false);
656 pvreg->retention_enabled = false;
657 }
658 } else {
659 if (!pvreg->retention_enabled) {
660 pr_debug("Enabling Retention pmic = %duV, pmic_min_uV_for_retention = %duV",
661 uV, pvreg->pmic_min_uV_for_retention);
662 msm_pm_enable_retention(true);
663 pvreg->retention_enabled = true;
664 }
665 }
666
Abhijeet Dharmapurikard4f38da2012-08-08 21:42:06 -0700667 setpoint = DIV_ROUND_UP(uV, LV_RANGE_STEP);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800668
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800669 rc = msm_spm_apcs_set_vdd(setpoint);
670 if (rc < 0)
671 pr_err("could not set %duV setpt = 0x%x rc = %d\n",
672 uV, setpoint, rc);
673 else
674 pvreg->pmic_vmax_uV = uV;
675
676 return rc;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700677}
678
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800679static int configure_ldo_or_hs_all(struct krait_power_vreg *from, int vmax)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700680{
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700681 struct pmic_gang_vreg *pvreg = from->pvreg;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700682 struct krait_power_vreg *kvreg;
683 int rc = 0;
684
685 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800686 if (!kvreg->online)
687 continue;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800688 if (kvreg->uV <= kvreg->ldo_threshold_uV
689 && kvreg->uV - kvreg->ldo_delta_uV + kvreg->headroom_uV
690 <= vmax) {
691 rc = switch_to_using_ldo(kvreg);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700692 if (rc < 0) {
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800693 pr_err("could not switch %s to ldo rc = %d\n",
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700694 kvreg->name, rc);
695 return rc;
696 }
697 } else {
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800698 rc = switch_to_using_hs(kvreg);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700699 if (rc < 0) {
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800700 pr_err("could not switch %s to hs rc = %d\n",
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700701 kvreg->name, rc);
702 return rc;
703 }
704 }
705 }
706
707 return rc;
708}
709
710#define SLEW_RATE 2994
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800711static int krait_voltage_increase(struct krait_power_vreg *from,
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700712 int vmax)
713{
714 struct pmic_gang_vreg *pvreg = from->pvreg;
715 int rc = 0;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700716 int settling_us;
717
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700718 /*
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800719 * since krait voltage is increasing set the gang voltage
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700720 * prior to changing ldo/hs states of the requesting krait
721 */
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800722 rc = set_pmic_gang_voltage(pvreg, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700723 if (rc < 0) {
724 dev_err(&from->rdev->dev, "%s failed set voltage %d rc = %d\n",
725 pvreg->name, vmax, rc);
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800726 return rc;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700727 }
728
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800729
730 /* complete the above writes before the delay */
731 mb();
732
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700733 /* delay until the voltage is settled when it is raised */
734 settling_us = DIV_ROUND_UP(vmax - pvreg->pmic_vmax_uV, SLEW_RATE);
735 udelay(settling_us);
736
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800737 rc = configure_ldo_or_hs_all(from, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700738 if (rc < 0) {
739 dev_err(&from->rdev->dev, "%s failed ldo/hs conf %d rc = %d\n",
740 pvreg->name, vmax, rc);
741 }
742
743 return rc;
744}
745
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800746static int krait_voltage_decrease(struct krait_power_vreg *from,
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700747 int vmax)
748{
749 struct pmic_gang_vreg *pvreg = from->pvreg;
750 int rc = 0;
751
752 /*
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800753 * since krait voltage is decreasing ldos might get out of their
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700754 * operating range. Hence configure such kraits to be in hs mode prior
755 * to setting the pmic gang voltage
756 */
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800757 rc = configure_ldo_or_hs_all(from, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700758 if (rc < 0) {
759 dev_err(&from->rdev->dev, "%s failed ldo/hs conf %d rc = %d\n",
760 pvreg->name, vmax, rc);
761 return rc;
762 }
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700763
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800764 rc = set_pmic_gang_voltage(pvreg, vmax);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700765 if (rc < 0) {
766 dev_err(&from->rdev->dev, "%s failed set voltage %d rc = %d\n",
767 pvreg->name, vmax, rc);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700768 }
769
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700770 return rc;
771}
772
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700773static int krait_power_get_voltage(struct regulator_dev *rdev)
774{
775 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
776
777 return kvreg->uV;
778}
779
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800780static int get_vmax(struct pmic_gang_vreg *pvreg)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700781{
782 int vmax = 0;
783 int v;
784 struct krait_power_vreg *kvreg;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700785
786 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800787 if (!kvreg->online)
788 continue;
789
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700790 v = kvreg->uV;
791
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700792 if (vmax < v)
793 vmax = v;
794 }
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800795
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700796 return vmax;
797}
798
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700799#define ROUND_UP_VOLTAGE(v, res) (DIV_ROUND_UP(v, res) * res)
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800800static int _set_voltage(struct regulator_dev *rdev,
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800801 int orig_krait_uV, int requested_uV)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700802{
803 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
804 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
805 int rc;
806 int vmax;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700807 int coeff_total;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700808
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800809 pr_debug("%s: %d to %d\n", kvreg->name, orig_krait_uV, requested_uV);
810 /*
811 * Assign the voltage before updating the gang voltage as we iterate
812 * over all the core voltages and choose HS or LDO for each of them
813 */
814 kvreg->uV = requested_uV;
815
816 vmax = get_vmax(pvreg);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800817
818 /* round up the pmic voltage as per its resolution */
819 vmax = ROUND_UP_VOLTAGE(vmax, LV_RANGE_STEP);
820
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800821 if (requested_uV > orig_krait_uV)
822 rc = krait_voltage_increase(kvreg, vmax);
823 else
824 rc = krait_voltage_decrease(kvreg, vmax);
825
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800826 if (rc < 0) {
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800827 dev_err(&rdev->dev, "%s failed to set %duV from %duV rc = %d\n",
828 kvreg->name, requested_uV, orig_krait_uV, rc);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800829 }
830
Patrick Cain955d3522013-04-22 16:25:24 -0700831 kvreg->online_at_probe &= ~WAIT_FOR_VOLTAGE;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700832 coeff_total = get_coeff_total(kvreg);
833 /* adjust the phases since coeff2 would have changed */
834 rc = pmic_gang_set_phases(kvreg, coeff_total);
835
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800836 return rc;
837}
838
839static int krait_power_set_voltage(struct regulator_dev *rdev,
840 int min_uV, int max_uV, unsigned *selector)
841{
842 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
843 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
844 int rc;
845
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700846 /*
847 * if the voltage requested is below LDO_THRESHOLD this cpu could
848 * switch to LDO mode. Hence round the voltage as per the LDO
849 * resolution
850 */
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700851 if (min_uV < kvreg->ldo_threshold_uV) {
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700852 if (min_uV < KRAIT_LDO_VOLTAGE_MIN)
853 min_uV = KRAIT_LDO_VOLTAGE_MIN;
854 min_uV = ROUND_UP_VOLTAGE(min_uV, KRAIT_LDO_STEP);
855 }
856
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700857 mutex_lock(&pvreg->krait_power_vregs_lock);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800858 if (!kvreg->online) {
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800859 kvreg->uV = min_uV;
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800860 mutex_unlock(&pvreg->krait_power_vregs_lock);
861 return 0;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700862 }
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700863
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800864 rc = _set_voltage(rdev, kvreg->uV, min_uV);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700865 mutex_unlock(&pvreg->krait_power_vregs_lock);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800866
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700867 return rc;
868}
869
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800870static int krait_power_is_enabled(struct regulator_dev *rdev)
871{
872 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
873
874 return kvreg->online;
875}
876
877static int krait_power_enable(struct regulator_dev *rdev)
878{
879 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
880 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
881 int rc;
882
883 mutex_lock(&pvreg->krait_power_vregs_lock);
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -0700884 __krait_power_mdd_enable(kvreg, true);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800885 kvreg->online = true;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700886 rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800887 if (rc < 0)
888 goto en_err;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800889 /*
890 * since the core is being enabled, behave as if it is increasing
891 * the core voltage
892 */
893 rc = _set_voltage(rdev, 0, kvreg->uV);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800894en_err:
895 mutex_unlock(&pvreg->krait_power_vregs_lock);
896 return rc;
897}
898
899static int krait_power_disable(struct regulator_dev *rdev)
900{
901 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
902 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
903 int rc;
904
905 mutex_lock(&pvreg->krait_power_vregs_lock);
906 kvreg->online = false;
907
Patrick Cain92f4fa12013-04-22 16:23:19 -0700908 rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800909 if (rc < 0)
910 goto dis_err;
911
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800912 rc = _set_voltage(rdev, kvreg->uV, kvreg->uV);
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -0700913 __krait_power_mdd_enable(kvreg, false);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800914dis_err:
915 mutex_unlock(&pvreg->krait_power_vregs_lock);
916 return rc;
917}
918
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700919static struct regulator_ops krait_power_ops = {
920 .get_voltage = krait_power_get_voltage,
921 .set_voltage = krait_power_set_voltage,
922 .get_optimum_mode = krait_power_get_optimum_mode,
923 .set_mode = krait_power_set_mode,
924 .get_mode = krait_power_get_mode,
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800925 .enable = krait_power_enable,
926 .disable = krait_power_disable,
927 .is_enabled = krait_power_is_enabled,
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700928};
929
Abhijeet Dharmapurikar37c47a82013-01-08 18:44:21 -0800930static struct dentry *dent;
931static int get_retention_dbg_uV(void *data, u64 *val)
932{
933 struct pmic_gang_vreg *pvreg = data;
934 struct krait_power_vreg *kvreg;
935
936 mutex_lock(&pvreg->krait_power_vregs_lock);
937 if (!list_empty(&pvreg->krait_power_vregs)) {
938 /* return the retention voltage on just the first cpu */
939 kvreg = list_entry((&pvreg->krait_power_vregs)->next,
940 typeof(*kvreg), link);
941 *val = get_krait_retention_ldo_uv(kvreg);
942 }
943 mutex_unlock(&pvreg->krait_power_vregs_lock);
944 return 0;
945}
946
947static int set_retention_dbg_uV(void *data, u64 val)
948{
949 struct pmic_gang_vreg *pvreg = data;
950 struct krait_power_vreg *kvreg;
951 int retention_uV = val;
952
953 if (!is_between(LDO_UV_MIN, LDO_UV_MAX, retention_uV))
954 return -EINVAL;
955
956 mutex_lock(&pvreg->krait_power_vregs_lock);
957 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
958 kvreg->retention_uV = retention_uV;
959 set_krait_retention_uv(kvreg, retention_uV);
960 }
961 mutex_unlock(&pvreg->krait_power_vregs_lock);
962 return 0;
963}
964DEFINE_SIMPLE_ATTRIBUTE(retention_fops,
965 get_retention_dbg_uV, set_retention_dbg_uV, "%llu\n");
966
Patrick Cain955d3522013-04-22 16:25:24 -0700967#define CPU_PWR_CTL_ONLINE_MASK 0x80
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700968static void kvreg_hw_init(struct krait_power_vreg *kvreg)
969{
Patrick Cain955d3522013-04-22 16:25:24 -0700970 int online;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700971 /*
972 * bhs_cnt value sets the ramp-up time from power collapse,
973 * initialize the ramp up time
974 */
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700975 set_krait_retention_uv(kvreg, kvreg->retention_uV);
976 set_krait_ldo_uv(kvreg, kvreg->ldo_default_uV);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800977
978 /* setup the bandgap that configures the reference to the LDO */
979 writel_relaxed(0x00000190, kvreg->mdd_base + MDD_CONFIG_CTL);
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -0700980 /* Enable MDD */
981 writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800982 mb();
Patrick Cain955d3522013-04-22 16:25:24 -0700983 online = CPU_PWR_CTL_ONLINE_MASK
984 & readl_relaxed(kvreg->reg_base + CPU_PWR_CTL);
985 kvreg->online_at_probe
986 = online ? (WAIT_FOR_LOAD | WAIT_FOR_VOLTAGE) : 0x0;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700987}
988
Stepan Moskovchenko7663b782013-03-08 20:13:06 -0800989static void glb_init(void __iomem *apcs_gcc_base)
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700990{
991 /* configure bi-modal switch */
Stepan Moskovchenko7663b782013-03-08 20:13:06 -0800992 writel_relaxed(0x0008736E, apcs_gcc_base + PWR_GATE_CONFIG);
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700993 /* read kpss version */
Stepan Moskovchenko7663b782013-03-08 20:13:06 -0800994 version = readl_relaxed(apcs_gcc_base + VERSION);
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700995 pr_debug("version= 0x%x\n", version);
996}
997
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700998static int __devinit krait_power_probe(struct platform_device *pdev)
999{
1000 struct krait_power_vreg *kvreg;
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001001 struct resource *res, *res_mdd;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001002 struct regulator_init_data *init_data = pdev->dev.platform_data;
1003 int rc = 0;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -07001004 int headroom_uV, retention_uV, ldo_default_uV, ldo_threshold_uV;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -08001005 int ldo_delta_uV;
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -08001006 int cpu_num;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001007
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001008 if (pdev->dev.of_node) {
1009 /* Get init_data from device tree. */
1010 init_data = of_get_regulator_init_data(&pdev->dev,
1011 pdev->dev.of_node);
1012 init_data->constraints.valid_ops_mask
1013 |= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_DRMS
1014 | REGULATOR_CHANGE_MODE;
1015 init_data->constraints.valid_modes_mask
1016 |= REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE
1017 | REGULATOR_MODE_FAST;
1018 init_data->constraints.input_uV = init_data->constraints.max_uV;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -07001019 rc = of_property_read_u32(pdev->dev.of_node,
1020 "qcom,headroom-voltage",
1021 &headroom_uV);
1022 if (rc < 0) {
1023 pr_err("headroom-voltage missing rc=%d\n", rc);
1024 return rc;
1025 }
1026 if (!is_between(LDO_HDROOM_MIN, LDO_HDROOM_MAX, headroom_uV)) {
1027 pr_err("bad headroom-voltage = %d specified\n",
1028 headroom_uV);
1029 return -EINVAL;
1030 }
1031
1032 rc = of_property_read_u32(pdev->dev.of_node,
1033 "qcom,retention-voltage",
1034 &retention_uV);
1035 if (rc < 0) {
1036 pr_err("retention-voltage missing rc=%d\n", rc);
1037 return rc;
1038 }
1039 if (!is_between(LDO_UV_MIN, LDO_UV_MAX, retention_uV)) {
1040 pr_err("bad retention-voltage = %d specified\n",
1041 retention_uV);
1042 return -EINVAL;
1043 }
1044
1045 rc = of_property_read_u32(pdev->dev.of_node,
1046 "qcom,ldo-default-voltage",
1047 &ldo_default_uV);
1048 if (rc < 0) {
1049 pr_err("ldo-default-voltage missing rc=%d\n", rc);
1050 return rc;
1051 }
1052 if (!is_between(LDO_UV_MIN, LDO_UV_MAX, ldo_default_uV)) {
1053 pr_err("bad ldo-default-voltage = %d specified\n",
1054 ldo_default_uV);
1055 return -EINVAL;
1056 }
1057
1058 rc = of_property_read_u32(pdev->dev.of_node,
1059 "qcom,ldo-threshold-voltage",
1060 &ldo_threshold_uV);
1061 if (rc < 0) {
1062 pr_err("ldo-threshold-voltage missing rc=%d\n", rc);
1063 return rc;
1064 }
1065 if (!is_between(LDO_TH_MIN, LDO_TH_MAX, ldo_threshold_uV)) {
1066 pr_err("bad ldo-threshold-voltage = %d specified\n",
1067 ldo_threshold_uV);
1068 return -EINVAL;
1069 }
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -08001070
1071 rc = of_property_read_u32(pdev->dev.of_node,
1072 "qcom,ldo-delta-voltage",
1073 &ldo_delta_uV);
1074 if (rc < 0) {
1075 pr_err("ldo-delta-voltage missing rc=%d\n", rc);
1076 return rc;
1077 }
1078 if (!is_between(LDO_DELTA_MIN, LDO_DELTA_MAX, ldo_delta_uV)) {
1079 pr_err("bad ldo-delta-voltage = %d specified\n",
1080 ldo_delta_uV);
1081 return -EINVAL;
1082 }
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -08001083 rc = of_property_read_u32(pdev->dev.of_node,
1084 "qcom,cpu-num",
1085 &cpu_num);
1086 if (cpu_num > num_possible_cpus()) {
1087 pr_err("bad cpu-num= %d specified\n", cpu_num);
1088 return -EINVAL;
1089 }
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001090 }
1091
1092 if (!init_data) {
1093 dev_err(&pdev->dev, "init data required.\n");
1094 return -EINVAL;
1095 }
1096
1097 if (!init_data->constraints.name) {
1098 dev_err(&pdev->dev,
1099 "regulator name must be specified in constraints.\n");
1100 return -EINVAL;
1101 }
1102
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001103 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acs");
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001104 if (!res) {
1105 dev_err(&pdev->dev, "missing physical register addresses\n");
1106 return -EINVAL;
1107 }
1108
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001109 res_mdd = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdd");
1110 if (!res_mdd) {
1111 dev_err(&pdev->dev, "missing mdd register addresses\n");
1112 return -EINVAL;
1113 }
1114
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001115 kvreg = devm_kzalloc(&pdev->dev,
1116 sizeof(struct krait_power_vreg), GFP_KERNEL);
1117 if (!kvreg) {
1118 dev_err(&pdev->dev, "kzalloc failed.\n");
1119 return -ENOMEM;
1120 }
1121
1122 kvreg->reg_base = devm_ioremap(&pdev->dev,
1123 res->start, resource_size(res));
1124
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001125 kvreg->mdd_base = devm_ioremap(&pdev->dev,
1126 res_mdd->start, resource_size(res));
1127
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -07001128 kvreg->pvreg = the_gang;
1129 kvreg->name = init_data->constraints.name;
1130 kvreg->desc.name = kvreg->name;
1131 kvreg->desc.ops = &krait_power_ops;
1132 kvreg->desc.type = REGULATOR_VOLTAGE;
1133 kvreg->desc.owner = THIS_MODULE;
Patrick Cain92f4fa12013-04-22 16:23:19 -07001134 kvreg->uV = CORE_VOLTAGE_BOOTUP;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -07001135 kvreg->mode = HS_MODE;
1136 kvreg->desc.ops = &krait_power_ops;
1137 kvreg->headroom_uV = headroom_uV;
1138 kvreg->retention_uV = retention_uV;
1139 kvreg->ldo_default_uV = ldo_default_uV;
1140 kvreg->ldo_threshold_uV = ldo_threshold_uV;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -08001141 kvreg->ldo_delta_uV = ldo_delta_uV;
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -08001142 kvreg->cpu_num = cpu_num;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001143
1144 platform_set_drvdata(pdev, kvreg);
1145
1146 mutex_lock(&the_gang->krait_power_vregs_lock);
Abhijeet Dharmapurikar295c4dc2013-01-08 12:59:01 -08001147 the_gang->pmic_min_uV_for_retention
1148 = min(the_gang->pmic_min_uV_for_retention,
1149 kvreg->retention_uV + kvreg->headroom_uV);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001150 list_add_tail(&kvreg->link, &the_gang->krait_power_vregs);
1151 mutex_unlock(&the_gang->krait_power_vregs_lock);
1152
1153 kvreg->rdev = regulator_register(&kvreg->desc, &pdev->dev, init_data,
1154 kvreg, pdev->dev.of_node);
1155 if (IS_ERR(kvreg->rdev)) {
1156 rc = PTR_ERR(kvreg->rdev);
1157 pr_err("regulator_register failed, rc=%d.\n", rc);
1158 goto out;
1159 }
1160
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -07001161 kvreg_hw_init(kvreg);
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -08001162 per_cpu(krait_vregs, cpu_num) = kvreg;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001163 dev_dbg(&pdev->dev, "id=%d, name=%s\n", pdev->id, kvreg->name);
1164
1165 return 0;
1166out:
1167 mutex_lock(&the_gang->krait_power_vregs_lock);
1168 list_del(&kvreg->link);
1169 mutex_unlock(&the_gang->krait_power_vregs_lock);
1170
1171 platform_set_drvdata(pdev, NULL);
1172 return rc;
1173}
1174
1175static int __devexit krait_power_remove(struct platform_device *pdev)
1176{
1177 struct krait_power_vreg *kvreg = platform_get_drvdata(pdev);
1178 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
1179
1180 mutex_lock(&pvreg->krait_power_vregs_lock);
1181 list_del(&kvreg->link);
1182 mutex_unlock(&pvreg->krait_power_vregs_lock);
1183
1184 regulator_unregister(kvreg->rdev);
1185 platform_set_drvdata(pdev, NULL);
1186 return 0;
1187}
1188
1189static struct of_device_id krait_power_match_table[] = {
1190 { .compatible = "qcom,krait-regulator", },
1191 {}
1192};
1193
1194static struct platform_driver krait_power_driver = {
1195 .probe = krait_power_probe,
1196 .remove = __devexit_p(krait_power_remove),
1197 .driver = {
1198 .name = KRAIT_REGULATOR_DRIVER_NAME,
1199 .of_match_table = krait_power_match_table,
1200 .owner = THIS_MODULE,
1201 },
1202};
1203
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001204static struct of_device_id krait_pdn_match_table[] = {
1205 { .compatible = "qcom,krait-pdn", },
1206 {}
1207};
1208
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -07001209static int boot_cpu_mdd_off(void)
1210{
1211 struct krait_power_vreg *kvreg = per_cpu(krait_vregs, 0);
1212
1213 __krait_power_mdd_enable(kvreg, false);
1214 return 0;
1215}
1216
1217static void boot_cpu_mdd_on(void)
1218{
1219 struct krait_power_vreg *kvreg = per_cpu(krait_vregs, 0);
1220
1221 __krait_power_mdd_enable(kvreg, true);
1222}
1223
1224static struct syscore_ops boot_cpu_mdd_ops = {
1225 .suspend = boot_cpu_mdd_off,
1226 .resume = boot_cpu_mdd_on,
1227};
1228
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001229static int __devinit krait_pdn_probe(struct platform_device *pdev)
1230{
1231 int rc;
1232 bool use_phase_switching = false;
Patrick Cain92f4fa12013-04-22 16:23:19 -07001233 int pfm_threshold;
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001234 struct device *dev = &pdev->dev;
1235 struct device_node *node = dev->of_node;
1236 struct pmic_gang_vreg *pvreg;
Stepan Moskovchenko7663b782013-03-08 20:13:06 -08001237 struct resource *res;
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001238
1239 if (!dev->of_node) {
1240 dev_err(dev, "device tree information missing\n");
1241 return -ENODEV;
1242 }
1243
1244 use_phase_switching = of_property_read_bool(node,
1245 "qcom,use-phase-switching");
Patrick Cain92f4fa12013-04-22 16:23:19 -07001246
1247 rc = of_property_read_u32(node, "qcom,pfm-threshold", &pfm_threshold);
1248 if (rc < 0) {
1249 dev_err(dev, "pfm-threshold missing rc=%d, pfm disabled\n", rc);
1250 return -EINVAL;
1251 }
1252
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001253 pvreg = devm_kzalloc(&pdev->dev,
1254 sizeof(struct pmic_gang_vreg), GFP_KERNEL);
1255 if (!pvreg) {
1256 pr_err("kzalloc failed.\n");
1257 return 0;
1258 }
1259
Stepan Moskovchenko7663b782013-03-08 20:13:06 -08001260 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apcs_gcc");
1261 if (!res) {
1262 dev_err(&pdev->dev, "missing apcs gcc base addresses\n");
1263 return -EINVAL;
1264 }
1265
1266 pvreg->apcs_gcc_base = devm_ioremap(&pdev->dev, res->start,
1267 resource_size(res));
1268
1269 if (pvreg->apcs_gcc_base == NULL)
1270 return -ENOMEM;
1271
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001272 pvreg->name = "pmic_gang";
1273 pvreg->pmic_vmax_uV = PMIC_VOLTAGE_MIN;
1274 pvreg->pmic_phase_count = -EINVAL;
1275 pvreg->retention_enabled = true;
1276 pvreg->pmic_min_uV_for_retention = INT_MAX;
1277 pvreg->use_phase_switching = use_phase_switching;
Patrick Cain92f4fa12013-04-22 16:23:19 -07001278 pvreg->pfm_threshold = pfm_threshold;
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001279
1280 mutex_init(&pvreg->krait_power_vregs_lock);
1281 INIT_LIST_HEAD(&pvreg->krait_power_vregs);
1282 the_gang = pvreg;
1283
1284 pr_debug("name=%s inited\n", pvreg->name);
1285
1286 /* global initializtion */
Stepan Moskovchenko7663b782013-03-08 20:13:06 -08001287 glb_init(pvreg->apcs_gcc_base);
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001288
1289 rc = of_platform_populate(node, NULL, NULL, dev);
1290 if (rc) {
1291 dev_err(dev, "failed to add child nodes, rc=%d\n", rc);
1292 return rc;
1293 }
1294
1295 dent = debugfs_create_dir(KRAIT_REGULATOR_DRIVER_NAME, NULL);
1296 debugfs_create_file("retention_uV",
1297 0644, dent, the_gang, &retention_fops);
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -07001298 register_syscore_ops(&boot_cpu_mdd_ops);
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001299 return 0;
1300}
1301
1302static int __devexit krait_pdn_remove(struct platform_device *pdev)
1303{
1304 the_gang = NULL;
1305 debugfs_remove_recursive(dent);
1306 return 0;
1307}
1308
1309static struct platform_driver krait_pdn_driver = {
1310 .probe = krait_pdn_probe,
1311 .remove = __devexit_p(krait_pdn_remove),
1312 .driver = {
1313 .name = KRAIT_PDN_DRIVER_NAME,
1314 .of_match_table = krait_pdn_match_table,
1315 .owner = THIS_MODULE,
1316 },
1317};
1318
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001319int __init krait_power_init(void)
1320{
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001321 int rc = platform_driver_register(&krait_power_driver);
1322 if (rc) {
1323 pr_err("failed to add %s driver rc = %d\n",
1324 KRAIT_REGULATOR_DRIVER_NAME, rc);
1325 return rc;
1326 }
1327 return platform_driver_register(&krait_pdn_driver);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001328}
1329
1330static void __exit krait_power_exit(void)
1331{
1332 platform_driver_unregister(&krait_power_driver);
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001333 platform_driver_unregister(&krait_pdn_driver);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001334}
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001335module_exit(krait_power_exit);
1336
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001337void secondary_cpu_hs_init(void *base_ptr)
1338{
Matt Wagantall5a58f452013-04-26 12:59:49 -07001339 uint32_t reg_val;
Mahesh Sivasubramanian3dca48e2013-04-12 14:29:57 -06001340 void *l2_saw_base;
Matt Wagantall5a58f452013-04-26 12:59:49 -07001341
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001342 /* Turn on the BHS, turn off LDO Bypass and power down LDO */
Matt Wagantall5a58f452013-04-26 12:59:49 -07001343 reg_val = BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001344 | LDO_PWR_DWN_MASK
1345 | CLK_SRC_DEFAULT << CLK_SRC_SEL_BIT_POS
Matt Wagantall5a58f452013-04-26 12:59:49 -07001346 | BHS_EN_MASK;
1347 writel_relaxed(reg_val, base_ptr + APC_PWR_GATE_CTL);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001348
1349 /* complete the above write before the delay */
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001350 mb();
Matt Wagantall5a58f452013-04-26 12:59:49 -07001351 /* wait for the bhs to settle */
1352 udelay(BHS_SETTLING_DELAY_US);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001353
Matt Wagantall5a58f452013-04-26 12:59:49 -07001354 /* Turn on BHS segments */
1355 reg_val |= BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS;
1356 writel_relaxed(reg_val, base_ptr + APC_PWR_GATE_CTL);
1357
1358 /* complete the above write before the delay */
1359 mb();
1360 /* wait for the bhs to settle */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001361 udelay(BHS_SETTLING_DELAY_US);
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001362
1363 /* Finally turn on the bypass so that BHS supplies power */
Matt Wagantall5a58f452013-04-26 12:59:49 -07001364 reg_val |= LDO_BYP_MASK;
1365 writel_relaxed(reg_val, base_ptr + APC_PWR_GATE_CTL);
Mahesh Sivasubramanian3dca48e2013-04-12 14:29:57 -06001366
1367 if (the_gang && the_gang->manage_phases)
1368 return;
1369
1370 /*
1371 * If the driver has not yet started to manage phases then enable
1372 * max phases.
1373 */
1374 l2_saw_base = ioremap_nocache(MSM_L2_SAW_PHYS, SZ_4K);
1375 if (!l2_saw_base) {
1376 __WARN();
1377 return;
1378 }
1379 writel_relaxed(0x10003, l2_saw_base + 0x1c);
1380 mb();
1381 udelay(PHASE_SETTLING_TIME_US);
1382
1383 iounmap(l2_saw_base);
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001384}
1385
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001386MODULE_LICENSE("GPL v2");
1387MODULE_DESCRIPTION("KRAIT POWER regulator driver");
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001388MODULE_ALIAS("platform:"KRAIT_REGULATOR_DRIVER_NAME);