blob: a54fddf95220a8ab15ce5a4f103b3563a511c986 [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;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800165 int ldo_delta_uV;
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800166 bool online;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700167};
168
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700169static u32 version;
170
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700171static void krait_masked_write(struct krait_power_vreg *kvreg,
172 int reg, uint32_t mask, uint32_t val)
173{
174 uint32_t reg_val;
175
176 reg_val = readl_relaxed(kvreg->reg_base + reg);
177 reg_val &= ~mask;
178 reg_val |= (val & mask);
179 writel_relaxed(reg_val, kvreg->reg_base + reg);
180
181 /*
182 * Barrier to ensure that the reads and writes from
183 * other regulator regions (they are 1k apart) execute in
184 * order to the above write.
185 */
186 mb();
187}
188
189static int get_krait_ldo_uv(struct krait_power_vreg *kvreg)
190{
191 uint32_t reg_val;
192 int uV;
193
194 reg_val = readl_relaxed(kvreg->reg_base + APC_LDO_VREF_SET);
195 reg_val &= VREF_LDO_MASK;
196 reg_val >>= VREF_LDO_BIT_POS;
197
198 if (reg_val == 0)
199 uV = 0;
200 else
201 uV = KRAIT_LDO_VOLTAGE_OFFSET + reg_val * KRAIT_LDO_STEP;
202
203 return uV;
204}
205
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700206static int set_krait_retention_uv(struct krait_power_vreg *kvreg, int uV)
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700207{
208 uint32_t reg_val;
209
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700210 reg_val = DIV_ROUND_UP(uV - KRAIT_LDO_VOLTAGE_OFFSET, KRAIT_LDO_STEP);
211 krait_masked_write(kvreg, APC_LDO_VREF_SET, VREF_RET_MASK,
212 reg_val << VREF_RET_POS);
213
214 return 0;
215}
216
217static int set_krait_ldo_uv(struct krait_power_vreg *kvreg, int uV)
218{
219 uint32_t reg_val;
220
221 reg_val = DIV_ROUND_UP(uV - KRAIT_LDO_VOLTAGE_OFFSET, KRAIT_LDO_STEP);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700222 krait_masked_write(kvreg, APC_LDO_VREF_SET, VREF_LDO_MASK,
223 reg_val << VREF_LDO_BIT_POS);
224
225 return 0;
226}
227
228static int switch_to_using_hs(struct krait_power_vreg *kvreg)
229{
230 if (kvreg->mode == HS_MODE)
231 return 0;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700232 /* enable bhs */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800233 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
234 BHS_SEG_EN_MASK | BHS_EN_MASK,
235 BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS | BHS_EN_MASK);
236
237 /* complete the above write before the delay */
238 mb();
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700239
240 /*
241 * wait for the bhs to settle - note that
242 * after the voltage has settled both BHS and LDO are supplying power
243 * to the krait. This avoids glitches during switching
244 */
245 udelay(BHS_SETTLING_DELAY_US);
246
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800247 /*
248 * enable ldo bypass - the krait is powered still by LDO since
249 * LDO is enabled
250 */
251 krait_masked_write(kvreg, APC_PWR_GATE_CTL, LDO_BYP_MASK, LDO_BYP_MASK);
252
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700253 /* disable ldo - only the BHS provides voltage to the cpu after this */
254 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
255 LDO_PWR_DWN_MASK, LDO_PWR_DWN_MASK);
256
257 kvreg->mode = HS_MODE;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800258 pr_debug("%s using BHS\n", kvreg->name);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700259 return 0;
260}
261
262static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
263{
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800264 if (kvreg->mode == LDO_MODE
265 && get_krait_ldo_uv(kvreg) == kvreg->uV - kvreg->ldo_delta_uV)
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700266 return 0;
267
268 /*
269 * if the krait is in ldo mode and a voltage change is requested on the
270 * ldo switch to using hs before changing ldo voltage
271 */
272 if (kvreg->mode == LDO_MODE)
273 switch_to_using_hs(kvreg);
274
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800275 set_krait_ldo_uv(kvreg, kvreg->uV - kvreg->ldo_delta_uV);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700276
277 /*
278 * enable ldo - note that both LDO and BHS are are supplying voltage to
279 * the cpu after this. This avoids glitches during switching from BHS
280 * to LDO.
281 */
282 krait_masked_write(kvreg, APC_PWR_GATE_CTL, LDO_PWR_DWN_MASK, 0);
283
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800284 /* complete the writes before the delay */
285 mb();
286
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700287 /* wait for the ldo to settle */
288 udelay(LDO_SETTLING_DELAY_US);
289
290 /*
291 * disable BHS and disable LDO bypass seperate from enabling
292 * the LDO above.
293 */
294 krait_masked_write(kvreg, APC_PWR_GATE_CTL,
295 BHS_EN_MASK | LDO_BYP_MASK, 0);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800296 krait_masked_write(kvreg, APC_PWR_GATE_CTL, BHS_SEG_EN_MASK, 0);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700297
298 kvreg->mode = LDO_MODE;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800299 pr_debug("%s using LDO\n", kvreg->name);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700300 return 0;
301}
302
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700303static int set_pmic_gang_phases(int phase_count)
304{
Abhijeet Dharmapurikare4b89ee2012-08-07 18:53:53 -0700305 /*
306 * TODO : spm writes for phase control,
307 * pmic phase control is not working yet
308 */
309 return 0;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700310}
311
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800312static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700313{
314 int setpoint;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800315 int rc;
316
317 if (pvreg->pmic_vmax_uV == uV)
318 return 0;
319
320 pr_debug("%d\n", uV);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700321
322 if (uV < PMIC_VOLTAGE_MIN) {
323 pr_err("requested %d < %d, restricting it to %d\n",
324 uV, PMIC_VOLTAGE_MIN, PMIC_VOLTAGE_MIN);
325 uV = PMIC_VOLTAGE_MIN;
326 }
327 if (uV > PMIC_VOLTAGE_MAX) {
328 pr_err("requested %d > %d, restricting it to %d\n",
329 uV, PMIC_VOLTAGE_MAX, PMIC_VOLTAGE_MAX);
330 uV = PMIC_VOLTAGE_MAX;
331 }
332
Abhijeet Dharmapurikard4f38da2012-08-08 21:42:06 -0700333 setpoint = DIV_ROUND_UP(uV, LV_RANGE_STEP);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800334
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800335 rc = msm_spm_apcs_set_vdd(setpoint);
336 if (rc < 0)
337 pr_err("could not set %duV setpt = 0x%x rc = %d\n",
338 uV, setpoint, rc);
339 else
340 pvreg->pmic_vmax_uV = uV;
341
342 return rc;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700343}
344
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800345static int configure_ldo_or_hs_all(struct krait_power_vreg *from, int vmax)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700346{
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700347 struct pmic_gang_vreg *pvreg = from->pvreg;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700348 struct krait_power_vreg *kvreg;
349 int rc = 0;
350
351 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800352 if (!kvreg->online)
353 continue;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800354 if (kvreg->uV <= kvreg->ldo_threshold_uV
355 && kvreg->uV - kvreg->ldo_delta_uV + kvreg->headroom_uV
356 <= vmax) {
357 rc = switch_to_using_ldo(kvreg);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700358 if (rc < 0) {
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800359 pr_err("could not switch %s to ldo rc = %d\n",
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700360 kvreg->name, rc);
361 return rc;
362 }
363 } else {
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800364 rc = switch_to_using_hs(kvreg);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700365 if (rc < 0) {
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800366 pr_err("could not switch %s to hs rc = %d\n",
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700367 kvreg->name, rc);
368 return rc;
369 }
370 }
371 }
372
373 return rc;
374}
375
376#define SLEW_RATE 2994
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800377static int krait_voltage_increase(struct krait_power_vreg *from,
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700378 int vmax)
379{
380 struct pmic_gang_vreg *pvreg = from->pvreg;
381 int rc = 0;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700382 int settling_us;
383
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700384 /*
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800385 * since krait voltage is increasing set the gang voltage
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700386 * prior to changing ldo/hs states of the requesting krait
387 */
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800388 rc = set_pmic_gang_voltage(pvreg, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700389 if (rc < 0) {
390 dev_err(&from->rdev->dev, "%s failed set voltage %d rc = %d\n",
391 pvreg->name, vmax, rc);
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800392 return rc;
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700393 }
394
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800395
396 /* complete the above writes before the delay */
397 mb();
398
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700399 /* delay until the voltage is settled when it is raised */
400 settling_us = DIV_ROUND_UP(vmax - pvreg->pmic_vmax_uV, SLEW_RATE);
401 udelay(settling_us);
402
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800403 rc = configure_ldo_or_hs_all(from, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700404 if (rc < 0) {
405 dev_err(&from->rdev->dev, "%s failed ldo/hs conf %d rc = %d\n",
406 pvreg->name, vmax, rc);
407 }
408
409 return rc;
410}
411
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800412static int krait_voltage_decrease(struct krait_power_vreg *from,
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700413 int vmax)
414{
415 struct pmic_gang_vreg *pvreg = from->pvreg;
416 int rc = 0;
417
418 /*
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800419 * since krait voltage is decreasing ldos might get out of their
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700420 * operating range. Hence configure such kraits to be in hs mode prior
421 * to setting the pmic gang voltage
422 */
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800423 rc = configure_ldo_or_hs_all(from, vmax);
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700424 if (rc < 0) {
425 dev_err(&from->rdev->dev, "%s failed ldo/hs conf %d rc = %d\n",
426 pvreg->name, vmax, rc);
427 return rc;
428 }
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700429
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800430 rc = set_pmic_gang_voltage(pvreg, vmax);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700431 if (rc < 0) {
432 dev_err(&from->rdev->dev, "%s failed set voltage %d rc = %d\n",
433 pvreg->name, vmax, rc);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700434 }
435
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700436 return rc;
437}
438
439#define PHASE_SETTLING_TIME_US 10
440static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
441 int load_uA)
442{
443 struct pmic_gang_vreg *pvreg = from->pvreg;
444 int phase_count = DIV_ROUND_UP(load_uA, LOAD_PER_PHASE) - 1;
445 int rc = 0;
446
447 if (phase_count < 0)
448 phase_count = 0;
449
450 if (phase_count != pvreg->pmic_phase_count) {
451 rc = set_pmic_gang_phases(phase_count);
452 if (rc < 0) {
453 dev_err(&from->rdev->dev,
454 "%s failed set phase %d rc = %d\n",
455 pvreg->name, phase_count, rc);
456 return rc;
457 }
458
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800459 /* complete the writes before the delay */
460 mb();
461
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700462 /*
463 * delay until the phases are settled when
464 * the count is raised
465 */
466 if (phase_count > pvreg->pmic_phase_count)
467 udelay(PHASE_SETTLING_TIME_US);
468
469 pvreg->pmic_phase_count = phase_count;
470 }
471 return rc;
472}
473
Matt Wagantall98bfbe92012-11-12 18:39:47 -0800474static int __devinit pvreg_init(struct platform_device *pdev)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700475{
476 struct pmic_gang_vreg *pvreg;
477
478 pvreg = devm_kzalloc(&pdev->dev,
479 sizeof(struct pmic_gang_vreg), GFP_KERNEL);
480 if (!pvreg) {
481 pr_err("kzalloc failed.\n");
482 return -ENOMEM;
483 }
484
485 pvreg->name = "pmic_gang";
486 pvreg->pmic_vmax_uV = PMIC_VOLTAGE_MIN;
487 pvreg->pmic_phase_count = 1;
488
489 mutex_init(&pvreg->krait_power_vregs_lock);
490 INIT_LIST_HEAD(&pvreg->krait_power_vregs);
491 the_gang = pvreg;
492
493 pr_debug("name=%s inited\n", pvreg->name);
494
495 return 0;
496}
497
498static int krait_power_get_voltage(struct regulator_dev *rdev)
499{
500 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
501
502 return kvreg->uV;
503}
504
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800505static int get_vmax(struct pmic_gang_vreg *pvreg)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700506{
507 int vmax = 0;
508 int v;
509 struct krait_power_vreg *kvreg;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700510
511 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800512 if (!kvreg->online)
513 continue;
514
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700515 v = kvreg->uV;
516
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700517 if (vmax < v)
518 vmax = v;
519 }
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800520
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700521 return vmax;
522}
523
524static int get_total_load(struct krait_power_vreg *from)
525{
526 int load_total = 0;
527 struct krait_power_vreg *kvreg;
528 struct pmic_gang_vreg *pvreg = from->pvreg;
529
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800530 list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
531 if (!kvreg->online)
532 continue;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700533 load_total += kvreg->load_uA;
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800534 }
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700535
536 return load_total;
537}
538
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700539#define ROUND_UP_VOLTAGE(v, res) (DIV_ROUND_UP(v, res) * res)
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800540static int _set_voltage(struct regulator_dev *rdev,
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800541 int orig_krait_uV, int requested_uV)
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700542{
543 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
544 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
545 int rc;
546 int vmax;
547
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800548 pr_debug("%s: %d to %d\n", kvreg->name, orig_krait_uV, requested_uV);
549 /*
550 * Assign the voltage before updating the gang voltage as we iterate
551 * over all the core voltages and choose HS or LDO for each of them
552 */
553 kvreg->uV = requested_uV;
554
555 vmax = get_vmax(pvreg);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800556
557 /* round up the pmic voltage as per its resolution */
558 vmax = ROUND_UP_VOLTAGE(vmax, LV_RANGE_STEP);
559
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800560 if (requested_uV > orig_krait_uV)
561 rc = krait_voltage_increase(kvreg, vmax);
562 else
563 rc = krait_voltage_decrease(kvreg, vmax);
564
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800565 if (rc < 0) {
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800566 dev_err(&rdev->dev, "%s failed to set %duV from %duV rc = %d\n",
567 kvreg->name, requested_uV, orig_krait_uV, rc);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800568 }
569
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800570 return rc;
571}
572
573static int krait_power_set_voltage(struct regulator_dev *rdev,
574 int min_uV, int max_uV, unsigned *selector)
575{
576 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
577 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
578 int rc;
579
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700580 /*
581 * if the voltage requested is below LDO_THRESHOLD this cpu could
582 * switch to LDO mode. Hence round the voltage as per the LDO
583 * resolution
584 */
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700585 if (min_uV < kvreg->ldo_threshold_uV) {
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700586 if (min_uV < KRAIT_LDO_VOLTAGE_MIN)
587 min_uV = KRAIT_LDO_VOLTAGE_MIN;
588 min_uV = ROUND_UP_VOLTAGE(min_uV, KRAIT_LDO_STEP);
589 }
590
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700591 mutex_lock(&pvreg->krait_power_vregs_lock);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800592 if (!kvreg->online) {
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800593 kvreg->uV = min_uV;
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800594 mutex_unlock(&pvreg->krait_power_vregs_lock);
595 return 0;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700596 }
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700597
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800598 rc = _set_voltage(rdev, kvreg->uV, min_uV);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700599 mutex_unlock(&pvreg->krait_power_vregs_lock);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800600
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700601 return rc;
602}
603
Abhijeet Dharmapurikar6a42ef82012-10-18 19:37:36 -0700604#define PMIC_FTS_MODE_PFM 0x00
605#define PMIC_FTS_MODE_PWM 0x80
606#define PFM_LOAD_UA 500000
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800607static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700608 int input_uV, int output_uV, int load_uA)
609{
610 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
611 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
612 int rc;
613 int load_total_uA;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700614
615 load_total_uA = get_total_load(kvreg);
616
Abhijeet Dharmapurikar6a42ef82012-10-18 19:37:36 -0700617 if (load_total_uA < PFM_LOAD_UA) {
618 if (!pvreg->pfm_mode) {
619 rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
620 if (rc) {
621 dev_err(&rdev->dev,
622 "%s enter PFM failed load %d rc = %d\n",
623 kvreg->name, load_total_uA, rc);
624 goto out;
625 } else {
626 pvreg->pfm_mode = true;
627 }
628 }
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800629 return kvreg->mode;
Abhijeet Dharmapurikar6a42ef82012-10-18 19:37:36 -0700630 }
631
632 if (pvreg->pfm_mode) {
633 rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
634 if (rc) {
635 dev_err(&rdev->dev,
636 "%s exit PFM failed load %d rc = %d\n",
637 kvreg->name, load_total_uA, rc);
638 goto out;
639 } else {
640 pvreg->pfm_mode = false;
641 }
642 }
643
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700644 rc = pmic_gang_set_phases(kvreg, load_total_uA);
645 if (rc < 0) {
646 dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
647 kvreg->name, load_total_uA, rc);
648 goto out;
649 }
650
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700651out:
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800652 return kvreg->mode;
653}
654
655static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
656 int input_uV, int output_uV, int load_uA)
657{
658 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
659 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
660 int rc;
661
662 mutex_lock(&pvreg->krait_power_vregs_lock);
663 kvreg->load_uA = load_uA;
664 if (!kvreg->online) {
665 mutex_unlock(&pvreg->krait_power_vregs_lock);
666 return kvreg->mode;
667 }
668
669 rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700670 mutex_unlock(&pvreg->krait_power_vregs_lock);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800671
672 return rc;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700673}
674
675static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
676{
677 return 0;
678}
679
680static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
681{
682 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
683
684 return kvreg->mode;
685}
686
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800687static int krait_power_is_enabled(struct regulator_dev *rdev)
688{
689 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
690
691 return kvreg->online;
692}
693
694static int krait_power_enable(struct regulator_dev *rdev)
695{
696 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
697 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
698 int rc;
699
700 mutex_lock(&pvreg->krait_power_vregs_lock);
701 kvreg->online = true;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800702 rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800703 if (rc < 0)
704 goto en_err;
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800705 /*
706 * since the core is being enabled, behave as if it is increasing
707 * the core voltage
708 */
709 rc = _set_voltage(rdev, 0, kvreg->uV);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800710en_err:
711 mutex_unlock(&pvreg->krait_power_vregs_lock);
712 return rc;
713}
714
715static int krait_power_disable(struct regulator_dev *rdev)
716{
717 struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
718 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
719 int rc;
720
721 mutex_lock(&pvreg->krait_power_vregs_lock);
722 kvreg->online = false;
723
724 rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV,
725 kvreg->load_uA);
726 if (rc < 0)
727 goto dis_err;
728
Abhijeet Dharmapurikarfe1306b2012-11-15 18:09:31 -0800729 rc = _set_voltage(rdev, kvreg->uV, kvreg->uV);
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800730dis_err:
731 mutex_unlock(&pvreg->krait_power_vregs_lock);
732 return rc;
733}
734
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700735static struct regulator_ops krait_power_ops = {
736 .get_voltage = krait_power_get_voltage,
737 .set_voltage = krait_power_set_voltage,
738 .get_optimum_mode = krait_power_get_optimum_mode,
739 .set_mode = krait_power_set_mode,
740 .get_mode = krait_power_get_mode,
Michael Bohanb5d1cdb2012-11-08 18:09:52 -0800741 .enable = krait_power_enable,
742 .disable = krait_power_disable,
743 .is_enabled = krait_power_is_enabled,
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700744};
745
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700746static void kvreg_hw_init(struct krait_power_vreg *kvreg)
747{
748 /*
749 * bhs_cnt value sets the ramp-up time from power collapse,
750 * initialize the ramp up time
751 */
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700752 set_krait_retention_uv(kvreg, kvreg->retention_uV);
753 set_krait_ldo_uv(kvreg, kvreg->ldo_default_uV);
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800754
755 /* setup the bandgap that configures the reference to the LDO */
756 writel_relaxed(0x00000190, kvreg->mdd_base + MDD_CONFIG_CTL);
757 /* Enable MDD */
758 writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
759 mb();
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700760}
761
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700762static void glb_init(struct platform_device *pdev)
763{
764 /* configure bi-modal switch */
765 writel_relaxed(0x0008736E, MSM_APCS_GCC_BASE + PWR_GATE_CONFIG);
766 /* read kpss version */
767 version = readl_relaxed(MSM_APCS_GCC_BASE + VERSION);
768 pr_debug("version= 0x%x\n", version);
769}
770
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700771static int is_between(int left, int right, int value)
772{
773 if (left >= right && left >= value && value >= right)
774 return 1;
775 if (left <= right && left <= value && value <= right)
776 return 1;
777 return 0;
778}
779
780#define LDO_HDROOM_MIN 50000
781#define LDO_HDROOM_MAX 250000
782
783#define LDO_UV_MIN 465000
784#define LDO_UV_MAX 750000
785
786#define LDO_TH_MIN 600000
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800787#define LDO_TH_MAX 900000
788
789#define LDO_DELTA_MIN 10000
790#define LDO_DELTA_MAX 100000
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700791
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700792static int __devinit krait_power_probe(struct platform_device *pdev)
793{
794 struct krait_power_vreg *kvreg;
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800795 struct resource *res, *res_mdd;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700796 struct regulator_init_data *init_data = pdev->dev.platform_data;
797 int rc = 0;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700798 int headroom_uV, retention_uV, ldo_default_uV, ldo_threshold_uV;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800799 int ldo_delta_uV;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700800
801 /* Initialize the pmic gang if it hasn't been initialized already */
802 if (the_gang == NULL) {
803 rc = pvreg_init(pdev);
804 if (rc < 0) {
805 dev_err(&pdev->dev,
806 "failed to init pmic gang rc = %d\n", rc);
807 return rc;
808 }
Abhijeet Dharmapurikar3ff7cba2012-10-10 17:48:29 -0700809 /* global initializtion */
810 glb_init(pdev);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700811 }
812
813 if (pdev->dev.of_node) {
814 /* Get init_data from device tree. */
815 init_data = of_get_regulator_init_data(&pdev->dev,
816 pdev->dev.of_node);
817 init_data->constraints.valid_ops_mask
818 |= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_DRMS
819 | REGULATOR_CHANGE_MODE;
820 init_data->constraints.valid_modes_mask
821 |= REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE
822 | REGULATOR_MODE_FAST;
823 init_data->constraints.input_uV = init_data->constraints.max_uV;
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700824 rc = of_property_read_u32(pdev->dev.of_node,
825 "qcom,headroom-voltage",
826 &headroom_uV);
827 if (rc < 0) {
828 pr_err("headroom-voltage missing rc=%d\n", rc);
829 return rc;
830 }
831 if (!is_between(LDO_HDROOM_MIN, LDO_HDROOM_MAX, headroom_uV)) {
832 pr_err("bad headroom-voltage = %d specified\n",
833 headroom_uV);
834 return -EINVAL;
835 }
836
837 rc = of_property_read_u32(pdev->dev.of_node,
838 "qcom,retention-voltage",
839 &retention_uV);
840 if (rc < 0) {
841 pr_err("retention-voltage missing rc=%d\n", rc);
842 return rc;
843 }
844 if (!is_between(LDO_UV_MIN, LDO_UV_MAX, retention_uV)) {
845 pr_err("bad retention-voltage = %d specified\n",
846 retention_uV);
847 return -EINVAL;
848 }
849
850 rc = of_property_read_u32(pdev->dev.of_node,
851 "qcom,ldo-default-voltage",
852 &ldo_default_uV);
853 if (rc < 0) {
854 pr_err("ldo-default-voltage missing rc=%d\n", rc);
855 return rc;
856 }
857 if (!is_between(LDO_UV_MIN, LDO_UV_MAX, ldo_default_uV)) {
858 pr_err("bad ldo-default-voltage = %d specified\n",
859 ldo_default_uV);
860 return -EINVAL;
861 }
862
863 rc = of_property_read_u32(pdev->dev.of_node,
864 "qcom,ldo-threshold-voltage",
865 &ldo_threshold_uV);
866 if (rc < 0) {
867 pr_err("ldo-threshold-voltage missing rc=%d\n", rc);
868 return rc;
869 }
870 if (!is_between(LDO_TH_MIN, LDO_TH_MAX, ldo_threshold_uV)) {
871 pr_err("bad ldo-threshold-voltage = %d specified\n",
872 ldo_threshold_uV);
873 return -EINVAL;
874 }
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800875
876 rc = of_property_read_u32(pdev->dev.of_node,
877 "qcom,ldo-delta-voltage",
878 &ldo_delta_uV);
879 if (rc < 0) {
880 pr_err("ldo-delta-voltage missing rc=%d\n", rc);
881 return rc;
882 }
883 if (!is_between(LDO_DELTA_MIN, LDO_DELTA_MAX, ldo_delta_uV)) {
884 pr_err("bad ldo-delta-voltage = %d specified\n",
885 ldo_delta_uV);
886 return -EINVAL;
887 }
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700888 }
889
890 if (!init_data) {
891 dev_err(&pdev->dev, "init data required.\n");
892 return -EINVAL;
893 }
894
895 if (!init_data->constraints.name) {
896 dev_err(&pdev->dev,
897 "regulator name must be specified in constraints.\n");
898 return -EINVAL;
899 }
900
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800901 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acs");
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700902 if (!res) {
903 dev_err(&pdev->dev, "missing physical register addresses\n");
904 return -EINVAL;
905 }
906
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800907 res_mdd = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdd");
908 if (!res_mdd) {
909 dev_err(&pdev->dev, "missing mdd register addresses\n");
910 return -EINVAL;
911 }
912
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700913 kvreg = devm_kzalloc(&pdev->dev,
914 sizeof(struct krait_power_vreg), GFP_KERNEL);
915 if (!kvreg) {
916 dev_err(&pdev->dev, "kzalloc failed.\n");
917 return -ENOMEM;
918 }
919
920 kvreg->reg_base = devm_ioremap(&pdev->dev,
921 res->start, resource_size(res));
922
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -0800923 kvreg->mdd_base = devm_ioremap(&pdev->dev,
924 res_mdd->start, resource_size(res));
925
Abhijeet Dharmapurikar34f0d642012-10-25 12:35:23 -0700926 kvreg->pvreg = the_gang;
927 kvreg->name = init_data->constraints.name;
928 kvreg->desc.name = kvreg->name;
929 kvreg->desc.ops = &krait_power_ops;
930 kvreg->desc.type = REGULATOR_VOLTAGE;
931 kvreg->desc.owner = THIS_MODULE;
932 kvreg->uV = CORE_VOLTAGE_MIN;
933 kvreg->mode = HS_MODE;
934 kvreg->desc.ops = &krait_power_ops;
935 kvreg->headroom_uV = headroom_uV;
936 kvreg->retention_uV = retention_uV;
937 kvreg->ldo_default_uV = ldo_default_uV;
938 kvreg->ldo_threshold_uV = ldo_threshold_uV;
Abhijeet Dharmapurikar2269db02012-12-05 15:49:20 -0800939 kvreg->ldo_delta_uV = ldo_delta_uV;
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700940
941 platform_set_drvdata(pdev, kvreg);
942
943 mutex_lock(&the_gang->krait_power_vregs_lock);
944 list_add_tail(&kvreg->link, &the_gang->krait_power_vregs);
945 mutex_unlock(&the_gang->krait_power_vregs_lock);
946
947 kvreg->rdev = regulator_register(&kvreg->desc, &pdev->dev, init_data,
948 kvreg, pdev->dev.of_node);
949 if (IS_ERR(kvreg->rdev)) {
950 rc = PTR_ERR(kvreg->rdev);
951 pr_err("regulator_register failed, rc=%d.\n", rc);
952 goto out;
953 }
954
Abhijeet Dharmapurikar152a7082012-05-14 20:25:59 -0700955 kvreg_hw_init(kvreg);
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -0700956 dev_dbg(&pdev->dev, "id=%d, name=%s\n", pdev->id, kvreg->name);
957
958 return 0;
959out:
960 mutex_lock(&the_gang->krait_power_vregs_lock);
961 list_del(&kvreg->link);
962 mutex_unlock(&the_gang->krait_power_vregs_lock);
963
964 platform_set_drvdata(pdev, NULL);
965 return rc;
966}
967
968static int __devexit krait_power_remove(struct platform_device *pdev)
969{
970 struct krait_power_vreg *kvreg = platform_get_drvdata(pdev);
971 struct pmic_gang_vreg *pvreg = kvreg->pvreg;
972
973 mutex_lock(&pvreg->krait_power_vregs_lock);
974 list_del(&kvreg->link);
975 mutex_unlock(&pvreg->krait_power_vregs_lock);
976
977 regulator_unregister(kvreg->rdev);
978 platform_set_drvdata(pdev, NULL);
979 return 0;
980}
981
982static struct of_device_id krait_power_match_table[] = {
983 { .compatible = "qcom,krait-regulator", },
984 {}
985};
986
987static struct platform_driver krait_power_driver = {
988 .probe = krait_power_probe,
989 .remove = __devexit_p(krait_power_remove),
990 .driver = {
991 .name = KRAIT_REGULATOR_DRIVER_NAME,
992 .of_match_table = krait_power_match_table,
993 .owner = THIS_MODULE,
994 },
995};
996
997int __init krait_power_init(void)
998{
999 return platform_driver_register(&krait_power_driver);
1000}
1001
1002static void __exit krait_power_exit(void)
1003{
1004 platform_driver_unregister(&krait_power_driver);
1005}
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001006module_exit(krait_power_exit);
1007
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001008void secondary_cpu_hs_init(void *base_ptr)
1009{
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001010 /* Turn on the BHS, turn off LDO Bypass and power down LDO */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001011 writel_relaxed(
1012 BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
1013 | LDO_PWR_DWN_MASK
1014 | CLK_SRC_DEFAULT << CLK_SRC_SEL_BIT_POS
1015 | BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS
1016 | BHS_EN_MASK,
1017 base_ptr + APC_PWR_GATE_CTL);
1018
1019 /* complete the above write before the delay */
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001020 mb();
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001021
1022 /*
1023 * wait for the bhs to settle
1024 */
1025 udelay(BHS_SETTLING_DELAY_US);
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001026
1027 /* Finally turn on the bypass so that BHS supplies power */
Abhijeet Dharmapurikar749ecd42012-11-08 17:29:04 -08001028 writel_relaxed(
1029 BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
1030 | LDO_PWR_DWN_MASK
1031 | CLK_SRC_DEFAULT << CLK_SRC_SEL_BIT_POS
1032 | LDO_BYP_MASK
1033 | BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS
1034 | BHS_EN_MASK,
1035 base_ptr + APC_PWR_GATE_CTL);
Abhijeet Dharmapurikare8571ef2012-08-14 20:44:58 -07001036}
1037
Abhijeet Dharmapurikar00269e52012-05-14 17:59:10 -07001038MODULE_LICENSE("GPL v2");
1039MODULE_DESCRIPTION("KRAIT POWER regulator driver");
1040MODULE_VERSION("1.0");
1041MODULE_ALIAS("platform:"KRAIT_REGULATOR_DRIVER_NAME);