| /* |
| * (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; |
| } |
| |