blob: 02700e9ba67697445e8863d645f5e8943978d659 [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>
#define KBC_SLAVE_ADDR 0x15
#define MAX77601_SLAVE_ADDR 0x1c
#define MAX77601_VDVSSD0_REG 0x1B
#define MAX77601_CNFG1_L1_REG 0x25
#define MAX77601_CNFG1_L7_REG 0x31
#define MAX77601_CNFG_GPIO5 0x3B
#define MAX77601_AME_GPIO_REG 0x40
#define MAX77601_FPS_L1_REG 0x47
#define MAX77601_FPS_L7_REG 0x4D
#define MAX77601_FPSSRC_NOTFPS (0x3 << 6)
#define MAX77601_MODE_NORMAL (0x3 << 6)
#define MAX77601_L1_1P2V 0x10
#define MAX77601_L7_1P2V 0x08
#define MAX77601_VSD3_REG 0x19
#define MAX77601_SD0_1P25V 0x34
#define MAX77601_SD3_2P8V 0xB0
#define MAX77601_ONOFFCNFG2 0x42
#define MAX77601_ONOFFCNFG1 0x41
#define MAX77601_SFT_RST_WK 0x80
#define MAX77601_SFT_RST 0x80
#define MAX77601_RTCUPDATE0 0x04
#define MAX77601_RTCUPDATE1 0x05
#define MAX77601_RTCSECA2 0x15
#define MAX77601_UDF (1 << 0)
#define MAX77601_RBUDF (1 << 1)
#define MAX77601_RBUDR (1 << 4)
#define MAX77601_RTC_RETRY_LIMIT 10
void pmic_init(void)
{
u8 data, KBCdata;
unsigned int cur_bus = i2c_get_bus_num();
/* Set i2c bus */
i2c_set_bus_num(0);
//Clear KBC reboot command 0x44
//Purpose: In case hang in WTM, KBC will take care the reset action
KBCdata = 0x1;
i2c_write(KBC_SLAVE_ADDR ,0x45, 1, &KBCdata, 1);//Notify KBC to monitor 0x44
KBCdata = 0;
i2c_write(KBC_SLAVE_ADDR ,0x44, 1, &KBCdata, 1);//Clear 0x44 to let KBC know have success boot.
/* set ame for gpio 4/5/7 */
data = 0xb0;
i2c_write(MAX77601_SLAVE_ADDR, MAX77601_AME_GPIO_REG, 1, &data, 1);
/* Set GPIO5 active low, VCXO_EN is low when suspend */
i2c_read(MAX77601_SLAVE_ADDR, MAX77601_CNFG_GPIO5, 1, &data, 1);
data &= ~0x1;
i2c_write(MAX77601_SLAVE_ADDR, MAX77601_CNFG_GPIO5, 1, &data, 1);
/* Enable 1.2V pmic_1p2v_mipi (Max77601 LDO1) at first */
/* not configured as part of a flexible power sequence */
i2c_read(MAX77601_SLAVE_ADDR, MAX77601_FPS_L1_REG, 1, &data, 1);
data |= MAX77601_FPSSRC_NOTFPS;
i2c_write(MAX77601_SLAVE_ADDR, MAX77601_FPS_L1_REG, 1, &data, 1);
data = MAX77601_MODE_NORMAL | MAX77601_L1_1P2V;
i2c_write(MAX77601_SLAVE_ADDR, MAX77601_CNFG1_L1_REG, 1, &data, 1);
/* Then enable 1.2V pmic_1p2v_mipi_logic (Max77601 LDO7) */
i2c_read(MAX77601_SLAVE_ADDR, MAX77601_FPS_L7_REG, 1, &data, 1);
data |= MAX77601_FPSSRC_NOTFPS;
i2c_write(MAX77601_SLAVE_ADDR, MAX77601_FPS_L7_REG, 1, &data, 1);
data = MAX77601_MODE_NORMAL | MAX77601_L7_1P2V;
i2c_write(MAX77601_SLAVE_ADDR, MAX77601_CNFG1_L7_REG, 1, &data, 1);
/* Restore i2c bus num */
i2c_set_bus_num(cur_bus);
return;
}
void pmic_sdmmc_init(void)
{
u8 data;
unsigned int cur_bus = i2c_get_bus_num();
/* Set i2c bus */
i2c_set_bus_num(0);
data = MAX77601_SD3_2P8V;
i2c_write(MAX77601_SLAVE_ADDR, MAX77601_VSD3_REG, 1, &data, 1);
/* Restore i2c bus num */
i2c_set_bus_num(cur_bus);
return;
}
void pmic_reset_cpu(void)
{
u8 data, KBCdata;
i2c_set_bus_num(0);
//Set KBC reboot command 0x44
//Purpose: In case hang in WTM, KBC will take care the reset action without uboot clear 0x44
KBCdata = 0x1;
i2c_write(KBC_SLAVE_ADDR ,0x44, 1, &KBCdata, 1);
/* 1. Enable SW reset wake up */
i2c_read(MAX77601_SLAVE_ADDR, MAX77601_ONOFFCNFG2, 1, &data, 1);
data |= MAX77601_SFT_RST_WK;
i2c_write(MAX77601_SLAVE_ADDR, MAX77601_ONOFFCNFG2, 1, &data, 1);
/* 2. Issue SW reset */
i2c_read(MAX77601_SLAVE_ADDR, MAX77601_ONOFFCNFG1, 1, &data, 1);
data |= MAX77601_SFT_RST;
i2c_write(MAX77601_SLAVE_ADDR, MAX77601_ONOFFCNFG1, 1, &data, 1);
udelay(100*1000);
}
void write_recovery_reg(u8 val)
{
int retry = 0;
u8 tmp;
i2c_set_bus_num(0);
tmp = val;
i2c_write(0x48, MAX77601_RTCSECA2, 1, &tmp, 1);
tmp = MAX77601_UDF;
i2c_write(0x48, MAX77601_RTCUPDATE0, 1, &tmp, 1);
while (retry++ < MAX77601_RTC_RETRY_LIMIT) {
udelay(20000);
i2c_read(0x48, MAX77601_RTCUPDATE1, 1, &tmp, 1);
if (tmp & MAX77601_UDF)
break;
}
if (retry >= MAX77601_RTC_RETRY_LIMIT)
printf("error in writing max77601-rtc reg!\n");
}
int read_recovery_reg(void)
{
int retry = 0;
u8 tmp;
i2c_set_bus_num(0);
tmp = MAX77601_RBUDR;
i2c_write(0x48, MAX77601_RTCUPDATE0, 1, &tmp, 1);
while (retry++ < MAX77601_RTC_RETRY_LIMIT) {
udelay(20000);
i2c_read(0x48, MAX77601_RTCUPDATE1, 1, &tmp, 1);
if (tmp & MAX77601_RBUDF)
break;
}
if (retry >= MAX77601_RTC_RETRY_LIMIT)
{ printf("error in reading max77601-rtc reg!\n");
pmic_reset_cpu();
}
i2c_read(0x48, MAX77601_RTCSECA2, 1, &tmp, 1);
return tmp;
}