blob: b6d69650548ac2f63d7d8c8d849b5a013918e142 [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 Dharmapurikar3ff7cba2012-10-10 17:48:29 -070030#include <mach/msm_iomap.h>
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -070031
32#include "spm.h"
33
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070034/*
35 * supply
36 * from
37 * pmic
38 * gang
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -080039 * |
40 * |________________________________
41 * | | |
42 * ___|___ | |
43 * | | | |
44 * | | / /
45 * | LDO | / /LDO BYP [6]
46 * | | / BHS[6] /(bypass is a weak BHS
47 * |_______| | | needs to be on when in
48 * | | | BHS mode)
49 * |________________|_______________|
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070050 * |
51 * ________|________
52 * | |
53 * | KRAIT |
54 * |_________________|
55 */
56
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -070057#define PMIC_VOLTAGE_MIN 350000
58#define PMIC_VOLTAGE_MAX 1355000
59#define LV_RANGE_STEP 5000
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -070060
61#define LOAD_PER_PHASE 3200000
62
Michael Bohan5daee152012-08-14 16:39:35 -070063#define CORE_VOLTAGE_MIN 900000
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -070064
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070065#define KRAIT_LDO_VOLTAGE_MIN 465000
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -070066#define KRAIT_LDO_VOLTAGE_OFFSET 465000
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070067#define KRAIT_LDO_STEP 5000
68
69#define BHS_SETTLING_DELAY_US 1
70#define LDO_SETTLING_DELAY_US 1
71
72#define _KRAIT_MASK(BITS, POS) (((u32)(1 << (BITS)) - 1) << POS)
73#define KRAIT_MASK(LEFT_BIT_POS, RIGHT_BIT_POS) \
74 _KRAIT_MASK(LEFT_BIT_POS - RIGHT_BIT_POS + 1, RIGHT_BIT_POS)
75
76#define APC_SECURE 0x00000000
77#define CPU_PWR_CTL 0x00000004
78#define APC_PWR_STATUS 0x00000008
79#define APC_TEST_BUS_SEL 0x0000000C
80#define CPU_TRGTD_DBG_RST 0x00000010
81#define APC_PWR_GATE_CTL 0x00000014
82#define APC_LDO_VREF_SET 0x00000018
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -070083#define APC_PWR_GATE_MODE 0x0000001C
84#define APC_PWR_GATE_DLY 0x00000020
85
86#define PWR_GATE_CONFIG 0x00000044
87#define VERSION 0x00000FD0
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070088
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -080089/* MDD register group */
90#define MDD_CONFIG_CTL 0x00000000
91#define MDD_MODE 0x00000010
92
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -070093/* bit definitions for APC_PWR_GATE_CTL */
94#define BHS_CNT_BIT_POS 24
95#define BHS_CNT_MASK KRAIT_MASK(31, 24)
96#define BHS_CNT_DEFAULT 64
97
98#define CLK_SRC_SEL_BIT_POS 15
99#define CLK_SRC_SEL_MASK KRAIT_MASK(15, 15)
100#define CLK_SRC_DEFAULT 0
101
102#define LDO_PWR_DWN_BIT_POS 16
103#define LDO_PWR_DWN_MASK KRAIT_MASK(21, 16)
104
105#define LDO_BYP_BIT_POS 8
106#define LDO_BYP_MASK KRAIT_MASK(13, 8)
107
108#define BHS_SEG_EN_BIT_POS 1
109#define BHS_SEG_EN_MASK KRAIT_MASK(6, 1)
110#define BHS_SEG_EN_DEFAULT 0x3F
111
112#define BHS_EN_BIT_POS 0
113#define BHS_EN_MASK KRAIT_MASK(0, 0)
114
115/* bit definitions for APC_LDO_VREF_SET register */
116#define VREF_RET_POS 8
117#define VREF_RET_MASK KRAIT_MASK(14, 8)
118
119#define VREF_LDO_BIT_POS 0
120#define VREF_LDO_MASK KRAIT_MASK(6, 0)
121
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700122/**
123 * struct pmic_gang_vreg -
124 * @name: the string used to represent the gang
125 * @pmic_vmax_uV: the current pmic gang voltage
126 * @pmic_phase_count: the number of phases turned on in the gang
127 * @krait_power_vregs: a list of krait consumers this gang supplies to
128 * @krait_power_vregs_lock: lock to prevent simultaneous access to the list
129 * and its nodes. This needs to be taken by each
130 * regulator's callback functions to prevent
131 * simultaneous updates to the pmic's phase
132 * voltage.
133 */
134struct pmic_gang_vreg {
135 const char *name;
136 int pmic_vmax_uV;
137 int pmic_phase_count;
138 struct list_head krait_power_vregs;
139 struct mutex krait_power_vregs_lock;
Abhijeet Dharmapurikar6a42ef82012-10-18 19:37:36 -0700140 bool pfm_mode;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700141};
142
143static struct pmic_gang_vreg *the_gang;
144
145enum krait_supply_mode {
146 HS_MODE = REGULATOR_MODE_NORMAL,
147 LDO_MODE = REGULATOR_MODE_IDLE,
148};
149
150struct krait_power_vreg {
151 struct list_head link;
152 struct regulator_desc desc;
153 struct regulator_dev *rdev;
154 const char *name;
155 struct pmic_gang_vreg *pvreg;
156 int uV;
157 int load_uA;
158 enum krait_supply_mode mode;
159 void __iomem *reg_base;
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800160 void __iomem *mdd_base;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700161 int ldo_default_uV;
162 int retention_uV;
163 int headroom_uV;
164 int ldo_threshold_uV;
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800165 bool online;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700166};
167
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700168static u32 version;
169
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700170static void krait_masked_write(struct krait_power_vreg *kvreg,
171 int reg, uint32_t mask, uint32_t val)
172{
173 uint32_t reg_val;
174
175 reg_val = readl_relaxed(kvreg->reg_base + reg);
176 reg_val &= ~mask;
177 reg_val |= (val & mask);
178 writel_relaxed(reg_val, kvreg->reg_base + reg);
179
180 /*
181 * Barrier to ensure that the reads and writes from
182 * other regulator regions (they are 1k apart) execute in
183 * order to the above write.
184 */
185 mb();
186}
187
188static int get_krait_ldo_uv(struct krait_power_vreg *kvreg)
189{
190 uint32_t reg_val;
191 int uV;
192
193 reg_val = readl_relaxed(kvreg->reg_base + APC_LDO_VREF_SET);
194 reg_val &= VREF_LDO_MASK;
195 reg_val >>= VREF_LDO_BIT_POS;
196
197 if (reg_val == 0)
198 uV = 0;
199 else
200 uV = KRAIT_LDO_VOLTAGE_OFFSET + reg_val * KRAIT_LDO_STEP;
201
202 return uV;
203}
204
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700205static int set_krait_retention_uv(struct krait_power_vreg *kvreg, int uV)
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700206{
207 uint32_t reg_val;
208
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700209 reg_val = DIV_ROUND_UP(uV - KRAIT_LDO_VOLTAGE_OFFSET, KRAIT_LDO_STEP);
210 krait_masked_write(kvreg, APC_LDO_VREF_SET, VREF_RET_MASK,
211 reg_val << VREF_RET_POS);
212
213 return 0;
214}
215
216static int set_krait_ldo_uv(struct krait_power_vreg *kvreg, int uV)
217{
218 uint32_t reg_val;
219
220 reg_val = DIV_ROUND_UP(uV - KRAIT_LDO_VOLTAGE_OFFSET, KRAIT_LDO_STEP);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700221 krait_masked_write(kvreg, APC_LDO_VREF_SET, VREF_LDO_MASK,
222 reg_val << VREF_LDO_BIT_POS);
223
224 return 0;
225}
226
227static int switch_to_using_hs(struct krait_power_vreg *kvreg)
228{
229 if (kvreg->mode == HS_MODE)
230 return 0;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700231 /* enable bhs */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800232 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
233 BHS_SEG_EN_MASK | BHS_EN_MASK,
234 BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS | BHS_EN_MASK);
235
236 /* complete the above write before the delay */
237 mb();
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700238
239 /*
240 * wait for the bhs to settle - note that
241 * after the voltage has settled both BHS and LDO are supplying power
242 * to the krait. This avoids glitches during switching
243 */
244 udelay(BHS_SETTLING_DELAY_US);
245
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800246 /*
247 * enable ldo bypass - the krait is powered still by LDO since
248 * LDO is enabled
249 */
250 krait_masked_write(kvreg, APC_PWR_GATE_CTL, LDO_BYP_MASK, LDO_BYP_MASK);
251
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700252 /* disable ldo - only the BHS provides voltage to the cpu after this */
253 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
254 LDO_PWR_DWN_MASK, LDO_PWR_DWN_MASK);
255
256 kvreg->mode = HS_MODE;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800257 pr_debug("%s using BHS\n", kvreg->name);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700258 return 0;
259}
260
261static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
262{
263 if (kvreg->mode == LDO_MODE && get_krait_ldo_uv(kvreg) == kvreg->uV)
264 return 0;
265
266 /*
267 * if the krait is in ldo mode and a voltage change is requested on the
268 * ldo switch to using hs before changing ldo voltage
269 */
270 if (kvreg->mode == LDO_MODE)
271 switch_to_using_hs(kvreg);
272
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700273 set_krait_ldo_uv(kvreg, kvreg->uV);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700274
275 /*
276 * enable ldo - note that both LDO and BHS are are supplying voltage to
277 * the cpu after this. This avoids glitches during switching from BHS
278 * to LDO.
279 */
280 krait_masked_write(kvreg, APC_PWR_GATE_CTL, LDO_PWR_DWN_MASK, 0);
281
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800282 /* complete the writes before the delay */
283 mb();
284
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700285 /* wait for the ldo to settle */
286 udelay(LDO_SETTLING_DELAY_US);
287
288 /*
289 * disable BHS and disable LDO bypass seperate from enabling
290 * the LDO above.
291 */
292 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
293 BHS_EN_MASK | LDO_BYP_MASK, 0);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800294 krait_masked_write(kvreg, APC_PWR_GATE_CTL, BHS_SEG_EN_MASK, 0);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700295
296 kvreg->mode = LDO_MODE;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800297 pr_debug("%s using LDO\n", kvreg->name);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700298 return 0;
299}
300
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700301static int set_pmic_gang_phases(int phase_count)
302{
Abhijeet Dharmapurikare4b89ee2012-08-07 18:53:53 -0700303 /*
304 * TODO : spm writes for phase control,
305 * pmic phase control is not working yet
306 */
307 return 0;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700308}
309
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800310static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700311{
312 int setpoint;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800313 int rc;
314
315 if (pvreg->pmic_vmax_uV == uV)
316 return 0;
317
318 pr_debug("%d\n", uV);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700319
320 if (uV < PMIC_VOLTAGE_MIN) {
321 pr_err("requested %d < %d, restricting it to %d\n",
322 uV, PMIC_VOLTAGE_MIN, PMIC_VOLTAGE_MIN);
323 uV = PMIC_VOLTAGE_MIN;
324 }
325 if (uV > PMIC_VOLTAGE_MAX) {
326 pr_err("requested %d > %d, restricting it to %d\n",
327 uV, PMIC_VOLTAGE_MAX, PMIC_VOLTAGE_MAX);
328 uV = PMIC_VOLTAGE_MAX;
329 }
330
Abhijeet Dharmapurikard4f38da2012-08-08 21:42:06 -0700331 setpoint = DIV_ROUND_UP(uV, LV_RANGE_STEP);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800332
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800333 rc = msm_spm_apcs_set_vdd(setpoint);
334 if (rc < 0)
335 pr_err("could not set %duV setpt = 0x%x rc = %d\n",
336 uV, setpoint, rc);
337 else
338 pvreg->pmic_vmax_uV = uV;
339
340 return rc;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700341}
342
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800343static int configure_ldo_or_hs_all(struct krait_power_vreg *from, int vmax)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700344{
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700345 struct pmic_gang_vreg *pvreg = from->pvreg;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700346 struct krait_power_vreg *kvreg;
347 int rc = 0;
348
349 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800350 if (!kvreg->online)
351 continue;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700352 if (kvreg->uV > kvreg->ldo_threshold_uV
353 || kvreg->uV > vmax - kvreg->headroom_uV) {
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700354 rc = switch_to_using_hs(kvreg);
355 if (rc < 0) {
356 pr_err("could not switch %s to hs rc = %d\n",
357 kvreg->name, rc);
358 return rc;
359 }
360 } else {
361 rc = switch_to_using_ldo(kvreg);
362 if (rc < 0) {
363 pr_err("could not switch %s to ldo rc = %d\n",
364 kvreg->name, rc);
365 return rc;
366 }
367 }
368 }
369
370 return rc;
371}
372
373#define SLEW_RATE 2994
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800374static int krait_voltage_increase(struct krait_power_vreg *from,
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700375 int vmax)
376{
377 struct pmic_gang_vreg *pvreg = from->pvreg;
378 int rc = 0;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700379 int settling_us;
380
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700381 /*
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800382 * since krait voltage is increasing set the gang voltage
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700383 * prior to changing ldo/hs states of the requesting krait
384 */
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800385 rc = set_pmic_gang_voltage(pvreg, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700386 if (rc < 0) {
387 dev_err(&from->rdev->dev, "%s failed set voltage %d rc = %d\n",
388 pvreg->name, vmax, rc);
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800389 return rc;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700390 }
391
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800392
393 /* complete the above writes before the delay */
394 mb();
395
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700396 /* delay until the voltage is settled when it is raised */
397 settling_us = DIV_ROUND_UP(vmax - pvreg->pmic_vmax_uV, SLEW_RATE);
398 udelay(settling_us);
399
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800400 rc = configure_ldo_or_hs_all(from, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700401 if (rc < 0) {
402 dev_err(&from->rdev->dev, "%s failed ldo/hs conf %d rc = %d\n",
403 pvreg->name, vmax, rc);
404 }
405
406 return rc;
407}
408
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800409static int krait_voltage_decrease(struct krait_power_vreg *from,
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700410 int vmax)
411{
412 struct pmic_gang_vreg *pvreg = from->pvreg;
413 int rc = 0;
414
415 /*
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800416 * since krait voltage is decreasing ldos might get out of their
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700417 * operating range. Hence configure such kraits to be in hs mode prior
418 * to setting the pmic gang voltage
419 */
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800420 rc = configure_ldo_or_hs_all(from, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700421 if (rc < 0) {
422 dev_err(&from->rdev->dev, "%s failed ldo/hs conf %d rc = %d\n",
423 pvreg->name, vmax, rc);
424 return rc;
425 }
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700426
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800427 rc = set_pmic_gang_voltage(pvreg, vmax);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700428 if (rc < 0) {
429 dev_err(&from->rdev->dev, "%s failed set voltage %d rc = %d\n",
430 pvreg->name, vmax, rc);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700431 }
432
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700433 return rc;
434}
435
436#define PHASE_SETTLING_TIME_US 10
437static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
438 int load_uA)
439{
440 struct pmic_gang_vreg *pvreg = from->pvreg;
441 int phase_count = DIV_ROUND_UP(load_uA, LOAD_PER_PHASE) - 1;
442 int rc = 0;
443
444 if (phase_count < 0)
445 phase_count = 0;
446
447 if (phase_count != pvreg->pmic_phase_count) {
448 rc = set_pmic_gang_phases(phase_count);
449 if (rc < 0) {
450 dev_err(&from->rdev->dev,
451 "%s failed set phase %d rc = %d\n",
452 pvreg->name, phase_count, rc);
453 return rc;
454 }
455
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800456 /* complete the writes before the delay */
457 mb();
458
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700459 /*
460 * delay until the phases are settled when
461 * the count is raised
462 */
463 if (phase_count > pvreg->pmic_phase_count)
464 udelay(PHASE_SETTLING_TIME_US);
465
466 pvreg->pmic_phase_count = phase_count;
467 }
468 return rc;
469}
470
Matt Wagantall98bfbe92012-11-12 18:39:47 -0800471static int __devinit pvreg_init(struct platform_device *pdev)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700472{
473 struct pmic_gang_vreg *pvreg;
474
475 pvreg = devm_kzalloc(&pdev->dev,
476 sizeof(struct pmic_gang_vreg), GFP_KERNEL);
477 if (!pvreg) {
478 pr_err("kzalloc failed.\n");
479 return -ENOMEM;
480 }
481
482 pvreg->name = "pmic_gang";
483 pvreg->pmic_vmax_uV = PMIC_VOLTAGE_MIN;
484 pvreg->pmic_phase_count = 1;
485
486 mutex_init(&pvreg->krait_power_vregs_lock);
487 INIT_LIST_HEAD(&pvreg->krait_power_vregs);
488 the_gang = pvreg;
489
490 pr_debug("name=%s inited\n", pvreg->name);
491
492 return 0;
493}
494
495static int krait_power_get_voltage(struct regulator_dev *rdev)
496{
497 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
498
499 return kvreg->uV;
500}
501
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800502static int get_vmax(struct pmic_gang_vreg *pvreg)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700503{
504 int vmax = 0;
505 int v;
506 struct krait_power_vreg *kvreg;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700507
508 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800509 if (!kvreg->online)
510 continue;
511
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700512 v = kvreg->uV;
513
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700514 if (vmax < v)
515 vmax = v;
516 }
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800517
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700518 return vmax;
519}
520
521static int get_total_load(struct krait_power_vreg *from)
522{
523 int load_total = 0;
524 struct krait_power_vreg *kvreg;
525 struct pmic_gang_vreg *pvreg = from->pvreg;
526
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800527 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
528 if (!kvreg->online)
529 continue;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700530 load_total += kvreg->load_uA;
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800531 }
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700532
533 return load_total;
534}
535
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700536#define ROUND_UP_VOLTAGE(v, res) (DIV_ROUND_UP(v, res) * res)
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800537static int _set_voltage(struct regulator_dev *rdev,
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800538 int orig_krait_uV, int requested_uV)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700539{
540 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
541 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
542 int rc;
543 int vmax;
544
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800545 pr_debug("%s: %d to %d\n", kvreg->name, orig_krait_uV, requested_uV);
546 /*
547 * Assign the voltage before updating the gang voltage as we iterate
548 * over all the core voltages and choose HS or LDO for each of them
549 */
550 kvreg->uV = requested_uV;
551
552 vmax = get_vmax(pvreg);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800553
554 /* round up the pmic voltage as per its resolution */
555 vmax = ROUND_UP_VOLTAGE(vmax, LV_RANGE_STEP);
556
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800557 if (requested_uV > orig_krait_uV)
558 rc = krait_voltage_increase(kvreg, vmax);
559 else
560 rc = krait_voltage_decrease(kvreg, vmax);
561
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800562 if (rc < 0) {
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800563 dev_err(&rdev->dev, "%s failed to set %duV from %duV rc = %d\n",
564 kvreg->name, requested_uV, orig_krait_uV, rc);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800565 }
566
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800567 return rc;
568}
569
570static int krait_power_set_voltage(struct regulator_dev *rdev,
571 int min_uV, int max_uV, unsigned *selector)
572{
573 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
574 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
575 int rc;
576
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700577 /*
578 * if the voltage requested is below LDO_THRESHOLD this cpu could
579 * switch to LDO mode. Hence round the voltage as per the LDO
580 * resolution
581 */
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700582 if (min_uV < kvreg->ldo_threshold_uV) {
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700583 if (min_uV < KRAIT_LDO_VOLTAGE_MIN)
584 min_uV = KRAIT_LDO_VOLTAGE_MIN;
585 min_uV = ROUND_UP_VOLTAGE(min_uV, KRAIT_LDO_STEP);
586 }
587
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700588 mutex_lock(&pvreg->krait_power_vregs_lock);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800589 if (!kvreg->online) {
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800590 kvreg->uV = min_uV;
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800591 mutex_unlock(&pvreg->krait_power_vregs_lock);
592 return 0;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700593 }
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700594
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800595 rc = _set_voltage(rdev, kvreg->uV, min_uV);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700596 mutex_unlock(&pvreg->krait_power_vregs_lock);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800597
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700598 return rc;
599}
600
Abhijeet Dharmapurikar6a42ef82012-10-18 19:37:36 -0700601#define PMIC_FTS_MODE_PFM 0x00
602#define PMIC_FTS_MODE_PWM 0x80
603#define PFM_LOAD_UA 500000
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800604static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700605 int input_uV, int output_uV, int load_uA)
606{
607 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
608 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
609 int rc;
610 int load_total_uA;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700611
612 load_total_uA = get_total_load(kvreg);
613
Abhijeet Dharmapurikar6a42ef82012-10-18 19:37:36 -0700614 if (load_total_uA < PFM_LOAD_UA) {
615 if (!pvreg->pfm_mode) {
616 rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
617 if (rc) {
618 dev_err(&rdev->dev,
619 "%s enter PFM failed load %d rc = %d\n",
620 kvreg->name, load_total_uA, rc);
621 goto out;
622 } else {
623 pvreg->pfm_mode = true;
624 }
625 }
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800626 return kvreg->mode;
Abhijeet Dharmapurikar6a42ef82012-10-18 19:37:36 -0700627 }
628
629 if (pvreg->pfm_mode) {
630 rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
631 if (rc) {
632 dev_err(&rdev->dev,
633 "%s exit PFM failed load %d rc = %d\n",
634 kvreg->name, load_total_uA, rc);
635 goto out;
636 } else {
637 pvreg->pfm_mode = false;
638 }
639 }
640
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700641 rc = pmic_gang_set_phases(kvreg, load_total_uA);
642 if (rc < 0) {
643 dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
644 kvreg->name, load_total_uA, rc);
645 goto out;
646 }
647
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700648out:
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800649 return kvreg->mode;
650}
651
652static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
653 int input_uV, int output_uV, int load_uA)
654{
655 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
656 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
657 int rc;
658
659 mutex_lock(&pvreg->krait_power_vregs_lock);
660 kvreg->load_uA = load_uA;
661 if (!kvreg->online) {
662 mutex_unlock(&pvreg->krait_power_vregs_lock);
663 return kvreg->mode;
664 }
665
666 rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700667 mutex_unlock(&pvreg->krait_power_vregs_lock);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800668
669 return rc;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700670}
671
672static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
673{
674 return 0;
675}
676
677static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
678{
679 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
680
681 return kvreg->mode;
682}
683
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800684static int krait_power_is_enabled(struct regulator_dev *rdev)
685{
686 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
687
688 return kvreg->online;
689}
690
691static int krait_power_enable(struct regulator_dev *rdev)
692{
693 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
694 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
695 int rc;
696
697 mutex_lock(&pvreg->krait_power_vregs_lock);
698 kvreg->online = true;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800699 rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800700 if (rc < 0)
701 goto en_err;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800702 /*
703 * since the core is being enabled, behave as if it is increasing
704 * the core voltage
705 */
706 rc = _set_voltage(rdev, 0, kvreg->uV);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800707en_err:
708 mutex_unlock(&pvreg->krait_power_vregs_lock);
709 return rc;
710}
711
712static int krait_power_disable(struct regulator_dev *rdev)
713{
714 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
715 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
716 int rc;
717
718 mutex_lock(&pvreg->krait_power_vregs_lock);
719 kvreg->online = false;
720
721 rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV,
722 kvreg->load_uA);
723 if (rc < 0)
724 goto dis_err;
725
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800726 rc = _set_voltage(rdev, kvreg->uV, kvreg->uV);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800727dis_err:
728 mutex_unlock(&pvreg->krait_power_vregs_lock);
729 return rc;
730}
731
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700732static struct regulator_ops krait_power_ops = {
733 .get_voltage = krait_power_get_voltage,
734 .set_voltage = krait_power_set_voltage,
735 .get_optimum_mode = krait_power_get_optimum_mode,
736 .set_mode = krait_power_set_mode,
737 .get_mode = krait_power_get_mode,
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800738 .enable = krait_power_enable,
739 .disable = krait_power_disable,
740 .is_enabled = krait_power_is_enabled,
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700741};
742
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700743static void kvreg_hw_init(struct krait_power_vreg *kvreg)
744{
745 /*
746 * bhs_cnt value sets the ramp-up time from power collapse,
747 * initialize the ramp up time
748 */
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700749 set_krait_retention_uv(kvreg, kvreg->retention_uV);
750 set_krait_ldo_uv(kvreg, kvreg->ldo_default_uV);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800751
752 /* setup the bandgap that configures the reference to the LDO */
753 writel_relaxed(0x00000190, kvreg->mdd_base + MDD_CONFIG_CTL);
754 /* Enable MDD */
755 writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
756 mb();
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700757}
758
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700759static void glb_init(struct platform_device *pdev)
760{
761 /* configure bi-modal switch */
762 writel_relaxed(0x0008736E, MSM_APCS_GCC_BASE + PWR_GATE_CONFIG);
763 /* read kpss version */
764 version = readl_relaxed(MSM_APCS_GCC_BASE + VERSION);
765 pr_debug("version= 0x%x\n", version);
766}
767
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700768static int is_between(int left, int right, int value)
769{
770 if (left >= right && left >= value && value >= right)
771 return 1;
772 if (left <= right && left <= value && value <= right)
773 return 1;
774 return 0;
775}
776
777#define LDO_HDROOM_MIN 50000
778#define LDO_HDROOM_MAX 250000
779
780#define LDO_UV_MIN 465000
781#define LDO_UV_MAX 750000
782
783#define LDO_TH_MIN 600000
784#define LDO_TH_MAX 800000
785
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700786static int __devinit krait_power_probe(struct platform_device *pdev)
787{
788 struct krait_power_vreg *kvreg;
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800789 struct resource *res, *res_mdd;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700790 struct regulator_init_data *init_data = pdev->dev.platform_data;
791 int rc = 0;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700792 int headroom_uV, retention_uV, ldo_default_uV, ldo_threshold_uV;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700793
794 /* Initialize the pmic gang if it hasn't been initialized already */
795 if (the_gang == NULL) {
796 rc = pvreg_init(pdev);
797 if (rc < 0) {
798 dev_err(&pdev->dev,
799 "failed to init pmic gang rc = %d\n", rc);
800 return rc;
801 }
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700802 /* global initializtion */
803 glb_init(pdev);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700804 }
805
806 if (pdev->dev.of_node) {
807 /* Get init_data from device tree. */
808 init_data = of_get_regulator_init_data(&pdev->dev,
809 pdev->dev.of_node);
810 init_data->constraints.valid_ops_mask
811 |= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_DRMS
812 | REGULATOR_CHANGE_MODE;
813 init_data->constraints.valid_modes_mask
814 |= REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE
815 | REGULATOR_MODE_FAST;
816 init_data->constraints.input_uV = init_data->constraints.max_uV;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700817 rc = of_property_read_u32(pdev->dev.of_node,
818 "qcom,headroom-voltage",
819 &headroom_uV);
820 if (rc < 0) {
821 pr_err("headroom-voltage missing rc=%d\n", rc);
822 return rc;
823 }
824 if (!is_between(LDO_HDROOM_MIN, LDO_HDROOM_MAX, headroom_uV)) {
825 pr_err("bad headroom-voltage = %d specified\n",
826 headroom_uV);
827 return -EINVAL;
828 }
829
830 rc = of_property_read_u32(pdev->dev.of_node,
831 "qcom,retention-voltage",
832 &retention_uV);
833 if (rc < 0) {
834 pr_err("retention-voltage missing rc=%d\n", rc);
835 return rc;
836 }
837 if (!is_between(LDO_UV_MIN, LDO_UV_MAX, retention_uV)) {
838 pr_err("bad retention-voltage = %d specified\n",
839 retention_uV);
840 return -EINVAL;
841 }
842
843 rc = of_property_read_u32(pdev->dev.of_node,
844 "qcom,ldo-default-voltage",
845 &ldo_default_uV);
846 if (rc < 0) {
847 pr_err("ldo-default-voltage missing rc=%d\n", rc);
848 return rc;
849 }
850 if (!is_between(LDO_UV_MIN, LDO_UV_MAX, ldo_default_uV)) {
851 pr_err("bad ldo-default-voltage = %d specified\n",
852 ldo_default_uV);
853 return -EINVAL;
854 }
855
856 rc = of_property_read_u32(pdev->dev.of_node,
857 "qcom,ldo-threshold-voltage",
858 &ldo_threshold_uV);
859 if (rc < 0) {
860 pr_err("ldo-threshold-voltage missing rc=%d\n", rc);
861 return rc;
862 }
863 if (!is_between(LDO_TH_MIN, LDO_TH_MAX, ldo_threshold_uV)) {
864 pr_err("bad ldo-threshold-voltage = %d specified\n",
865 ldo_threshold_uV);
866 return -EINVAL;
867 }
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700868 }
869
870 if (!init_data) {
871 dev_err(&pdev->dev, "init data required.\n");
872 return -EINVAL;
873 }
874
875 if (!init_data->constraints.name) {
876 dev_err(&pdev->dev,
877 "regulator name must be specified in constraints.\n");
878 return -EINVAL;
879 }
880
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800881 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acs");
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700882 if (!res) {
883 dev_err(&pdev->dev, "missing physical register addresses\n");
884 return -EINVAL;
885 }
886
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800887 res_mdd = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdd");
888 if (!res_mdd) {
889 dev_err(&pdev->dev, "missing mdd register addresses\n");
890 return -EINVAL;
891 }
892
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700893 kvreg = devm_kzalloc(&pdev->dev,
894 sizeof(struct krait_power_vreg), GFP_KERNEL);
895 if (!kvreg) {
896 dev_err(&pdev->dev, "kzalloc failed.\n");
897 return -ENOMEM;
898 }
899
900 kvreg->reg_base = devm_ioremap(&pdev->dev,
901 res->start, resource_size(res));
902
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800903 kvreg->mdd_base = devm_ioremap(&pdev->dev,
904 res_mdd->start, resource_size(res));
905
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700906 kvreg->pvreg = the_gang;
907 kvreg->name = init_data->constraints.name;
908 kvreg->desc.name = kvreg->name;
909 kvreg->desc.ops = &krait_power_ops;
910 kvreg->desc.type = REGULATOR_VOLTAGE;
911 kvreg->desc.owner = THIS_MODULE;
912 kvreg->uV = CORE_VOLTAGE_MIN;
913 kvreg->mode = HS_MODE;
914 kvreg->desc.ops = &krait_power_ops;
915 kvreg->headroom_uV = headroom_uV;
916 kvreg->retention_uV = retention_uV;
917 kvreg->ldo_default_uV = ldo_default_uV;
918 kvreg->ldo_threshold_uV = ldo_threshold_uV;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700919
920 platform_set_drvdata(pdev, kvreg);
921
922 mutex_lock(&the_gang->krait_power_vregs_lock);
923 list_add_tail(&kvreg->link, &the_gang->krait_power_vregs);
924 mutex_unlock(&the_gang->krait_power_vregs_lock);
925
926 kvreg->rdev = regulator_register(&kvreg->desc, &pdev->dev, init_data,
927 kvreg, pdev->dev.of_node);
928 if (IS_ERR(kvreg->rdev)) {
929 rc = PTR_ERR(kvreg->rdev);
930 pr_err("regulator_register failed, rc=%d.\n", rc);
931 goto out;
932 }
933
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700934 kvreg_hw_init(kvreg);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700935 dev_dbg(&pdev->dev, "id=%d, name=%s\n", pdev->id, kvreg->name);
936
937 return 0;
938out:
939 mutex_lock(&the_gang->krait_power_vregs_lock);
940 list_del(&kvreg->link);
941 mutex_unlock(&the_gang->krait_power_vregs_lock);
942
943 platform_set_drvdata(pdev, NULL);
944 return rc;
945}
946
947static int __devexit krait_power_remove(struct platform_device *pdev)
948{
949 struct krait_power_vreg *kvreg = platform_get_drvdata(pdev);
950 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
951
952 mutex_lock(&pvreg->krait_power_vregs_lock);
953 list_del(&kvreg->link);
954 mutex_unlock(&pvreg->krait_power_vregs_lock);
955
956 regulator_unregister(kvreg->rdev);
957 platform_set_drvdata(pdev, NULL);
958 return 0;
959}
960
961static struct of_device_id krait_power_match_table[] = {
962 { .compatible = "qcom,krait-regulator", },
963 {}
964};
965
966static struct platform_driver krait_power_driver = {
967 .probe = krait_power_probe,
968 .remove = __devexit_p(krait_power_remove),
969 .driver = {
970 .name = KRAIT_REGULATOR_DRIVER_NAME,
971 .of_match_table = krait_power_match_table,
972 .owner = THIS_MODULE,
973 },
974};
975
976int __init krait_power_init(void)
977{
978 return platform_driver_register(&krait_power_driver);
979}
980
981static void __exit krait_power_exit(void)
982{
983 platform_driver_unregister(&krait_power_driver);
984}
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700985module_exit(krait_power_exit);
986
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -0700987void secondary_cpu_hs_init(void *base_ptr)
988{
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -0700989 /* Turn on the BHS, turn off LDO Bypass and power down LDO */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800990 writel_relaxed(
991 BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
992 | LDO_PWR_DWN_MASK
993 | CLK_SRC_DEFAULT << CLK_SRC_SEL_BIT_POS
994 | BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS
995 | BHS_EN_MASK,
996 base_ptr + APC_PWR_GATE_CTL);
997
998 /* complete the above write before the delay */
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -0700999 mb();
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001000
1001 /*
1002 * wait for the bhs to settle
1003 */
1004 udelay(BHS_SETTLING_DELAY_US);
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001005
1006 /* Finally turn on the bypass so that BHS supplies power */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001007 writel_relaxed(
1008 BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
1009 | LDO_PWR_DWN_MASK
1010 | CLK_SRC_DEFAULT << CLK_SRC_SEL_BIT_POS
1011 | LDO_BYP_MASK
1012 | BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS
1013 | BHS_EN_MASK,
1014 base_ptr + APC_PWR_GATE_CTL);
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001015}
1016
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001017MODULE_LICENSE("GPL v2");
1018MODULE_DESCRIPTION("KRAIT POWER regulator driver");
1019MODULE_VERSION("1.0");
1020MODULE_ALIAS("platform:"KRAIT_REGULATOR_DRIVER_NAME);