blob: ed9f63941fefc0de934d52bf3b7df235219e6f51 [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
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700136/**
137 * struct pmic_gang_vreg -
138 * @name: the string used to represent the gang
139 * @pmic_vmax_uV: the current pmic gang voltage
140 * @pmic_phase_count: the number of phases turned on in the gang
141 * @krait_power_vregs: a list of krait consumers this gang supplies to
142 * @krait_power_vregs_lock: lock to prevent simultaneous access to the list
143 * and its nodes. This needs to be taken by each
144 * regulator's callback functions to prevent
145 * simultaneous updates to the pmic's phase
146 * voltage.
Patrick Cain92f4fa12013-04-22 16:23:19 -0700147 * @apcs_gcc_base: virtual address of the APCS GCC registers
148 * @manage_phases: begin phase control
149 * @pfm_threshold: the sum of coefficients below which PFM can be
150 * enabled
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700151 */
152struct pmic_gang_vreg {
153 const char *name;
154 int pmic_vmax_uV;
155 int pmic_phase_count;
156 struct list_head krait_power_vregs;
157 struct mutex krait_power_vregs_lock;
Abhijeet Dharmapurikar6a42ef82012-10-18 19:37:36 -0700158 bool pfm_mode;
Abhijeet Dharmapurikar295c4dc2013-01-08 12:59:01 -0800159 int pmic_min_uV_for_retention;
160 bool retention_enabled;
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -0800161 bool use_phase_switching;
Stepan Moskovchenko7663b782013-03-08 20:13:06 -0800162 void __iomem *apcs_gcc_base;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700163 bool manage_phases;
164 int pfm_threshold;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700165};
166
167static struct pmic_gang_vreg *the_gang;
168
169enum krait_supply_mode {
170 HS_MODE = REGULATOR_MODE_NORMAL,
171 LDO_MODE = REGULATOR_MODE_IDLE,
172};
173
Patrick Cain955d3522013-04-22 16:25:24 -0700174#define WAIT_FOR_LOAD 0x2
175#define WAIT_FOR_VOLTAGE 0x1
176
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700177struct krait_power_vreg {
178 struct list_head link;
179 struct regulator_desc desc;
180 struct regulator_dev *rdev;
181 const char *name;
182 struct pmic_gang_vreg *pvreg;
183 int uV;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700184 int load;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700185 enum krait_supply_mode mode;
186 void __iomem *reg_base;
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800187 void __iomem *mdd_base;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700188 int ldo_default_uV;
189 int retention_uV;
190 int headroom_uV;
191 int ldo_threshold_uV;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800192 int ldo_delta_uV;
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -0800193 int cpu_num;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700194 int coeff1;
195 int coeff2;
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800196 bool online;
Patrick Cain955d3522013-04-22 16:25:24 -0700197 int online_at_probe;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700198};
199
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -0800200DEFINE_PER_CPU(struct krait_power_vreg *, krait_vregs);
201
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700202static u32 version;
203
Abhijeet Dharmapurikar37c47a82013-01-08 18:44:21 -0800204static int is_between(int left, int right, int value)
205{
206 if (left >= right && left >= value && value >= right)
207 return 1;
208 if (left <= right && left <= value && value <= right)
209 return 1;
210 return 0;
211}
212
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700213static void krait_masked_write(struct krait_power_vreg *kvreg,
214 int reg, uint32_t mask, uint32_t val)
215{
216 uint32_t reg_val;
217
218 reg_val = readl_relaxed(kvreg->reg_base + reg);
219 reg_val &= ~mask;
220 reg_val |= (val & mask);
221 writel_relaxed(reg_val, kvreg->reg_base + reg);
222
223 /*
224 * Barrier to ensure that the reads and writes from
225 * other regulator regions (they are 1k apart) execute in
226 * order to the above write.
227 */
228 mb();
229}
230
Abhijeet Dharmapurikar37c47a82013-01-08 18:44:21 -0800231static int get_krait_retention_ldo_uv(struct krait_power_vreg *kvreg)
232{
233 uint32_t reg_val;
234 int uV;
235
236 reg_val = readl_relaxed(kvreg->reg_base + APC_LDO_VREF_SET);
237 reg_val &= VREF_RET_MASK;
238 reg_val >>= VREF_RET_POS;
239
240 if (reg_val == 0)
241 uV = 0;
242 else
243 uV = KRAIT_LDO_VOLTAGE_OFFSET + reg_val * KRAIT_LDO_STEP;
244
245 return uV;
246}
247
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700248static int get_krait_ldo_uv(struct krait_power_vreg *kvreg)
249{
250 uint32_t reg_val;
251 int uV;
252
253 reg_val = readl_relaxed(kvreg->reg_base + APC_LDO_VREF_SET);
254 reg_val &= VREF_LDO_MASK;
255 reg_val >>= VREF_LDO_BIT_POS;
256
257 if (reg_val == 0)
258 uV = 0;
259 else
260 uV = KRAIT_LDO_VOLTAGE_OFFSET + reg_val * KRAIT_LDO_STEP;
261
262 return uV;
263}
264
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700265static int set_krait_retention_uv(struct krait_power_vreg *kvreg, int uV)
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700266{
267 uint32_t reg_val;
268
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700269 reg_val = DIV_ROUND_UP(uV - KRAIT_LDO_VOLTAGE_OFFSET, KRAIT_LDO_STEP);
270 krait_masked_write(kvreg, APC_LDO_VREF_SET, VREF_RET_MASK,
271 reg_val << VREF_RET_POS);
272
273 return 0;
274}
275
276static int set_krait_ldo_uv(struct krait_power_vreg *kvreg, int uV)
277{
278 uint32_t reg_val;
279
280 reg_val = DIV_ROUND_UP(uV - KRAIT_LDO_VOLTAGE_OFFSET, KRAIT_LDO_STEP);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700281 krait_masked_write(kvreg, APC_LDO_VREF_SET, VREF_LDO_MASK,
282 reg_val << VREF_LDO_BIT_POS);
283
284 return 0;
285}
286
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -0800287static int __krait_power_mdd_enable(struct krait_power_vreg *kvreg, bool on)
288{
289 if (on) {
290 writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
291 /* complete the above write before the delay */
292 mb();
293 udelay(MDD_SETTLING_DELAY_US);
294 } else {
295 writel_relaxed(0x00000000, kvreg->mdd_base + MDD_MODE);
296 /*
297 * complete the above write before other accesses
298 * to krait regulator
299 */
300 mb();
301 }
302 return 0;
303}
304
Patrick Cain92f4fa12013-04-22 16:23:19 -0700305#define COEFF2_UV_THRESHOLD 850000
306static int get_coeff2(int krait_uV)
307{
308 int coeff2 = 0;
309 int krait_mV = krait_uV / 1000;
310
311 if (krait_uV <= COEFF2_UV_THRESHOLD)
312 coeff2 = (612229 * krait_mV) / 1000 - 211258;
313 else
314 coeff2 = (892564 * krait_mV) / 1000 - 449543;
315
316 return coeff2;
317}
318
319static int get_coeff1(int actual_uV, int requested_uV, int load)
320{
321 int ratio = actual_uV * 1000 / requested_uV;
322 int coeff1 = 330 * load + (load * 673 * ratio / 1000);
323
324 return coeff1;
325}
326
327static int get_coeff_total(struct krait_power_vreg *from)
328{
329 int coeff_total = 0;
330 struct krait_power_vreg *kvreg;
331 struct pmic_gang_vreg *pvreg = from->pvreg;
332
333 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
334 if (!kvreg->online)
335 continue;
336
337 if (kvreg->mode == LDO_MODE) {
338 kvreg->coeff1 =
339 get_coeff1(kvreg->uV - kvreg->ldo_delta_uV,
340 kvreg->uV, kvreg->load);
341 kvreg->coeff2 =
342 get_coeff2(kvreg->uV - kvreg->ldo_delta_uV);
343 } else {
344 kvreg->coeff1 =
345 get_coeff1(pvreg->pmic_vmax_uV,
346 kvreg->uV, kvreg->load);
347 kvreg->coeff2 = get_coeff2(pvreg->pmic_vmax_uV);
348 }
349 coeff_total += kvreg->coeff1 + kvreg->coeff2;
350 }
351
352 return coeff_total;
353}
354
355static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
356{
357 pr_debug("programming phase_count = %d\n", phase_count);
358 if (pvreg->use_phase_switching)
359 /*
360 * note the PMIC sets the phase count to one more than
361 * the value in the register - hence subtract 1 from it
362 */
363 return msm_spm_apcs_set_phase(phase_count - 1);
364 else
365 return 0;
366}
367
368static int num_online(struct pmic_gang_vreg *pvreg)
369{
370 int online_total = 0;
371 struct krait_power_vreg *kvreg;
372
373 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
374 if (kvreg->online)
375 online_total++;
376 }
377 return online_total;
378}
379
380static int get_total_load(struct krait_power_vreg *from)
381{
382 int load_total = 0;
383 struct krait_power_vreg *kvreg;
384 struct pmic_gang_vreg *pvreg = from->pvreg;
385
386 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
387 if (!kvreg->online)
388 continue;
389 load_total += kvreg->load;
390 }
391
392 return load_total;
393}
394
Patrick Cain955d3522013-04-22 16:25:24 -0700395static bool enable_phase_management(struct pmic_gang_vreg *pvreg)
396{
397 struct krait_power_vreg *kvreg;
398
399 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
400 pr_debug("%s online_at_probe:0x%x\n", kvreg->name,
401 kvreg->online_at_probe);
402 if (kvreg->online_at_probe)
403 return false;
404 }
405 return true;
406}
407
Patrick Cain92f4fa12013-04-22 16:23:19 -0700408#define PMIC_FTS_MODE_PFM 0x00
409#define PMIC_FTS_MODE_PWM 0x80
410#define ONE_PHASE_COEFF 1000000
411#define TWO_PHASE_COEFF 2000000
412
413#define PHASE_SETTLING_TIME_US 10
414static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
415 int coeff_total)
416{
417 struct pmic_gang_vreg *pvreg = from->pvreg;
418 int phase_count;
419 int rc = 0;
420 int n_online = num_online(pvreg);
421 int load_total;
422
423 load_total = get_total_load(from);
424
Patrick Cain955d3522013-04-22 16:25:24 -0700425 if (pvreg->manage_phases == false) {
426 if (enable_phase_management(pvreg))
427 pvreg->manage_phases = true;
428 else
429 return 0;
430 }
Patrick Cain92f4fa12013-04-22 16:23:19 -0700431
432 /* First check if the coeff is low for PFM mode */
433 if (load_total <= pvreg->pfm_threshold && n_online == 1) {
434 if (!pvreg->pfm_mode) {
435 rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
436 if (rc) {
437 pr_err("%s PFM en failed load_t %d rc = %d\n",
438 from->name, load_total, rc);
439 return rc;
440 } else {
441 pvreg->pfm_mode = true;
442 }
443 }
444 return rc;
445 }
446
447 /* coeff is high switch to PWM mode before changing phases */
448 if (pvreg->pfm_mode) {
449 rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
450 if (rc) {
451 pr_err("%s PFM exit failed load %d rc = %d\n",
452 from->name, coeff_total, rc);
453 return rc;
454 } else {
455 pvreg->pfm_mode = false;
456 }
457 }
458
459 /* calculate phases */
460 if (coeff_total < ONE_PHASE_COEFF)
461 phase_count = 1;
462 else if (coeff_total < TWO_PHASE_COEFF)
463 phase_count = 2;
464 else
465 phase_count = 4;
466
467 /* don't increase the phase count higher than number of online cpus */
468 if (phase_count > n_online)
469 phase_count = n_online;
470
471 if (phase_count != pvreg->pmic_phase_count) {
472 rc = set_pmic_gang_phases(pvreg, phase_count);
473 if (rc < 0) {
474 pr_err("%s failed set phase %d rc = %d\n",
475 from->name, phase_count, rc);
476 return rc;
477 }
478
479 /* complete the writes before the delay */
480 mb();
481
482 /*
483 * delay until the phases are settled when
484 * the count is raised
485 */
486 if (phase_count > pvreg->pmic_phase_count)
487 udelay(PHASE_SETTLING_TIME_US);
488
489 pvreg->pmic_phase_count = phase_count;
490 }
491
492 return rc;
493}
494
495static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
496 int input_uV, int output_uV, int load)
497{
498 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
499 int coeff_total;
500 int rc;
501
Patrick Cain955d3522013-04-22 16:25:24 -0700502 kvreg->online_at_probe &= ~WAIT_FOR_LOAD;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700503 coeff_total = get_coeff_total(kvreg);
504
505 rc = pmic_gang_set_phases(kvreg, coeff_total);
506 if (rc < 0) {
507 dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
508 kvreg->name, coeff_total, rc);
509 }
510
511 return kvreg->mode;
512}
513
514static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
515 int input_uV, int output_uV, int load_uA)
516{
517 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
518 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
519 int rc;
520
521 mutex_lock(&pvreg->krait_power_vregs_lock);
522 kvreg->load = load_uA;
523 if (!kvreg->online) {
524 mutex_unlock(&pvreg->krait_power_vregs_lock);
525 return kvreg->mode;
526 }
527
528 rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
529 mutex_unlock(&pvreg->krait_power_vregs_lock);
530
531 return rc;
532}
533
534static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
535{
536 return 0;
537}
538
539static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
540{
541 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
542
543 return kvreg->mode;
544}
545
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700546static int switch_to_using_hs(struct krait_power_vreg *kvreg)
547{
548 if (kvreg->mode == HS_MODE)
549 return 0;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700550 /* enable bhs */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800551 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
552 BHS_SEG_EN_MASK | BHS_EN_MASK,
553 BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS | BHS_EN_MASK);
554
555 /* complete the above write before the delay */
556 mb();
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700557
558 /*
559 * wait for the bhs to settle - note that
560 * after the voltage has settled both BHS and LDO are supplying power
561 * to the krait. This avoids glitches during switching
562 */
563 udelay(BHS_SETTLING_DELAY_US);
564
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800565 /*
566 * enable ldo bypass - the krait is powered still by LDO since
567 * LDO is enabled
568 */
569 krait_masked_write(kvreg, APC_PWR_GATE_CTL, LDO_BYP_MASK, LDO_BYP_MASK);
570
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700571 /* disable ldo - only the BHS provides voltage to the cpu after this */
572 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
573 LDO_PWR_DWN_MASK, LDO_PWR_DWN_MASK);
574
575 kvreg->mode = HS_MODE;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800576 pr_debug("%s using BHS\n", kvreg->name);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700577 return 0;
578}
579
580static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
581{
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800582 if (kvreg->mode == LDO_MODE
583 && get_krait_ldo_uv(kvreg) == kvreg->uV - kvreg->ldo_delta_uV)
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700584 return 0;
585
586 /*
587 * if the krait is in ldo mode and a voltage change is requested on the
588 * ldo switch to using hs before changing ldo voltage
589 */
590 if (kvreg->mode == LDO_MODE)
591 switch_to_using_hs(kvreg);
592
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800593 set_krait_ldo_uv(kvreg, kvreg->uV - kvreg->ldo_delta_uV);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700594
595 /*
596 * enable ldo - note that both LDO and BHS are are supplying voltage to
597 * the cpu after this. This avoids glitches during switching from BHS
598 * to LDO.
599 */
600 krait_masked_write(kvreg, APC_PWR_GATE_CTL, LDO_PWR_DWN_MASK, 0);
601
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800602 /* complete the writes before the delay */
603 mb();
604
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700605 /* wait for the ldo to settle */
606 udelay(LDO_SETTLING_DELAY_US);
607
608 /*
609 * disable BHS and disable LDO bypass seperate from enabling
610 * the LDO above.
611 */
612 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
613 BHS_EN_MASK | LDO_BYP_MASK, 0);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800614 krait_masked_write(kvreg, APC_PWR_GATE_CTL, BHS_SEG_EN_MASK, 0);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700615
616 kvreg->mode = LDO_MODE;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800617 pr_debug("%s using LDO\n", kvreg->name);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700618 return 0;
619}
620
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800621static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700622{
623 int setpoint;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800624 int rc;
625
626 if (pvreg->pmic_vmax_uV == uV)
627 return 0;
628
629 pr_debug("%d\n", uV);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700630
631 if (uV < PMIC_VOLTAGE_MIN) {
632 pr_err("requested %d < %d, restricting it to %d\n",
633 uV, PMIC_VOLTAGE_MIN, PMIC_VOLTAGE_MIN);
634 uV = PMIC_VOLTAGE_MIN;
635 }
636 if (uV > PMIC_VOLTAGE_MAX) {
637 pr_err("requested %d > %d, restricting it to %d\n",
638 uV, PMIC_VOLTAGE_MAX, PMIC_VOLTAGE_MAX);
639 uV = PMIC_VOLTAGE_MAX;
640 }
641
Abhijeet Dharmapurikar295c4dc2013-01-08 12:59:01 -0800642 if (uV < pvreg->pmic_min_uV_for_retention) {
643 if (pvreg->retention_enabled) {
644 pr_debug("Disabling Retention pmic = %duV, pmic_min_uV_for_retention = %duV",
645 uV, pvreg->pmic_min_uV_for_retention);
646 msm_pm_enable_retention(false);
647 pvreg->retention_enabled = false;
648 }
649 } else {
650 if (!pvreg->retention_enabled) {
651 pr_debug("Enabling Retention pmic = %duV, pmic_min_uV_for_retention = %duV",
652 uV, pvreg->pmic_min_uV_for_retention);
653 msm_pm_enable_retention(true);
654 pvreg->retention_enabled = true;
655 }
656 }
657
Abhijeet Dharmapurikard4f38da2012-08-08 21:42:06 -0700658 setpoint = DIV_ROUND_UP(uV, LV_RANGE_STEP);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800659
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800660 rc = msm_spm_apcs_set_vdd(setpoint);
661 if (rc < 0)
662 pr_err("could not set %duV setpt = 0x%x rc = %d\n",
663 uV, setpoint, rc);
664 else
665 pvreg->pmic_vmax_uV = uV;
666
667 return rc;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700668}
669
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800670static int configure_ldo_or_hs_all(struct krait_power_vreg *from, int vmax)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700671{
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700672 struct pmic_gang_vreg *pvreg = from->pvreg;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700673 struct krait_power_vreg *kvreg;
674 int rc = 0;
675
676 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800677 if (!kvreg->online)
678 continue;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800679 if (kvreg->uV <= kvreg->ldo_threshold_uV
680 && kvreg->uV - kvreg->ldo_delta_uV + kvreg->headroom_uV
681 <= vmax) {
682 rc = switch_to_using_ldo(kvreg);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700683 if (rc < 0) {
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800684 pr_err("could not switch %s to ldo rc = %d\n",
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700685 kvreg->name, rc);
686 return rc;
687 }
688 } else {
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800689 rc = switch_to_using_hs(kvreg);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700690 if (rc < 0) {
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800691 pr_err("could not switch %s to hs rc = %d\n",
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700692 kvreg->name, rc);
693 return rc;
694 }
695 }
696 }
697
698 return rc;
699}
700
701#define SLEW_RATE 2994
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800702static int krait_voltage_increase(struct krait_power_vreg *from,
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700703 int vmax)
704{
705 struct pmic_gang_vreg *pvreg = from->pvreg;
706 int rc = 0;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700707 int settling_us;
708
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700709 /*
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800710 * since krait voltage is increasing set the gang voltage
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700711 * prior to changing ldo/hs states of the requesting krait
712 */
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800713 rc = set_pmic_gang_voltage(pvreg, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700714 if (rc < 0) {
715 dev_err(&from->rdev->dev, "%s failed set voltage %d rc = %d\n",
716 pvreg->name, vmax, rc);
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800717 return rc;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700718 }
719
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800720
721 /* complete the above writes before the delay */
722 mb();
723
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700724 /* delay until the voltage is settled when it is raised */
725 settling_us = DIV_ROUND_UP(vmax - pvreg->pmic_vmax_uV, SLEW_RATE);
726 udelay(settling_us);
727
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800728 rc = configure_ldo_or_hs_all(from, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700729 if (rc < 0) {
730 dev_err(&from->rdev->dev, "%s failed ldo/hs conf %d rc = %d\n",
731 pvreg->name, vmax, rc);
732 }
733
734 return rc;
735}
736
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800737static int krait_voltage_decrease(struct krait_power_vreg *from,
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700738 int vmax)
739{
740 struct pmic_gang_vreg *pvreg = from->pvreg;
741 int rc = 0;
742
743 /*
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800744 * since krait voltage is decreasing ldos might get out of their
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700745 * operating range. Hence configure such kraits to be in hs mode prior
746 * to setting the pmic gang voltage
747 */
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800748 rc = configure_ldo_or_hs_all(from, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700749 if (rc < 0) {
750 dev_err(&from->rdev->dev, "%s failed ldo/hs conf %d rc = %d\n",
751 pvreg->name, vmax, rc);
752 return rc;
753 }
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700754
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800755 rc = set_pmic_gang_voltage(pvreg, vmax);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700756 if (rc < 0) {
757 dev_err(&from->rdev->dev, "%s failed set voltage %d rc = %d\n",
758 pvreg->name, vmax, rc);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700759 }
760
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700761 return rc;
762}
763
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700764static int krait_power_get_voltage(struct regulator_dev *rdev)
765{
766 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
767
768 return kvreg->uV;
769}
770
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800771static int get_vmax(struct pmic_gang_vreg *pvreg)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700772{
773 int vmax = 0;
774 int v;
775 struct krait_power_vreg *kvreg;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700776
777 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800778 if (!kvreg->online)
779 continue;
780
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700781 v = kvreg->uV;
782
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700783 if (vmax < v)
784 vmax = v;
785 }
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800786
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700787 return vmax;
788}
789
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700790#define ROUND_UP_VOLTAGE(v, res) (DIV_ROUND_UP(v, res) * res)
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800791static int _set_voltage(struct regulator_dev *rdev,
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800792 int orig_krait_uV, int requested_uV)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700793{
794 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
795 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
796 int rc;
797 int vmax;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700798 int coeff_total;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700799
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800800 pr_debug("%s: %d to %d\n", kvreg->name, orig_krait_uV, requested_uV);
801 /*
802 * Assign the voltage before updating the gang voltage as we iterate
803 * over all the core voltages and choose HS or LDO for each of them
804 */
805 kvreg->uV = requested_uV;
806
807 vmax = get_vmax(pvreg);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800808
809 /* round up the pmic voltage as per its resolution */
810 vmax = ROUND_UP_VOLTAGE(vmax, LV_RANGE_STEP);
811
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800812 if (requested_uV > orig_krait_uV)
813 rc = krait_voltage_increase(kvreg, vmax);
814 else
815 rc = krait_voltage_decrease(kvreg, vmax);
816
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800817 if (rc < 0) {
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800818 dev_err(&rdev->dev, "%s failed to set %duV from %duV rc = %d\n",
819 kvreg->name, requested_uV, orig_krait_uV, rc);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800820 }
821
Patrick Cain955d3522013-04-22 16:25:24 -0700822 kvreg->online_at_probe &= ~WAIT_FOR_VOLTAGE;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700823 coeff_total = get_coeff_total(kvreg);
824 /* adjust the phases since coeff2 would have changed */
825 rc = pmic_gang_set_phases(kvreg, coeff_total);
826
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800827 return rc;
828}
829
830static int krait_power_set_voltage(struct regulator_dev *rdev,
831 int min_uV, int max_uV, unsigned *selector)
832{
833 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
834 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
835 int rc;
836
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700837 /*
838 * if the voltage requested is below LDO_THRESHOLD this cpu could
839 * switch to LDO mode. Hence round the voltage as per the LDO
840 * resolution
841 */
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700842 if (min_uV < kvreg->ldo_threshold_uV) {
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700843 if (min_uV < KRAIT_LDO_VOLTAGE_MIN)
844 min_uV = KRAIT_LDO_VOLTAGE_MIN;
845 min_uV = ROUND_UP_VOLTAGE(min_uV, KRAIT_LDO_STEP);
846 }
847
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700848 mutex_lock(&pvreg->krait_power_vregs_lock);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800849 if (!kvreg->online) {
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800850 kvreg->uV = min_uV;
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800851 mutex_unlock(&pvreg->krait_power_vregs_lock);
852 return 0;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700853 }
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700854
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800855 rc = _set_voltage(rdev, kvreg->uV, min_uV);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700856 mutex_unlock(&pvreg->krait_power_vregs_lock);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800857
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700858 return rc;
859}
860
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800861static int krait_power_is_enabled(struct regulator_dev *rdev)
862{
863 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
864
865 return kvreg->online;
866}
867
868static int krait_power_enable(struct regulator_dev *rdev)
869{
870 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
871 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
872 int rc;
873
874 mutex_lock(&pvreg->krait_power_vregs_lock);
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -0700875 __krait_power_mdd_enable(kvreg, true);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800876 kvreg->online = true;
Patrick Cain92f4fa12013-04-22 16:23:19 -0700877 rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800878 if (rc < 0)
879 goto en_err;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800880 /*
881 * since the core is being enabled, behave as if it is increasing
882 * the core voltage
883 */
884 rc = _set_voltage(rdev, 0, kvreg->uV);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800885en_err:
886 mutex_unlock(&pvreg->krait_power_vregs_lock);
887 return rc;
888}
889
890static int krait_power_disable(struct regulator_dev *rdev)
891{
892 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
893 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
894 int rc;
895
896 mutex_lock(&pvreg->krait_power_vregs_lock);
897 kvreg->online = false;
898
Patrick Cain92f4fa12013-04-22 16:23:19 -0700899 rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800900 if (rc < 0)
901 goto dis_err;
902
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800903 rc = _set_voltage(rdev, kvreg->uV, kvreg->uV);
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -0700904 __krait_power_mdd_enable(kvreg, false);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800905dis_err:
906 mutex_unlock(&pvreg->krait_power_vregs_lock);
907 return rc;
908}
909
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700910static struct regulator_ops krait_power_ops = {
911 .get_voltage = krait_power_get_voltage,
912 .set_voltage = krait_power_set_voltage,
913 .get_optimum_mode = krait_power_get_optimum_mode,
914 .set_mode = krait_power_set_mode,
915 .get_mode = krait_power_get_mode,
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800916 .enable = krait_power_enable,
917 .disable = krait_power_disable,
918 .is_enabled = krait_power_is_enabled,
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700919};
920
Abhijeet Dharmapurikar37c47a82013-01-08 18:44:21 -0800921static struct dentry *dent;
922static int get_retention_dbg_uV(void *data, u64 *val)
923{
924 struct pmic_gang_vreg *pvreg = data;
925 struct krait_power_vreg *kvreg;
926
927 mutex_lock(&pvreg->krait_power_vregs_lock);
928 if (!list_empty(&pvreg->krait_power_vregs)) {
929 /* return the retention voltage on just the first cpu */
930 kvreg = list_entry((&pvreg->krait_power_vregs)->next,
931 typeof(*kvreg), link);
932 *val = get_krait_retention_ldo_uv(kvreg);
933 }
934 mutex_unlock(&pvreg->krait_power_vregs_lock);
935 return 0;
936}
937
938static int set_retention_dbg_uV(void *data, u64 val)
939{
940 struct pmic_gang_vreg *pvreg = data;
941 struct krait_power_vreg *kvreg;
942 int retention_uV = val;
943
944 if (!is_between(LDO_UV_MIN, LDO_UV_MAX, retention_uV))
945 return -EINVAL;
946
947 mutex_lock(&pvreg->krait_power_vregs_lock);
948 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
949 kvreg->retention_uV = retention_uV;
950 set_krait_retention_uv(kvreg, retention_uV);
951 }
952 mutex_unlock(&pvreg->krait_power_vregs_lock);
953 return 0;
954}
955DEFINE_SIMPLE_ATTRIBUTE(retention_fops,
956 get_retention_dbg_uV, set_retention_dbg_uV, "%llu\n");
957
Patrick Cain955d3522013-04-22 16:25:24 -0700958#define CPU_PWR_CTL_ONLINE_MASK 0x80
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700959static void kvreg_hw_init(struct krait_power_vreg *kvreg)
960{
Patrick Cain955d3522013-04-22 16:25:24 -0700961 int online;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700962 /*
963 * bhs_cnt value sets the ramp-up time from power collapse,
964 * initialize the ramp up time
965 */
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700966 set_krait_retention_uv(kvreg, kvreg->retention_uV);
967 set_krait_ldo_uv(kvreg, kvreg->ldo_default_uV);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800968
969 /* setup the bandgap that configures the reference to the LDO */
970 writel_relaxed(0x00000190, kvreg->mdd_base + MDD_CONFIG_CTL);
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -0700971 /* Enable MDD */
972 writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800973 mb();
Patrick Cain955d3522013-04-22 16:25:24 -0700974 online = CPU_PWR_CTL_ONLINE_MASK
975 & readl_relaxed(kvreg->reg_base + CPU_PWR_CTL);
976 kvreg->online_at_probe
977 = online ? (WAIT_FOR_LOAD | WAIT_FOR_VOLTAGE) : 0x0;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700978}
979
Stepan Moskovchenko7663b782013-03-08 20:13:06 -0800980static void glb_init(void __iomem *apcs_gcc_base)
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700981{
982 /* configure bi-modal switch */
Stepan Moskovchenko7663b782013-03-08 20:13:06 -0800983 writel_relaxed(0x0008736E, apcs_gcc_base + PWR_GATE_CONFIG);
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700984 /* read kpss version */
Stepan Moskovchenko7663b782013-03-08 20:13:06 -0800985 version = readl_relaxed(apcs_gcc_base + VERSION);
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700986 pr_debug("version= 0x%x\n", version);
987}
988
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700989static int __devinit krait_power_probe(struct platform_device *pdev)
990{
991 struct krait_power_vreg *kvreg;
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800992 struct resource *res, *res_mdd;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700993 struct regulator_init_data *init_data = pdev->dev.platform_data;
994 int rc = 0;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700995 int headroom_uV, retention_uV, ldo_default_uV, ldo_threshold_uV;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800996 int ldo_delta_uV;
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -0800997 int cpu_num;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700998
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700999 if (pdev->dev.of_node) {
1000 /* Get init_data from device tree. */
1001 init_data = of_get_regulator_init_data(&pdev->dev,
1002 pdev->dev.of_node);
1003 init_data->constraints.valid_ops_mask
1004 |= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_DRMS
1005 | REGULATOR_CHANGE_MODE;
1006 init_data->constraints.valid_modes_mask
1007 |= REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE
1008 | REGULATOR_MODE_FAST;
1009 init_data->constraints.input_uV = init_data->constraints.max_uV;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -07001010 rc = of_property_read_u32(pdev->dev.of_node,
1011 "qcom,headroom-voltage",
1012 &headroom_uV);
1013 if (rc < 0) {
1014 pr_err("headroom-voltage missing rc=%d\n", rc);
1015 return rc;
1016 }
1017 if (!is_between(LDO_HDROOM_MIN, LDO_HDROOM_MAX, headroom_uV)) {
1018 pr_err("bad headroom-voltage = %d specified\n",
1019 headroom_uV);
1020 return -EINVAL;
1021 }
1022
1023 rc = of_property_read_u32(pdev->dev.of_node,
1024 "qcom,retention-voltage",
1025 &retention_uV);
1026 if (rc < 0) {
1027 pr_err("retention-voltage missing rc=%d\n", rc);
1028 return rc;
1029 }
1030 if (!is_between(LDO_UV_MIN, LDO_UV_MAX, retention_uV)) {
1031 pr_err("bad retention-voltage = %d specified\n",
1032 retention_uV);
1033 return -EINVAL;
1034 }
1035
1036 rc = of_property_read_u32(pdev->dev.of_node,
1037 "qcom,ldo-default-voltage",
1038 &ldo_default_uV);
1039 if (rc < 0) {
1040 pr_err("ldo-default-voltage missing rc=%d\n", rc);
1041 return rc;
1042 }
1043 if (!is_between(LDO_UV_MIN, LDO_UV_MAX, ldo_default_uV)) {
1044 pr_err("bad ldo-default-voltage = %d specified\n",
1045 ldo_default_uV);
1046 return -EINVAL;
1047 }
1048
1049 rc = of_property_read_u32(pdev->dev.of_node,
1050 "qcom,ldo-threshold-voltage",
1051 &ldo_threshold_uV);
1052 if (rc < 0) {
1053 pr_err("ldo-threshold-voltage missing rc=%d\n", rc);
1054 return rc;
1055 }
1056 if (!is_between(LDO_TH_MIN, LDO_TH_MAX, ldo_threshold_uV)) {
1057 pr_err("bad ldo-threshold-voltage = %d specified\n",
1058 ldo_threshold_uV);
1059 return -EINVAL;
1060 }
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -08001061
1062 rc = of_property_read_u32(pdev->dev.of_node,
1063 "qcom,ldo-delta-voltage",
1064 &ldo_delta_uV);
1065 if (rc < 0) {
1066 pr_err("ldo-delta-voltage missing rc=%d\n", rc);
1067 return rc;
1068 }
1069 if (!is_between(LDO_DELTA_MIN, LDO_DELTA_MAX, ldo_delta_uV)) {
1070 pr_err("bad ldo-delta-voltage = %d specified\n",
1071 ldo_delta_uV);
1072 return -EINVAL;
1073 }
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -08001074 rc = of_property_read_u32(pdev->dev.of_node,
1075 "qcom,cpu-num",
1076 &cpu_num);
1077 if (cpu_num > num_possible_cpus()) {
1078 pr_err("bad cpu-num= %d specified\n", cpu_num);
1079 return -EINVAL;
1080 }
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001081 }
1082
1083 if (!init_data) {
1084 dev_err(&pdev->dev, "init data required.\n");
1085 return -EINVAL;
1086 }
1087
1088 if (!init_data->constraints.name) {
1089 dev_err(&pdev->dev,
1090 "regulator name must be specified in constraints.\n");
1091 return -EINVAL;
1092 }
1093
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001094 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acs");
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001095 if (!res) {
1096 dev_err(&pdev->dev, "missing physical register addresses\n");
1097 return -EINVAL;
1098 }
1099
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001100 res_mdd = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdd");
1101 if (!res_mdd) {
1102 dev_err(&pdev->dev, "missing mdd register addresses\n");
1103 return -EINVAL;
1104 }
1105
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001106 kvreg = devm_kzalloc(&pdev->dev,
1107 sizeof(struct krait_power_vreg), GFP_KERNEL);
1108 if (!kvreg) {
1109 dev_err(&pdev->dev, "kzalloc failed.\n");
1110 return -ENOMEM;
1111 }
1112
1113 kvreg->reg_base = devm_ioremap(&pdev->dev,
1114 res->start, resource_size(res));
1115
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001116 kvreg->mdd_base = devm_ioremap(&pdev->dev,
1117 res_mdd->start, resource_size(res));
1118
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -07001119 kvreg->pvreg = the_gang;
1120 kvreg->name = init_data->constraints.name;
1121 kvreg->desc.name = kvreg->name;
1122 kvreg->desc.ops = &krait_power_ops;
1123 kvreg->desc.type = REGULATOR_VOLTAGE;
1124 kvreg->desc.owner = THIS_MODULE;
Patrick Cain92f4fa12013-04-22 16:23:19 -07001125 kvreg->uV = CORE_VOLTAGE_BOOTUP;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -07001126 kvreg->mode = HS_MODE;
1127 kvreg->desc.ops = &krait_power_ops;
1128 kvreg->headroom_uV = headroom_uV;
1129 kvreg->retention_uV = retention_uV;
1130 kvreg->ldo_default_uV = ldo_default_uV;
1131 kvreg->ldo_threshold_uV = ldo_threshold_uV;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -08001132 kvreg->ldo_delta_uV = ldo_delta_uV;
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -08001133 kvreg->cpu_num = cpu_num;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001134
1135 platform_set_drvdata(pdev, kvreg);
1136
1137 mutex_lock(&the_gang->krait_power_vregs_lock);
Abhijeet Dharmapurikar295c4dc2013-01-08 12:59:01 -08001138 the_gang->pmic_min_uV_for_retention
1139 = min(the_gang->pmic_min_uV_for_retention,
1140 kvreg->retention_uV + kvreg->headroom_uV);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001141 list_add_tail(&kvreg->link, &the_gang->krait_power_vregs);
1142 mutex_unlock(&the_gang->krait_power_vregs_lock);
1143
1144 kvreg->rdev = regulator_register(&kvreg->desc, &pdev->dev, init_data,
1145 kvreg, pdev->dev.of_node);
1146 if (IS_ERR(kvreg->rdev)) {
1147 rc = PTR_ERR(kvreg->rdev);
1148 pr_err("regulator_register failed, rc=%d.\n", rc);
1149 goto out;
1150 }
1151
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -07001152 kvreg_hw_init(kvreg);
Abhijeet Dharmapurikare8f83852013-02-06 18:57:17 -08001153 per_cpu(krait_vregs, cpu_num) = kvreg;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001154 dev_dbg(&pdev->dev, "id=%d, name=%s\n", pdev->id, kvreg->name);
1155
1156 return 0;
1157out:
1158 mutex_lock(&the_gang->krait_power_vregs_lock);
1159 list_del(&kvreg->link);
1160 mutex_unlock(&the_gang->krait_power_vregs_lock);
1161
1162 platform_set_drvdata(pdev, NULL);
1163 return rc;
1164}
1165
1166static int __devexit krait_power_remove(struct platform_device *pdev)
1167{
1168 struct krait_power_vreg *kvreg = platform_get_drvdata(pdev);
1169 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
1170
1171 mutex_lock(&pvreg->krait_power_vregs_lock);
1172 list_del(&kvreg->link);
1173 mutex_unlock(&pvreg->krait_power_vregs_lock);
1174
1175 regulator_unregister(kvreg->rdev);
1176 platform_set_drvdata(pdev, NULL);
1177 return 0;
1178}
1179
1180static struct of_device_id krait_power_match_table[] = {
1181 { .compatible = "qcom,krait-regulator", },
1182 {}
1183};
1184
1185static struct platform_driver krait_power_driver = {
1186 .probe = krait_power_probe,
1187 .remove = __devexit_p(krait_power_remove),
1188 .driver = {
1189 .name = KRAIT_REGULATOR_DRIVER_NAME,
1190 .of_match_table = krait_power_match_table,
1191 .owner = THIS_MODULE,
1192 },
1193};
1194
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001195static struct of_device_id krait_pdn_match_table[] = {
1196 { .compatible = "qcom,krait-pdn", },
1197 {}
1198};
1199
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -07001200static int boot_cpu_mdd_off(void)
1201{
1202 struct krait_power_vreg *kvreg = per_cpu(krait_vregs, 0);
1203
1204 __krait_power_mdd_enable(kvreg, false);
1205 return 0;
1206}
1207
1208static void boot_cpu_mdd_on(void)
1209{
1210 struct krait_power_vreg *kvreg = per_cpu(krait_vregs, 0);
1211
1212 __krait_power_mdd_enable(kvreg, true);
1213}
1214
1215static struct syscore_ops boot_cpu_mdd_ops = {
1216 .suspend = boot_cpu_mdd_off,
1217 .resume = boot_cpu_mdd_on,
1218};
1219
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001220static int __devinit krait_pdn_probe(struct platform_device *pdev)
1221{
1222 int rc;
1223 bool use_phase_switching = false;
Patrick Cain92f4fa12013-04-22 16:23:19 -07001224 int pfm_threshold;
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001225 struct device *dev = &pdev->dev;
1226 struct device_node *node = dev->of_node;
1227 struct pmic_gang_vreg *pvreg;
Stepan Moskovchenko7663b782013-03-08 20:13:06 -08001228 struct resource *res;
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001229
1230 if (!dev->of_node) {
1231 dev_err(dev, "device tree information missing\n");
1232 return -ENODEV;
1233 }
1234
1235 use_phase_switching = of_property_read_bool(node,
1236 "qcom,use-phase-switching");
Patrick Cain92f4fa12013-04-22 16:23:19 -07001237
1238 rc = of_property_read_u32(node, "qcom,pfm-threshold", &pfm_threshold);
1239 if (rc < 0) {
1240 dev_err(dev, "pfm-threshold missing rc=%d, pfm disabled\n", rc);
1241 return -EINVAL;
1242 }
1243
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001244 pvreg = devm_kzalloc(&pdev->dev,
1245 sizeof(struct pmic_gang_vreg), GFP_KERNEL);
1246 if (!pvreg) {
1247 pr_err("kzalloc failed.\n");
1248 return 0;
1249 }
1250
Stepan Moskovchenko7663b782013-03-08 20:13:06 -08001251 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apcs_gcc");
1252 if (!res) {
1253 dev_err(&pdev->dev, "missing apcs gcc base addresses\n");
1254 return -EINVAL;
1255 }
1256
1257 pvreg->apcs_gcc_base = devm_ioremap(&pdev->dev, res->start,
1258 resource_size(res));
1259
1260 if (pvreg->apcs_gcc_base == NULL)
1261 return -ENOMEM;
1262
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001263 pvreg->name = "pmic_gang";
1264 pvreg->pmic_vmax_uV = PMIC_VOLTAGE_MIN;
1265 pvreg->pmic_phase_count = -EINVAL;
1266 pvreg->retention_enabled = true;
1267 pvreg->pmic_min_uV_for_retention = INT_MAX;
1268 pvreg->use_phase_switching = use_phase_switching;
Patrick Cain92f4fa12013-04-22 16:23:19 -07001269 pvreg->pfm_threshold = pfm_threshold;
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001270
1271 mutex_init(&pvreg->krait_power_vregs_lock);
1272 INIT_LIST_HEAD(&pvreg->krait_power_vregs);
1273 the_gang = pvreg;
1274
1275 pr_debug("name=%s inited\n", pvreg->name);
1276
1277 /* global initializtion */
Stepan Moskovchenko7663b782013-03-08 20:13:06 -08001278 glb_init(pvreg->apcs_gcc_base);
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001279
1280 rc = of_platform_populate(node, NULL, NULL, dev);
1281 if (rc) {
1282 dev_err(dev, "failed to add child nodes, rc=%d\n", rc);
1283 return rc;
1284 }
1285
1286 dent = debugfs_create_dir(KRAIT_REGULATOR_DRIVER_NAME, NULL);
1287 debugfs_create_file("retention_uV",
1288 0644, dent, the_gang, &retention_fops);
Abhijeet Dharmapurikarc8605a62013-03-11 21:24:25 -07001289 register_syscore_ops(&boot_cpu_mdd_ops);
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001290 return 0;
1291}
1292
1293static int __devexit krait_pdn_remove(struct platform_device *pdev)
1294{
1295 the_gang = NULL;
1296 debugfs_remove_recursive(dent);
1297 return 0;
1298}
1299
1300static struct platform_driver krait_pdn_driver = {
1301 .probe = krait_pdn_probe,
1302 .remove = __devexit_p(krait_pdn_remove),
1303 .driver = {
1304 .name = KRAIT_PDN_DRIVER_NAME,
1305 .of_match_table = krait_pdn_match_table,
1306 .owner = THIS_MODULE,
1307 },
1308};
1309
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001310int __init krait_power_init(void)
1311{
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001312 int rc = platform_driver_register(&krait_power_driver);
1313 if (rc) {
1314 pr_err("failed to add %s driver rc = %d\n",
1315 KRAIT_REGULATOR_DRIVER_NAME, rc);
1316 return rc;
1317 }
1318 return platform_driver_register(&krait_pdn_driver);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001319}
1320
1321static void __exit krait_power_exit(void)
1322{
1323 platform_driver_unregister(&krait_power_driver);
Abhijeet Dharmapurikar46a7ad32013-02-23 12:50:19 -08001324 platform_driver_unregister(&krait_pdn_driver);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001325}
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001326module_exit(krait_power_exit);
1327
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001328void secondary_cpu_hs_init(void *base_ptr)
1329{
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001330 /* Turn on the BHS, turn off LDO Bypass and power down LDO */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001331 writel_relaxed(
1332 BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
1333 | LDO_PWR_DWN_MASK
1334 | CLK_SRC_DEFAULT << CLK_SRC_SEL_BIT_POS
1335 | BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS
1336 | BHS_EN_MASK,
1337 base_ptr + APC_PWR_GATE_CTL);
1338
1339 /* complete the above write before the delay */
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001340 mb();
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001341
1342 /*
1343 * wait for the bhs to settle
1344 */
1345 udelay(BHS_SETTLING_DELAY_US);
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001346
1347 /* Finally turn on the bypass so that BHS supplies power */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001348 writel_relaxed(
1349 BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
1350 | LDO_PWR_DWN_MASK
1351 | CLK_SRC_DEFAULT << CLK_SRC_SEL_BIT_POS
1352 | LDO_BYP_MASK
1353 | BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS
1354 | BHS_EN_MASK,
1355 base_ptr + APC_PWR_GATE_CTL);
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001356}
1357
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001358MODULE_LICENSE("GPL v2");
1359MODULE_DESCRIPTION("KRAIT POWER regulator driver");
1360MODULE_VERSION("1.0");
1361MODULE_ALIAS("platform:"KRAIT_REGULATOR_DRIVER_NAME);