blob: 328d21dba52d6f4130aa97253b33ab04c4e5f092 [file] [log] [blame]
Matthew Qin3aa87052014-02-21 10:32:34 +08001/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Deepa Dinamani22799652012-07-21 12:26:22 -07002
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +053012 * * Neither the name of The Linux Foundation, Inc. nor the names of its
Deepa Dinamani22799652012-07-21 12:26:22 -070013 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
Deepa Dinamani9a612932012-08-14 16:15:03 -070029#include <bits.h>
Deepa Dinamani22799652012-07-21 12:26:22 -070030#include <debug.h>
31#include <reg.h>
32#include <spmi.h>
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +053033#include <string.h>
Deepa Dinamani22799652012-07-21 12:26:22 -070034#include <pm8x41_hw.h>
Deepa Dinamani9a612932012-08-14 16:15:03 -070035#include <pm8x41.h>
36#include <platform/timer.h>
Deepa Dinamani22799652012-07-21 12:26:22 -070037
Aparna Mallavarapu083766b2014-07-21 21:04:48 +053038static uint8_t mpp_slave_id;
39
vijay kumar9ec33942014-08-08 17:25:46 +053040void pmi8994_config_mpp_slave_id(uint8_t slave_id)
Aparna Mallavarapu083766b2014-07-21 21:04:48 +053041{
42 mpp_slave_id = slave_id;
43}
Channagoud Kadabid091f702013-01-07 16:17:37 -080044/* SPMI helper functions */
45uint8_t pm8x41_reg_read(uint32_t addr)
Deepa Dinamani9a612932012-08-14 16:15:03 -070046{
47 uint8_t val = 0;
48 struct pmic_arb_cmd cmd;
49 struct pmic_arb_param param;
50
51 cmd.address = PERIPH_ID(addr);
52 cmd.offset = REG_OFFSET(addr);
53 cmd.slave_id = SLAVE_ID(addr);
54 cmd.priority = 0;
55
56 param.buffer = &val;
57 param.size = 1;
58
59 pmic_arb_read_cmd(&cmd, &param);
60
61 return val;
62}
63
Channagoud Kadabid091f702013-01-07 16:17:37 -080064void pm8x41_reg_write(uint32_t addr, uint8_t val)
Deepa Dinamani22799652012-07-21 12:26:22 -070065{
66 struct pmic_arb_cmd cmd;
67 struct pmic_arb_param param;
Deepa Dinamani22799652012-07-21 12:26:22 -070068
Deepa Dinamani9a612932012-08-14 16:15:03 -070069 cmd.address = PERIPH_ID(addr);
70 cmd.offset = REG_OFFSET(addr);
71 cmd.slave_id = SLAVE_ID(addr);
Deepa Dinamani22799652012-07-21 12:26:22 -070072 cmd.priority = 0;
Deepa Dinamani22799652012-07-21 12:26:22 -070073
Deepa Dinamani9a612932012-08-14 16:15:03 -070074 param.buffer = &val;
75 param.size = 1;
Deepa Dinamani22799652012-07-21 12:26:22 -070076
Deepa Dinamani9a612932012-08-14 16:15:03 -070077 pmic_arb_write_cmd(&cmd, &param);
78}
Deepa Dinamani22799652012-07-21 12:26:22 -070079
Deepa Dinamani9a612932012-08-14 16:15:03 -070080/* Exported functions */
81
82/* Set the boot done flag */
83void pm8x41_set_boot_done()
84{
85 uint8_t val;
86
87 val = REG_READ(SMBB_MISC_BOOT_DONE);
88 val |= BIT(BOOT_DONE_BIT);
89 REG_WRITE(SMBB_MISC_BOOT_DONE, val);
90}
91
92/* Configure GPIO */
93int pm8x41_gpio_config(uint8_t gpio, struct pm8x41_gpio *config)
94{
95 uint8_t val;
96 uint32_t gpio_base = GPIO_N_PERIPHERAL_BASE(gpio);
97
98 /* Disable the GPIO */
99 val = REG_READ(gpio_base + GPIO_EN_CTL);
100 val &= ~BIT(PERPH_EN_BIT);
101 REG_WRITE(gpio_base + GPIO_EN_CTL, val);
102
103 /* Select the mode */
104 val = config->function | (config->direction << 4);
105 REG_WRITE(gpio_base + GPIO_MODE_CTL, val);
106
107 /* Set the right pull */
108 val = config->pull;
109 REG_WRITE(gpio_base + GPIO_DIG_PULL_CTL, val);
110
111 /* Select the VIN */
112 val = config->vin_sel;
113 REG_WRITE(gpio_base + GPIO_DIG_VIN_CTL, val);
114
Siddhartha Agrawald61f81e2012-12-17 19:20:35 -0800115 if (config->direction == PM_GPIO_DIR_OUT) {
116 /* Set the right dig out control */
117 val = config->out_strength | (config->output_buffer << 4);
118 REG_WRITE(gpio_base + GPIO_DIG_OUT_CTL, val);
119 }
120
Deepa Dinamani9a612932012-08-14 16:15:03 -0700121 /* Enable the GPIO */
122 val = REG_READ(gpio_base + GPIO_EN_CTL);
123 val |= BIT(PERPH_EN_BIT);
124 REG_WRITE(gpio_base + GPIO_EN_CTL, val);
125
Siddhartha Agrawald61f81e2012-12-17 19:20:35 -0800126 return 0;
Deepa Dinamani9a612932012-08-14 16:15:03 -0700127}
128
129/* Reads the status of requested gpio */
130int pm8x41_gpio_get(uint8_t gpio, uint8_t *status)
131{
132 uint32_t gpio_base = GPIO_N_PERIPHERAL_BASE(gpio);
133
134 *status = REG_READ(gpio_base + GPIO_STATUS);
135
136 /* Return the value of the GPIO pin */
137 *status &= BIT(GPIO_STATUS_VAL_BIT);
138
139 dprintf(SPEW, "GPIO %d status is %d\n", gpio, *status);
140
Siddhartha Agrawald61f81e2012-12-17 19:20:35 -0800141 return 0;
142}
143
144/* Write the output value of the requested gpio */
145int pm8x41_gpio_set(uint8_t gpio, uint8_t value)
146{
147 uint32_t gpio_base = GPIO_N_PERIPHERAL_BASE(gpio);
148 uint8_t val;
149
150 /* Set the output value of the gpio */
151 val = REG_READ(gpio_base + GPIO_MODE_CTL);
152 val = (val & ~PM_GPIO_OUTPUT_MASK) | value;
153 REG_WRITE(gpio_base + GPIO_MODE_CTL, val);
154
155 return 0;
Deepa Dinamani9a612932012-08-14 16:15:03 -0700156}
157
Kuogee Hsieh383a5ae2014-09-02 16:31:39 -0700158/* Configure PM and PMI GPIO with slave id */
159int pm8x41_gpio_config_sid(uint8_t sid, uint8_t gpio, struct pm8x41_gpio *config)
160{
161 uint8_t val;
162 uint32_t gpio_base = GPIO_N_PERIPHERAL_BASE(gpio);
163
164 gpio_base &= 0x0ffff; /* clear sid */
165 gpio_base |= (sid << 16); /* add sid */
166
167 dprintf(SPEW, "%s: gpio=%d base=%x\n", __func__, gpio, gpio_base);
168
169 /* Disable the GPIO */
170 val = REG_READ(gpio_base + GPIO_EN_CTL);
171 val &= ~BIT(PERPH_EN_BIT);
172 REG_WRITE(gpio_base + GPIO_EN_CTL, val);
173
174 /* Select the mode */
175 val = config->function | (config->direction << 4);
176 REG_WRITE(gpio_base + GPIO_MODE_CTL, val);
177
178 /* Set the right pull */
179 val = config->pull;
180 REG_WRITE(gpio_base + GPIO_DIG_PULL_CTL, val);
181
182 /* Select the VIN */
183 val = config->vin_sel;
184 REG_WRITE(gpio_base + GPIO_DIG_VIN_CTL, val);
185
186 if (config->direction == PM_GPIO_DIR_OUT) {
187 /* Set the right dig out control */
188 val = config->out_strength | (config->output_buffer << 4);
189 REG_WRITE(gpio_base + GPIO_DIG_OUT_CTL, val);
190 }
191
192 /* Enable the GPIO */
193 val = REG_READ(gpio_base + GPIO_EN_CTL);
194 val |= BIT(PERPH_EN_BIT);
195 REG_WRITE(gpio_base + GPIO_EN_CTL, val);
196
197 return 0;
198}
199
200/* Reads the status of requested gpio */
201int pm8x41_gpio_get_sid(uint8_t sid, uint8_t gpio, uint8_t *status)
202{
203 uint32_t gpio_base = GPIO_N_PERIPHERAL_BASE(gpio);
204
205 gpio_base &= 0x0ffff; /* clear sid */
206 gpio_base |= (sid << 16); /* add sid */
207
208 *status = REG_READ(gpio_base + GPIO_STATUS);
209
210 /* Return the value of the GPIO pin */
211 *status &= BIT(GPIO_STATUS_VAL_BIT);
212
213 dprintf(SPEW, "GPIO %d status is %d\n", gpio, *status);
214
215 return 0;
216}
217
218/* Write the output value of the requested gpio */
219int pm8x41_gpio_set_sid(uint8_t sid, uint8_t gpio, uint8_t value)
220{
221 uint32_t gpio_base = GPIO_N_PERIPHERAL_BASE(gpio);
222 uint8_t val;
223
224 gpio_base &= 0x0ffff; /* clear sid */
225 gpio_base |= (sid << 16); /* add sid */
226
227 dprintf(SPEW, "%s: gpio=%d base=%x\n", __func__, gpio, gpio_base);
228
229 /* Set the output value of the gpio */
230 val = REG_READ(gpio_base + GPIO_MODE_CTL);
231 val = (val & ~PM_GPIO_OUTPUT_MASK) | value;
232 REG_WRITE(gpio_base + GPIO_MODE_CTL, val);
233
234 return 0;
235}
236
Deepa Dinamanic7f87582013-02-01 15:24:49 -0800237/* Prepare PON RESIN S2 reset (bite) */
238void pm8x41_resin_s2_reset_enable()
Deepa Dinamani9a612932012-08-14 16:15:03 -0700239{
240 uint8_t val;
241
242 /* disable s2 reset */
243 REG_WRITE(PON_RESIN_N_RESET_S2_CTL, 0x0);
244
Amol Jadi7ec52b42012-08-16 14:12:45 -0700245 /* Delay needed for disable to kick in. */
246 udelay(300);
247
Deepa Dinamani9a612932012-08-14 16:15:03 -0700248 /* configure s1 timer to 0 */
249 REG_WRITE(PON_RESIN_N_RESET_S1_TIMER, 0x0);
250
251 /* configure s2 timer to 2s */
252 REG_WRITE(PON_RESIN_N_RESET_S2_TIMER, PON_RESIN_N_RESET_S2_TIMER_MAX_VALUE);
253
254 /* configure reset type */
255 REG_WRITE(PON_RESIN_N_RESET_S2_CTL, S2_RESET_TYPE_WARM);
256
257 val = REG_READ(PON_RESIN_N_RESET_S2_CTL);
258
259 /* enable s2 reset */
260 val |= BIT(S2_RESET_EN_BIT);
261 REG_WRITE(PON_RESIN_N_RESET_S2_CTL, val);
262}
263
Deepa Dinamanic7f87582013-02-01 15:24:49 -0800264/* Disable PON RESIN S2 reset. (bite)*/
265void pm8x41_resin_s2_reset_disable()
Deepa Dinamani9a612932012-08-14 16:15:03 -0700266{
267 /* disable s2 reset */
268 REG_WRITE(PON_RESIN_N_RESET_S2_CTL, 0x0);
Amol Jadi7ec52b42012-08-16 14:12:45 -0700269
270 /* Delay needed for disable to kick in. */
271 udelay(300);
Deepa Dinamani9a612932012-08-14 16:15:03 -0700272}
273
Deepa Dinamanic7f87582013-02-01 15:24:49 -0800274/* Resin irq status for faulty pmic*/
Channagoud Kadabi36c19ea2013-07-05 16:28:44 -0700275uint32_t pm8x41_v2_resin_status()
Deepa Dinamani9a612932012-08-14 16:15:03 -0700276{
277 uint8_t rt_sts = 0;
278
279 /* Enable S2 reset so we can detect the volume down key press */
Deepa Dinamanic7f87582013-02-01 15:24:49 -0800280 pm8x41_resin_s2_reset_enable();
Deepa Dinamani9a612932012-08-14 16:15:03 -0700281
282 /* Delay before interrupt triggering.
283 * See PON_DEBOUNCE_CTL reg.
284 */
285 mdelay(100);
286
287 rt_sts = REG_READ(PON_INT_RT_STS);
288
289 /* Must disable S2 reset otherwise PMIC will reset if key
290 * is held longer than S2 timer.
291 */
Deepa Dinamanic7f87582013-02-01 15:24:49 -0800292 pm8x41_resin_s2_reset_disable();
Deepa Dinamani9a612932012-08-14 16:15:03 -0700293
294 return (rt_sts & BIT(RESIN_BARK_INT_BIT));
Deepa Dinamani22799652012-07-21 12:26:22 -0700295}
Neeti Desai120b55d2012-08-20 17:15:56 -0700296
Deepa Dinamanic7f87582013-02-01 15:24:49 -0800297/* Resin pin status */
298uint32_t pm8x41_resin_status()
299{
300 uint8_t rt_sts = 0;
301
302 rt_sts = REG_READ(PON_INT_RT_STS);
303
304 return (rt_sts & BIT(RESIN_ON_INT_BIT));
305}
306
Matthew Qin3aa87052014-02-21 10:32:34 +0800307/* Return 1 if power key is pressed */
308uint32_t pm8x41_get_pwrkey_is_pressed()
309{
310 uint8_t pwr_sts = 0;
311
312 pwr_sts = REG_READ(PON_INT_RT_STS);
313
314 if (pwr_sts & BIT(KPDPWR_ON_INT_BIT))
315 return 1;
316 else
317 return 0;
318}
319
Deepa Dinamani3c9865d2013-03-08 14:03:19 -0800320void pm8x41_v2_reset_configure(uint8_t reset_type)
Neeti Desai120b55d2012-08-20 17:15:56 -0700321{
322 uint8_t val;
323
324 /* disable PS_HOLD_RESET */
325 REG_WRITE(PON_PS_HOLD_RESET_CTL, 0x0);
326
327 /* Delay needed for disable to kick in. */
328 udelay(300);
329
330 /* configure reset type */
331 REG_WRITE(PON_PS_HOLD_RESET_CTL, reset_type);
332
333 val = REG_READ(PON_PS_HOLD_RESET_CTL);
334
335 /* enable PS_HOLD_RESET */
336 val |= BIT(S2_RESET_EN_BIT);
337 REG_WRITE(PON_PS_HOLD_RESET_CTL, val);
338}
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530339
Deepa Dinamani3c9865d2013-03-08 14:03:19 -0800340void pm8x41_reset_configure(uint8_t reset_type)
341{
342 /* disable PS_HOLD_RESET */
343 REG_WRITE(PON_PS_HOLD_RESET_CTL2, 0x0);
344
345 /* Delay needed for disable to kick in. */
346 udelay(300);
347
348 /* configure reset type */
349 REG_WRITE(PON_PS_HOLD_RESET_CTL, reset_type);
350
351 /* enable PS_HOLD_RESET */
352 REG_WRITE(PON_PS_HOLD_RESET_CTL2, BIT(S2_RESET_EN_BIT));
353}
354
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530355/*
356 * LDO set voltage, takes ldo name & voltage in UV as input
357 */
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700358int pm8x41_ldo_set_voltage(struct pm8x41_ldo *ldo, uint32_t voltage)
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530359{
360 uint32_t range = 0;
361 uint32_t step = 0;
362 uint32_t mult = 0;
363 uint32_t val = 0;
364 uint32_t vmin = 0;
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530365
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700366 if (!ldo)
367 {
368 dprintf(CRITICAL, "LDO pointer is invalid: %p\n", ldo);
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530369 return 1;
370 }
371
372 /* Program Normal power mode */
373 val = 0x0;
374 val = (1 << LDO_NORMAL_PWR_BIT);
375 REG_WRITE((ldo->base + LDO_POWER_MODE), val);
376
377 /*
378 * Select range, step & vmin based on input voltage & type of LDO
379 * LDO can operate in low, mid, high power mode
380 */
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700381 if (ldo->type == PLDO_TYPE)
382 {
383 if (voltage < PLDO_UV_MIN)
384 {
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530385 range = 2;
386 step = PLDO_UV_STEP_LOW;
387 vmin = PLDO_UV_VMIN_LOW;
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700388 }
389 else if (voltage < PDLO_UV_MID)
390 {
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530391 range = 3;
392 step = PLDO_UV_STEP_MID;
393 vmin = PLDO_UV_VMIN_MID;
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700394 }
395 else
396 {
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530397 range = 4;
398 step = PLDO_UV_STEP_HIGH;
399 vmin = PLDO_UV_VMIN_HIGH;
400 }
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700401 }
402 else
403 {
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530404 range = 2;
405 step = NLDO_UV_STEP;
406 vmin = NLDO_UV_VMIN_LOW;
407 }
408
409 mult = (voltage - vmin) / step;
410
411 /* Set Range in voltage ctrl register */
412 val = 0x0;
413 val = range << LDO_RANGE_SEL_BIT;
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700414 REG_WRITE((ldo->base + LDO_RANGE_CTRL), val);
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530415
416 /* Set multiplier in voltage ctrl register */
417 val = 0x0;
418 val = mult << LDO_VSET_SEL_BIT;
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700419 REG_WRITE((ldo->base + LDO_STEP_CTRL), val);
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530420
421 return 0;
422}
423
424/*
425 * Enable or Disable LDO
426 */
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700427int pm8x41_ldo_control(struct pm8x41_ldo *ldo, uint8_t enable)
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530428{
429 uint32_t val = 0;
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530430
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700431 if (!ldo)
432 {
433 dprintf(CRITICAL, "LDO pointer is invalid: %p\n", ldo);
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530434 return 1;
435 }
436
437 /* Enable LDO */
438 if (enable)
439 val = (1 << LDO_VREG_ENABLE_BIT);
440 else
441 val = (0 << LDO_VREG_ENABLE_BIT);
442
Deepa Dinamanie69ba612013-06-03 16:10:09 -0700443 REG_WRITE((ldo->base + LDO_EN_CTL_REG), val);
Channagoud Kadabi0e60b7d2012-11-01 22:56:08 +0530444
445 return 0;
446}
Deepa Dinamani7564f2a2013-02-05 17:55:51 -0800447
Kuogee Hsieh11835112013-10-04 15:50:36 -0700448/*
449 * lpg channel register write:
450 */
451void pm8x41_lpg_write(uint8_t chan, uint8_t off, uint8_t val)
452{
453 uint32_t lpg_base = LPG_N_PERIPHERAL_BASE(chan);
454
455 REG_WRITE(lpg_base + off, val);
456}
457
Kuogee Hsieh383a5ae2014-09-02 16:31:39 -0700458/*
459 * pmi lpg channel register write with slave_id:
460 */
461void pm8x41_lpg_write_sid(uint8_t sid, uint8_t chan, uint8_t off, uint8_t val)
462{
463 uint32_t lpg_base = LPG_N_PERIPHERAL_BASE(chan);
464
465 lpg_base &= 0x0ffff; /* clear sid */
466 lpg_base |= (sid << 16); /* add sid */
467
468 dprintf(SPEW, "%s: lpg=%d base=%x\n", __func__, chan, lpg_base);
469
470 REG_WRITE(lpg_base + off, val);
471}
472
Deepa Dinamani7564f2a2013-02-05 17:55:51 -0800473uint8_t pm8x41_get_pmic_rev()
474{
475 return REG_READ(REVID_REVISION4);
476}
477
sundarajan srinivasand0f59e82013-02-12 19:17:02 -0800478uint8_t pm8x41_get_pon_reason()
479{
480 return REG_READ(PON_PON_REASON1);
481}
Deepa Dinamanic342f122013-06-12 15:41:31 -0700482
Matthew Qin5e90d832014-07-11 11:15:22 +0800483uint8_t pm8x41_get_pon_poff_reason1()
484{
485 return REG_READ(PON_POFF_REASON1);
486}
487
488uint8_t pm8x41_get_pon_poff_reason2()
489{
490 return REG_READ(PON_POFF_REASON2);
491}
492
Ajay Singh Parmar502ed712014-07-23 22:58:43 -0700493void pm8x41_enable_mvs(struct pm8x41_mvs *mvs, enum mvs_en_ctl enable)
494{
495 ASSERT(mvs);
496
497 REG_WRITE(mvs->base + MVS_EN_CTL, enable << MVS_EN_CTL_ENABLE_SHIFT);
498}
499
Deepa Dinamanic342f122013-06-12 15:41:31 -0700500void pm8x41_enable_mpp(struct pm8x41_mpp *mpp, enum mpp_en_ctl enable)
501{
502 ASSERT(mpp);
503
Aparna Mallavarapu083766b2014-07-21 21:04:48 +0530504 REG_WRITE(((mpp->base + MPP_EN_CTL) + (mpp_slave_id << 16)), enable << MPP_EN_CTL_ENABLE_SHIFT);
Deepa Dinamanic342f122013-06-12 15:41:31 -0700505}
506
507void pm8x41_config_output_mpp(struct pm8x41_mpp *mpp)
508{
509 ASSERT(mpp);
510
Aparna Mallavarapu083766b2014-07-21 21:04:48 +0530511 REG_WRITE(((mpp->base + MPP_DIG_VIN_CTL) + (mpp_slave_id << 16)), mpp->vin);
Deepa Dinamanic342f122013-06-12 15:41:31 -0700512
Aparna Mallavarapu083766b2014-07-21 21:04:48 +0530513 REG_WRITE(((mpp->base + MPP_MODE_CTL) + (mpp_slave_id << 16)), mpp->mode | (MPP_DIGITAL_OUTPUT << MPP_MODE_CTL_MODE_SHIFT));
Deepa Dinamanic342f122013-06-12 15:41:31 -0700514}
Ameya Thakurb0a62ab2013-06-25 13:43:10 -0700515
516uint8_t pm8x41_get_is_cold_boot()
517{
518 if (REG_READ(PON_WARMBOOT_STATUS1) || REG_READ(PON_WARMBOOT_STATUS2)) {
519 dprintf(INFO,"%s: Warm boot\n", __func__);
520 return 0;
521 }
522 dprintf(INFO,"%s: cold boot\n", __func__);
523 return 1;
524}
Amol Jadic3231ff2013-07-23 14:35:31 -0700525
Channagoud Kadabi7ec7a082014-02-04 15:47:13 -0800526/* api to control lnbb clock */
527void pm8x41_lnbb_clock_ctrl(uint8_t enable)
528{
529 uint8_t reg;
530
531 reg = REG_READ(LNBB_CLK_EN_CTL);
532
533 if (enable)
534 {
535 reg |= BIT(LNBB_CLK_EN_BIT);
536 }
537 else
538 {
539 reg &= ~BIT(LNBB_CLK_EN_BIT);
540 }
541
542 REG_WRITE(LNBB_CLK_EN_CTL, reg);
543}
544
Amol Jadic3231ff2013-07-23 14:35:31 -0700545/* api to control diff clock */
546void pm8x41_diff_clock_ctrl(uint8_t enable)
547{
548 uint8_t reg;
549
550 reg = REG_READ(DIFF_CLK1_EN_CTL);
551
552 if (enable)
553 {
554 reg |= BIT(DIFF_CLK1_EN_BIT);
555 }
556 else
557 {
558 reg &= ~BIT(DIFF_CLK1_EN_BIT);
559 }
560
561 REG_WRITE(DIFF_CLK1_EN_CTL, reg);
562}
Xiaocheng Li73c57122013-09-14 17:32:00 +0800563
564void pm8x41_clear_pmic_watchdog(void)
565{
566 pm8x41_reg_write(PMIC_WD_RESET_S2_CTL2, 0x0);
567}
Channagoud Kadabi1372b902013-10-28 16:20:51 -0700568
569/* API to check for borken battery */
570int pm8xxx_is_battery_broken()
571{
572 uint8_t trkl_default = 0;
573 uint8_t vbat_det_default = 0;
574 int batt_is_broken = 0;
575
576 /* Store original trickle charging current setting */
577 trkl_default = pm8x41_reg_read(PM8XXX_IBAT_ATC_A);
578 /* Store original VBAT_DET_LO setting */
579 vbat_det_default = pm8x41_reg_read(PM8XXX_VBAT_DET);
580
581 /*Set trickle charge current to 50mA (IBAT_ATC_A = 0x00) */
582 pm8x41_reg_write(PM8XXX_IBAT_ATC_A, 0x00);
583 /* Set VBAT_DET_LO to 4.3V so that VBAT_DET_HI = 4.52V (VBAT_DET_LO = 0x35) */
584 pm8x41_reg_write(PM8XXX_VBAT_DET, VBAT_DET_LO_4_30V);
585 /* Unlock SMBBP Secured Register */
586 pm8x41_reg_write(PM8XXX_SEC_ACCESS, SEC_ACCESS);
587 /* Disable VTRKL_FAULT comp (SMBBP_CHGR_COMP_OVR0 = 0x08) */
588 pm8x41_reg_write(PM8XXX_COMP_OVR0, OVR0_DIS_VTRKL_FAULT);
589 /* Disable VCP (SMBB_BAT_IF_VCP = 0x00) */
590 pm8x41_reg_write(PM8XXX_VCP, 0x00);
591 /* Unlock SMBBP Secured Register */
592 pm8x41_reg_write(PM8XXX_SEC_ACCESS, SEC_ACCESS);
593 /* Force trickle charging (SMBB_CHGR_TRKL_CHG_TEST = 0x01) */
594 pm8x41_reg_write(PM8XXX_TRKL_CHG_TEST, CHG_TRICKLE_FORCED_ON);
595 /* Wait for vbat to rise */
596 mdelay(12);
597
598 /* Check Above VBAT_DET_HIGH status */
599 if (pm8x41_reg_read(PM8XXX_VBAT_IN_TSTS) & VBAT_DET_HI_RT_STS)
600 batt_is_broken = 1;
601 else
602 batt_is_broken = 0;
603
604 /* Unlock SMBBP Secured Register */
605 pm8x41_reg_write(PM8XXX_SEC_ACCESS, SEC_ACCESS);
606
607 /* Disable force trickle charging */
608 pm8x41_reg_write(PM8XXX_TRKL_CHG_TEST, 0x00);
609 /* re-enable VCP */
610 pm8x41_reg_write(PM8XXX_VCP, VCP_ENABLE);
611 /* restore trickle charging default current */
612 pm8x41_reg_write(PM8XXX_IBAT_ATC_A, trkl_default);
613 /* restore VBAT_DET_LO setting to original value */
614 pm8x41_reg_write(PM8XXX_VBAT_DET, vbat_det_default);
615
616 return batt_is_broken;
617}