blob: e3671a3c5da3d02cee929473058cd1432cb6458d [file] [log] [blame]
/*
* (C) Copyright 2011
* Marvell Semiconductors Ltd. <www.marvell.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <i2c.h>
/* Base Page */
#define PM800_BASE_PAGE 0x30
#define PM800_CHIP_ID 0x00
#define PM800_WAKEUP1 0x0D
#define PM800_WAKEUP2 0x0E
/* Power Page */
#define PM800_POWER_PAGE 0x31
#define VBUCK_EN_REG 0x50
#define LDO_EN_REG1 0x51
#define LDO_EN_REG2 0x52
#define LDO_EN_REG3 0x53
#define LDO13_EN (1<<4)
#define LDO15_EN (1<<6)
#define LDO16_EN (1<<7)
#define LDO17_EN (1<<0)
#define VBUCK1_SET_REG 0x3C
#define VBUCK2_SET_REG 0x40
#define VBUCK3_SET_REG 0x41
#define VBUCK4_SET_REG 0x42
#define VBUCK5_SET_REG 0x43
#define LDO1_SET_REG 0x08
#define LDO2_SET_REG 0x0B
#define LDO3_SET_REG 0x0C
#define LDO4_SET_REG 0x0D
#define LDO5_SET_REG 0x0E
#define LDO6_SET_REG 0x0F
#define LDO7_SET_REG 0x10
#define LDO8_SET_REG 0x11
#define LDO9_SET_REG 0x12
#define LDO10_SET_REG 0x13
#define LDO11_SET_REG 0x14
#define LDO12_SET_REG 0x15
#define LDO13_SET_REG 0x16
#define LDO14_SET_REG 0x17
#define LDO15_SET_REG 0x18
#define LDO16_SET_REG 0x19
#define LDO17_SET_REG 0x1A
#define LDO18_SET_REG 0x1B
#define LDO19_SET_REG 0x1C
/* Procida Chip ID */
enum {
PM800_CHIP_A0 = 0x60,
PM800_CHIP_A1 = 0x61,
PM800_CHIP_B0 = 0x62,
PM800_CHIP_C0 = 0x63,
};
static inline int pm800_read_reg_power(u8 reg, u8 *val)
{
return i2c_read(PM800_POWER_PAGE, reg, 1, val, 1);
}
static inline int pm800_write_reg_power(u8 reg, u8 val)
{
return i2c_write(PM800_POWER_PAGE, reg, 1, &val, 1);
}
static inline int pm800_read_reg_base(u8 reg, u8 *val)
{
return i2c_read(PM800_BASE_PAGE, reg, 1, val, 1);
}
static inline int pm800_write_reg_base(u8 reg, u8 val)
{
return i2c_write(PM800_BASE_PAGE, reg, 1, &val, 1);
}
static int pm800_voltage_init(void)
{
int ret = 0;
u8 val;
/* enable buck2 (1.25v) for lpddr2 */
val = 0x34;
ret |= pm800_write_reg_power(VBUCK2_SET_REG, val);
/* enable buck5 (1.25v) for wukong */
val = 0x34;
ret |= pm800_write_reg_power(VBUCK5_SET_REG, val);
/* enable ldo17 */
ret |= pm800_read_reg_power(LDO_EN_REG3, &val);
val |= LDO17_EN;
ret |= pm800_write_reg_power(LDO_EN_REG3, val);
/* enable ldo16 (3.3v) for wifi */
val = 0xff;
ret |= pm800_write_reg_power(LDO16_SET_REG, val);
/* enable ldo13, ldo15, ldo16 */
ret |= pm800_read_reg_power(LDO_EN_REG2, &val);
val |= LDO13_EN | LDO15_EN | LDO16_EN;
ret |= pm800_write_reg_power(LDO_EN_REG2, val);
return ret;
}
static int pm800_disable_watch_dog(void)
{
int ret = 0;
/* Set WD_TIMER_COUNT to 0 */
ret |= pm800_write_reg_base(PM800_WAKEUP2, 0x0);
/* Reset watch dog timer */
ret |= pm800_write_reg_base(PM800_WAKEUP1, 0x10);
return ret;
}
int pmic_init(void)
{
int ret = 0;
unsigned int cur_bus = i2c_get_bus_num();
u8 val;
/* Set i2c bus */
i2c_set_bus_num(0);
ret |= pm800_read_reg_base(PM800_CHIP_ID, &val);
printf("Procida Chip ID: 0x%x\n", val);
/* Disable Watch Dog */
if (val < PM800_CHIP_C0)
ret |= pm800_disable_watch_dog();
/* Voltage init */
ret |= pm800_voltage_init();
/* Restore i2c bus num */
i2c_set_bus_num(cur_bus);
return ret;
}