blob: dc6db38f2109fb2f5620fd9d167e99a38dcaf231 [file] [log] [blame]
Shashank Mittal402d0972010-09-29 10:09:52 -07001/*
Aparna Mallavarapu88713ed2013-01-07 20:21:37 +05302 * * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
Shashank Mittal402d0972010-09-29 10:09:52 -07003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
Aparna Mallavarapu88713ed2013-01-07 20:21:37 +053013 * * Neither the name of The Linux Foundation nor the names of its
Shashank Mittal402d0972010-09-29 10:09:52 -070014 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <debug.h>
31#include <reg.h>
Shashank Mittal6df16072011-07-14 18:44:01 -070032#include <bits.h>
Shashank Mittal402d0972010-09-29 10:09:52 -070033#include <platform/iomap.h>
34#include <platform/pmic.h>
35
Subbaraman Narayanamurthy78aa8fe2011-02-17 18:03:15 -080036#define TRUE 1
37#define FALSE 0
38
Shashank Mittal6df16072011-07-14 18:44:01 -070039/* FTS regulator PMR registers */
40#define SSBI_REG_ADDR_S1_PMR (0xA7)
41#define SSBI_REG_ADDR_S2_PMR (0xA8)
42#define SSBI_REG_ADDR_S3_PMR (0xA9)
43#define SSBI_REG_ADDR_S4_PMR (0xAA)
44
45#define REGULATOR_PMR_STATE_MASK 0x60
46#define REGULATOR_PMR_STATE_OFF 0x20
47
48/* Regulator control registers for shutdown/reset */
49#define SSBI_REG_ADDR_L22_CTRL 0x121
50
51/* SLEEP CNTL register */
52#define SSBI_REG_ADDR_SLEEP_CNTL 0x02B
53
54#define PM8058_SLEEP_SMPL_EN_MASK 0x04
55#define PM8058_SLEEP_SMPL_EN_RESET 0x04
56#define PM8058_SLEEP_SMPL_EN_PWR_OFF 0x00
57
58/* PON CNTL 1 register */
59#define SSBI_REG_ADDR_PON_CNTL_1 0x01C
60
61#define PM8058_PON_PUP_MASK 0xF0
62
63#define PM8058_PON_WD_EN_MASK 0x08
64#define PM8058_PON_WD_EN_RESET 0x08
65#define PM8058_PON_WD_EN_PWR_OFF 0x00
66
67#define PM8058_RTC_CTRL 0x1E8
68#define PM8058_RTC_ALARM_ENABLE BIT(1)
69
Subbaraman Narayanamurthy78aa8fe2011-02-17 18:03:15 -080070#define PM_IRQ_ID_TO_BLOCK_INDEX(id) (uint8_t)(id / 8)
71#define PM_IRQ_ID_TO_BIT_MASK(id) (uint8_t)(1 << (id % 8))
72
Channagoud Kadabie4884122011-09-21 23:54:44 +053073/* HDMI MPP Registers */
74#define SSBI_MPP_CNTRL_BASE 0x27
75#define SSBI_MPP_CNTRL(n) (SSBI_MPP_CNTRL_BASE + (n))
76
77#define PM8901_MPP_TYPE_MASK 0xE0
78#define PM8901_MPP_CONFIG_LVL_MASK 0x1C
79#define PM8901_MPP_CONFIG_CTL_MASK 0x03
80#define PM8901_MPP0_CTRL_VAL 0x30
81#define VREG_PMR_STATE_MASK 0x60
82#define VREG_PMR_STATE_HPM 0x7F
83#define VS_CTRL_USE_PMR 0xD0
84#define VS_CTRL_ENABLE_MASK 0xD0
85#define LDO_CTRL_VPROG_MASK 0x1F
86#define REGULATOR_EN_MASK 0x80
87#define PM8901_HDMI_MVS_CTRL 0x058
88#define PM8901_HDMI_MVS_PMR 0x0B8
89#define PM8058_HDMI_L16_CTRL 0x08A
90
Shashank Mittal402d0972010-09-29 10:09:52 -070091typedef int (*pm8058_write_func) (unsigned char *, unsigned short,
Ajay Dudanib01e5062011-12-03 23:23:42 -080092 unsigned short);
Shashank Mittal402d0972010-09-29 10:09:52 -070093extern int pa1_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
Ajay Dudanib01e5062011-12-03 23:23:42 -080094 unsigned short slave_addr);
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -070095extern int pa1_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
Ajay Dudanib01e5062011-12-03 23:23:42 -080096 unsigned short slave_addr);
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -070097extern int pa2_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
Ajay Dudanib01e5062011-12-03 23:23:42 -080098 unsigned short slave_addr);
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -070099extern int pa2_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800100 unsigned short slave_addr);
Shashank Mittal402d0972010-09-29 10:09:52 -0700101
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700102/* PM8058 APIs */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800103int pm8058_write(uint16_t addr, uint8_t * data, uint16_t length)
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700104{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800105 return pa1_ssbi2_write_bytes(data, length, addr);
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700106}
107
Ajay Dudanib01e5062011-12-03 23:23:42 -0800108int pm8058_read(uint16_t addr, uint8_t * data, uint16_t length)
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700109{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800110 return pa1_ssbi2_read_bytes(data, length, addr);
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700111}
112
Shashank Mittal402d0972010-09-29 10:09:52 -0700113void pm8058_write_one(unsigned data, unsigned address)
114{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800115 pm8058_write_func wr_function = &pa1_ssbi2_write_bytes;
116 if (wr_function == NULL)
117 return;
118 if ((*wr_function) (&data, 1, address))
119 dprintf(CRITICAL, "Error in initializing register\n");
Shashank Mittal402d0972010-09-29 10:09:52 -0700120
121}
122
Ajay Dudanib01e5062011-12-03 23:23:42 -0800123int pm8058_get_irq_status(pm_irq_id_type irq, bool * rt_status)
Subbaraman Narayanamurthy78aa8fe2011-02-17 18:03:15 -0800124{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800125 unsigned block_index, reg_data, reg_mask;
126 int errFlag;
Subbaraman Narayanamurthy78aa8fe2011-02-17 18:03:15 -0800127
Ajay Dudanib01e5062011-12-03 23:23:42 -0800128 block_index = PM_IRQ_ID_TO_BLOCK_INDEX(irq);
Subbaraman Narayanamurthy78aa8fe2011-02-17 18:03:15 -0800129
Ajay Dudanib01e5062011-12-03 23:23:42 -0800130 /* select the irq block */
131 errFlag =
132 pa1_ssbi2_write_bytes(&block_index, 1, IRQ_BLOCK_SEL_USR_ADDR);
133 if (errFlag) {
134 dprintf(INFO, "Device Timeout");
135 return 1;
136 }
Subbaraman Narayanamurthy78aa8fe2011-02-17 18:03:15 -0800137
Ajay Dudanib01e5062011-12-03 23:23:42 -0800138 /* read real time status */
139 errFlag = pa1_ssbi2_read_bytes(&reg_data, 1, IRQ_STATUS_RT_USR_ADDR);
140 if (errFlag) {
141 dprintf(INFO, "Device Timeout");
142 return 1;
143 }
144 reg_mask = PM_IRQ_ID_TO_BIT_MASK(irq);
Subbaraman Narayanamurthy78aa8fe2011-02-17 18:03:15 -0800145
Ajay Dudanib01e5062011-12-03 23:23:42 -0800146 if ((reg_data & reg_mask) == reg_mask) {
147 /* The RT Status is high. */
148 *rt_status = TRUE;
149 } else {
150 /* The RT Status is low. */
151 *rt_status = FALSE;
152 }
153 return 0;
Subbaraman Narayanamurthy78aa8fe2011-02-17 18:03:15 -0800154}
155
Subbaraman Narayanamurthy8f0b0452011-03-11 18:30:10 -0800156bool pm8058_gpio_get(unsigned int gpio)
157{
Subbaraman Narayanamurthyaea23b72011-04-12 13:07:41 -0700158 pm_irq_id_type gpio_irq;
Subbaraman Narayanamurthy8f0b0452011-03-11 18:30:10 -0800159 bool status;
160 int ret;
161
162 gpio_irq = gpio + PM_GPIO01_CHGED_ST_IRQ_ID;
Subbaraman Narayanamurthyaea23b72011-04-12 13:07:41 -0700163 ret = pm8058_get_irq_status(gpio_irq, &status);
Subbaraman Narayanamurthy8f0b0452011-03-11 18:30:10 -0800164
Ajay Dudanib01e5062011-12-03 23:23:42 -0800165 if (ret)
166 dprintf(CRITICAL, "pm8058_gpio_get failed\n");
Subbaraman Narayanamurthy8f0b0452011-03-11 18:30:10 -0800167
168 return status;
169}
170
Ajay Dudanib01e5062011-12-03 23:23:42 -0800171int pm8058_mwrite(uint16_t addr, uint8_t val, uint8_t mask, uint8_t * reg_save)
Subbaraman Narayanamurthy8c7cd222011-06-16 18:24:28 -0700172{
173 int rc = 0;
174 uint8_t reg;
175
176 reg = (*reg_save & ~mask) | (val & mask);
177 if (reg != *reg_save)
178 rc = pm8058_write(addr, &reg, 1);
179 if (rc)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800180 dprintf(CRITICAL, "pm8058_write failed; addr=%03X, rc=%d\n",
181 addr, rc);
Subbaraman Narayanamurthy8c7cd222011-06-16 18:24:28 -0700182 else
183 *reg_save = reg;
184 return rc;
185}
186
Channagoud Kadabie4884122011-09-21 23:54:44 +0530187int pm8058_ldo_set_voltage()
188{
189 int ret = 0;
190 unsigned vprog = 0x00000110;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800191 ret =
192 pm8058_mwrite(PM8058_HDMI_L16_CTRL, vprog, LDO_CTRL_VPROG_MASK, 0);
193 if (ret) {
194 dprintf(SPEW, "Failed to set voltage for l16 regulator\n");
Channagoud Kadabie4884122011-09-21 23:54:44 +0530195 }
196 return ret;
197}
198
199int pm8058_vreg_enable()
200{
201 int ret = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800202 ret =
203 pm8058_mwrite(PM8058_HDMI_L16_CTRL, REGULATOR_EN_MASK,
204 REGULATOR_EN_MASK, 0);
205 if (ret) {
206 dprintf(SPEW, "Vreg enable failed for PM 8058\n");
Channagoud Kadabie4884122011-09-21 23:54:44 +0530207 }
208 return ret;
209}
210
Subbaraman Narayanamurthy8f1ffa52011-06-03 12:33:01 -0700211/* PM8901 APIs */
212
Shashank Mittal402d0972010-09-29 10:09:52 -0700213/*
214 * Write to the control registers on PMIC via the SSBI2 interface.
215 * Returns : (0) on success and (-1) on error.
216 */
217int pm8901_write(uint8_t * buffer, uint32_t length, uint32_t slave_addr)
218{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800219 return pa2_ssbi2_write_bytes(buffer, length, slave_addr);
Shashank Mittal402d0972010-09-29 10:09:52 -0700220}
221
222/*
223 * Read from the control registers on PMIC via the SSBI2 interface.
224 * Returns : (0) on success and (-1) on error.
225 */
226int pm8901_read(uint8_t * buffer, uint32_t length, uint32_t slave_addr)
227{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800228 return pa2_ssbi2_read_bytes(buffer, length, slave_addr);
Shashank Mittal402d0972010-09-29 10:09:52 -0700229}
230
231/*
232 * PMIC 8901 LDO vreg read.
233 */
234int pm8901_test_bank_read(uint8_t * buffer, uint8_t bank, uint16_t addr)
235{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800236 int ret = pm8901_write(&bank, 1, addr);
237 /* if the write does not work we can't read. */
238 if (ret) {
239 return ret;
240 }
Shashank Mittal402d0972010-09-29 10:09:52 -0700241
Ajay Dudanib01e5062011-12-03 23:23:42 -0800242 return pm8901_read(buffer, 1, addr);
Shashank Mittal402d0972010-09-29 10:09:52 -0700243}
244
245/*
246 * PMIC 8901 LDO vreg write.
247 */
248int pm8901_vreg_write(uint8_t * buffer, uint8_t mask, uint16_t addr,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800249 uint8_t prev_val)
Shashank Mittal402d0972010-09-29 10:09:52 -0700250{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800251 uint8_t reg;
Shashank Mittal402d0972010-09-29 10:09:52 -0700252
Ajay Dudanib01e5062011-12-03 23:23:42 -0800253 /* Clear the bits we want to try and set. */
254 reg = (prev_val & ~mask);
255 /* Set the bits we want to set, before writing them to addr */
256 reg |= (*buffer & mask);
257 return pm8901_write(&reg, 1, addr);
Shashank Mittal402d0972010-09-29 10:09:52 -0700258}
Shashank Mittal6df16072011-07-14 18:44:01 -0700259
260int pm8901_reset_pwr_off(int reset)
261{
262 int rc = 0, i;
263 uint8_t pmr;
264 uint8_t pmr_addr[4] = {
265 SSBI_REG_ADDR_S2_PMR,
266 SSBI_REG_ADDR_S3_PMR,
267 SSBI_REG_ADDR_S4_PMR,
268 SSBI_REG_ADDR_S1_PMR,
269 };
270
271 /* Turn off regulators S1, S2, S3, S4 when shutting down. */
272 if (!reset) {
273 for (i = 0; i < 4; i++) {
274 rc = pm8901_read(&pmr, 1, pmr_addr[i]);
275 if (rc) {
276 goto get_out;
277 }
278
279 pmr &= ~REGULATOR_PMR_STATE_MASK;
280 pmr |= REGULATOR_PMR_STATE_OFF;
281
282 rc = pm8901_write(&pmr, 1, pmr_addr[i]);
283 if (rc) {
284 goto get_out;
285 }
286 }
287 }
288
Ajay Dudanib01e5062011-12-03 23:23:42 -0800289 get_out:
Shashank Mittal6df16072011-07-14 18:44:01 -0700290 return rc;
291}
292
Aparna Mallavarapu88713ed2013-01-07 20:21:37 +0530293int pm8901_ldo_disable(int ldo_id)
294{
295 int rc = -1;
296 uint8_t prev_val = 0x0, val = 0x3F, mask = 0x7F;
297
298 if(ldo_id >= LDO_START && ldo_id <= LDO_END) {
299 rc = pm8901_read(&prev_val, 1, PM8901_PMR_REG(ldo_id));
300 if (rc)
301 goto get_out;
302
303 rc = pm8901_vreg_write(&val, mask, PM8901_PMR_REG(ldo_id), prev_val);
304 if (rc)
305 goto get_out;
306 }
307get_out:
308 return rc;
309}
310
Shashank Mittal6df16072011-07-14 18:44:01 -0700311int pm8058_reset_pwr_off(int reset)
312{
313 int rc;
314 uint8_t pon, ctrl, smpl;
315
316 /* Set regulator L22 to 1.225V in high power mode. */
317 rc = pm8058_read(SSBI_REG_ADDR_L22_CTRL, &ctrl, 1);
318 if (rc) {
319 goto get_out3;
320 }
321 /* Leave pull-down state intact. */
322 ctrl &= 0x40;
323 ctrl |= 0x93;
324
325 rc = pm8058_write(SSBI_REG_ADDR_L22_CTRL, &ctrl, 1);
326 if (rc) {
327 }
328
Ajay Dudanib01e5062011-12-03 23:23:42 -0800329 get_out3:
Shashank Mittal6df16072011-07-14 18:44:01 -0700330 if (!reset) {
331 /* Only modify the SLEEP_CNTL reg if shutdown is desired. */
332 rc = pm8058_read(SSBI_REG_ADDR_SLEEP_CNTL, &smpl, 1);
333 if (rc) {
334 goto get_out2;
335 }
336
337 smpl &= ~PM8058_SLEEP_SMPL_EN_MASK;
338 smpl |= PM8058_SLEEP_SMPL_EN_PWR_OFF;
339
340 rc = pm8058_write(SSBI_REG_ADDR_SLEEP_CNTL, &smpl, 1);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800341 if (rc) {
Shashank Mittal6df16072011-07-14 18:44:01 -0700342 }
343 }
344
Ajay Dudanib01e5062011-12-03 23:23:42 -0800345 get_out2:
Shashank Mittal6df16072011-07-14 18:44:01 -0700346 rc = pm8058_read(SSBI_REG_ADDR_PON_CNTL_1, &pon, 1);
347 if (rc) {
348 goto get_out;
349 }
350
351 pon &= ~PM8058_PON_WD_EN_MASK;
352 pon |= reset ? PM8058_PON_WD_EN_RESET : PM8058_PON_WD_EN_PWR_OFF;
353
354 /* Enable all pullups */
355 pon |= PM8058_PON_PUP_MASK;
356
357 rc = pm8058_write(SSBI_REG_ADDR_PON_CNTL_1, &pon, 1);
358 if (rc) {
359 goto get_out;
360 }
361
Ajay Dudanib01e5062011-12-03 23:23:42 -0800362 get_out:
Shashank Mittal6df16072011-07-14 18:44:01 -0700363 return rc;
364}
365
366int pm8058_rtc0_alarm_irq_disable(void)
367{
368 int rc;
369 uint8_t reg;
370
371 rc = pm8058_read(PM8058_RTC_CTRL, &reg, 1);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800372 if (rc) {
Shashank Mittal6df16072011-07-14 18:44:01 -0700373 return rc;
374 }
375 reg = (reg & ~PM8058_RTC_ALARM_ENABLE);
376
377 rc = pm8058_write(PM8058_RTC_CTRL, &reg, 1);
378 if (rc) {
379 return rc;
380 }
381
382 return rc;
383}
384
Channagoud Kadabie4884122011-09-21 23:54:44 +0530385int pm8901_mpp_enable()
386{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800387 uint8_t prevval = 0x0;
Channagoud Kadabie4884122011-09-21 23:54:44 +0530388 uint16_t mask;
389 uint8_t conf;
390 int ret = 0;
391
392 conf = PM8901_MPP0_CTRL_VAL;
393 mask = PM8901_MPP_TYPE_MASK | PM8901_MPP_CONFIG_LVL_MASK |
Ajay Dudanib01e5062011-12-03 23:23:42 -0800394 PM8901_MPP_CONFIG_CTL_MASK;
Channagoud Kadabie4884122011-09-21 23:54:44 +0530395
Ajay Dudanib01e5062011-12-03 23:23:42 -0800396 if (ret = pm8901_vreg_write(&conf, mask, SSBI_MPP_CNTRL(0), prevval)) {
397 dprintf(SPEW, "PM8901 MPP failed\n");
Channagoud Kadabie4884122011-09-21 23:54:44 +0530398 }
399 return ret;
400}
401
402int pm8901_vs_enable()
403{
404 uint8_t val = VREG_PMR_STATE_HPM;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800405 int prevval = 0x0;
Channagoud Kadabie4884122011-09-21 23:54:44 +0530406 int ret = 0;
407
Ajay Dudanib01e5062011-12-03 23:23:42 -0800408 if (ret =
409 pm8901_vreg_write(&val, VREG_PMR_STATE_HPM, PM8901_HDMI_MVS_PMR,
410 prevval)) {
411 dprintf(SPEW,
412 "pm8901_vreg_write failed for MVS PMR register\n");
Channagoud Kadabie4884122011-09-21 23:54:44 +0530413 return ret;
414 }
415
416 val = VS_CTRL_USE_PMR;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800417 if (ret =
418 pm8901_vreg_write(&val, VS_CTRL_ENABLE_MASK, PM8901_HDMI_MVS_CTRL,
419 prevval)) {
420 dprintf(SPEW,
421 "pm8901_vreg_write failed for MVS ctrl register\n");
Channagoud Kadabie4884122011-09-21 23:54:44 +0530422 return ret;
423 }
424 return ret;
425}