2018-07-13 01:31:50 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2016 Allwinner.
|
|
|
|
* wangwei <wangwei@allwinnertech.com>
|
|
|
|
*
|
|
|
|
* SUNXI AXP1506 Driver
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <common.h>
|
|
|
|
#include <power/sunxi/axp858_reg.h>
|
|
|
|
#include <power/sunxi/axp2585_reg.h>
|
|
|
|
#include <power/sunxi/axp.h>
|
|
|
|
#include <power/sunxi/pmu.h>
|
|
|
|
|
|
|
|
extern int axp2585_set_supply_status(int vol_name, int vol_value, int onoff);
|
|
|
|
extern int axp2585_set_supply_status_byname(char *vol_name, int vol_value, int onoff);
|
|
|
|
extern int axp2585_probe_supply_status(int vol_name, int vol_value, int onoff);
|
|
|
|
extern int axp2585_probe_supply_status_byname(char *vol_name);
|
|
|
|
extern int script_parser_fetch(char *main_name, char *sub_name, int value[], int count);
|
|
|
|
|
|
|
|
int axp2585_boost_set(void)
|
|
|
|
{
|
|
|
|
u8 value;
|
|
|
|
int pmu_boost_en;
|
|
|
|
int pmu_boost_cur_limit;
|
|
|
|
int pmu_boost_vol_limit;
|
|
|
|
int pmu_boost_vol_hold;
|
|
|
|
u8 tmp[3];
|
|
|
|
script_parser_fetch(PMU_SCRIPT_NAME, "pmu_boost_en", &pmu_boost_en, 1);
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_BOOST_EN, &value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (pmu_boost_en) {
|
|
|
|
value |= 0x80;
|
|
|
|
} else {
|
|
|
|
value &= 0x7f;
|
|
|
|
}
|
|
|
|
axp_i2c_write(AXP2585_ADDR, PMU_BOOST_EN, value);
|
|
|
|
script_parser_fetch(PMU_SCRIPT_NAME, "pmu_boost_cur_limit", &pmu_boost_cur_limit, 1);
|
|
|
|
if (pmu_boost_cur_limit <= 500) {
|
|
|
|
tmp[0] = 0x00;
|
|
|
|
} else if (pmu_boost_cur_limit <= 900) {
|
|
|
|
tmp[0] = 0x01;
|
|
|
|
} else if (pmu_boost_cur_limit <= 1500) {
|
|
|
|
tmp[0] = 0x02;
|
|
|
|
} else {
|
|
|
|
tmp[0] = 0x03;
|
|
|
|
}
|
|
|
|
script_parser_fetch(PMU_SCRIPT_NAME, "pmu_boost_vol_hold", &pmu_boost_vol_hold, 1);
|
|
|
|
if (pmu_boost_vol_hold <= 2400) {
|
|
|
|
tmp[1] = 0x00;
|
|
|
|
} else if (pmu_boost_vol_hold <= 2600) {
|
|
|
|
tmp[1] = 0x01;
|
|
|
|
} else if (pmu_boost_vol_hold <= 2800) {
|
|
|
|
tmp[1] = 0x02;
|
|
|
|
} else {
|
|
|
|
tmp[1] = 0x03;
|
|
|
|
}
|
|
|
|
script_parser_fetch(PMU_SCRIPT_NAME, "pmu_boost_vol_limit", &pmu_boost_vol_limit, 1);
|
|
|
|
if (pmu_boost_vol_limit <= 4500) {
|
|
|
|
tmp[2] = 0x0;
|
|
|
|
} else if (pmu_boost_vol_limit <= 5510) {
|
|
|
|
tmp[2] = (pmu_boost_vol_limit - 4500)/64;
|
|
|
|
} else {
|
|
|
|
tmp[2] = 0xf;
|
|
|
|
}
|
|
|
|
value = tmp[0] | (tmp[1]<<2) | (tmp[2]<<4);
|
|
|
|
axp_i2c_write(AXP2585_ADDR, PMU_BOOST_CTL, value);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
int axp2585_probe(void)
|
|
|
|
{
|
|
|
|
u8 pmu_type;
|
|
|
|
int pmu_on_ctl;
|
|
|
|
u8 value;
|
|
|
|
axp_i2c_config(SUNXI_AXP_2585, AXP2585_ADDR);
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_IC_TYPE, &pmu_type)) {
|
|
|
|
tick_printf("axp2585 read error\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
tick_printf("pmu_type = %x\n", pmu_type);
|
|
|
|
pmu_type &= 0xCF;
|
|
|
|
if (pmu_type == 0x46) {
|
|
|
|
/* pmu type AXP2585 */
|
|
|
|
tick_printf("BMU: AXP2585\n");
|
|
|
|
script_parser_fetch(PMU_SCRIPT_NAME, "pmu_on_ctl", &pmu_on_ctl, 1);
|
|
|
|
tick_printf("pmu_on_ctl:%x\n", pmu_on_ctl);
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PWR_ON_CTL, &value)) {
|
|
|
|
printf("axp2585 read error\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
value &= 0x0F;
|
|
|
|
value |= pmu_on_ctl << 4;
|
|
|
|
axp_i2c_write(AXP2585_ADDR, PWR_ON_CTL, value);
|
|
|
|
axp2585_boost_set();
|
2018-12-13 10:48:25 +00:00
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_BATFET_CTL, &value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
value &= 0x7f;
|
|
|
|
if (axp_i2c_write(AXP2585_ADDR, PMU_BATFET_CTL, value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
2018-07-13 01:31:50 +00:00
|
|
|
#if 0
|
|
|
|
axp_i2c_write(AXP2585_ADDR, PMU_REG_EXTENSION_EN, 0x06);
|
|
|
|
axp_i2c_write(AXP2585_ADDR, PMU_REG_LOCK, 0x04);
|
|
|
|
axp_i2c_write(AXP2585_ADDR, PMU_ADDR_EXTENSION, 0x01);
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, 0x03, &value)) {
|
|
|
|
printf("axp2585 read error\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
value &= 0xf7;
|
|
|
|
axp_i2c_write(AXP2585_ADDR, 0x03, value);
|
|
|
|
axp_i2c_write(AXP2585_ADDR, 0xff, 0x00);
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_set_coulombmeter_onoff(int onoff)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_set_charge_control(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_probe_battery_exist(void)
|
|
|
|
{
|
|
|
|
u8 reg_value;
|
|
|
|
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_BAT_STATUS, ®_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
//bit2 -- battery detect result
|
|
|
|
if ((reg_value & (1 << 3))) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_probe_battery_ratio(void)
|
|
|
|
{
|
|
|
|
u8 reg_value;
|
|
|
|
|
|
|
|
if(axp_i2c_read(AXP2585_ADDR, PMU_BAT_PERCENTAGE, ®_value))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//bit7-- 1:valid 0:invalid
|
|
|
|
if(reg_value&(1<<7))
|
|
|
|
{
|
|
|
|
reg_value = reg_value & 0x7f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
reg_value = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return reg_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_probe_power_status(void)
|
|
|
|
{
|
|
|
|
u8 reg_value;
|
|
|
|
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_CHG_STATUS, ®_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/*bit1: 0: vbus not power, 1: power good*/
|
|
|
|
if (reg_value & 0x2) {
|
|
|
|
return AXP_VBUS_EXIST;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_probe_battery_vol(void)
|
|
|
|
{
|
|
|
|
u8 reg_value_h = 0,reg_value_l = 0;
|
|
|
|
int tmp_value = 0;
|
|
|
|
int bat_vol;
|
|
|
|
|
|
|
|
if(axp_i2c_read(AXP2585_ADDR, PMU_BAT_VOL_H, ®_value_h))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if(axp_i2c_read(AXP2585_ADDR, PMU_BAT_VOL_L, ®_value_l))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp_value = (reg_value_h<<4) | reg_value_l;
|
|
|
|
bat_vol = tmp_value * 12/10;
|
|
|
|
|
|
|
|
return bat_vol;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_probe_key(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_probe_pre_sys_mode(void)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_set_next_sys_mode(int data)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_probe_this_poweron_cause(void)
|
|
|
|
{
|
|
|
|
uchar reg_value;
|
|
|
|
if (axp_i2c_read(AXP858_ADDR, PMU_DATA_BUFFER0, ®_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (reg_value == PMU_PRE_BOOT_MODE) {
|
|
|
|
axp_i2c_write(AXP858_ADDR, PMU_DATA_BUFFER0, PMU_PRE_SYS_MODE);
|
|
|
|
return AXP_POWER_ON_BY_POWER_KEY;
|
|
|
|
}
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_POWER_ON_STATUS, ®_value))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
tick_printf("poweron cause %x\n", reg_value);
|
|
|
|
/*bit7 : vbus, bit6: battery inster, bit5: battery charge to normal*/
|
|
|
|
if(reg_value&(1<<7))
|
|
|
|
{
|
|
|
|
reg_value &= 0x80;
|
|
|
|
axp_i2c_write(AXP2585_ADDR, PMU_POWER_ON_STATUS, reg_value);
|
|
|
|
return AXP_POWER_ON_BY_POWER_TRIGGER;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*need to check supply pmu*/
|
|
|
|
return AXP_POWER_ON_BY_POWER_KEY;
|
|
|
|
}
|
|
|
|
|
|
|
|
return reg_value & 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_set_power_off(void)
|
|
|
|
{
|
|
|
|
u8 reg_value;
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_POWER_ON_STATUS, ®_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
axp_i2c_write(AXP2585_ADDR, PMU_POWER_ON_STATUS, reg_value);
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_CHG_STATUS, ®_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (reg_value & 0x02) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_BATFET_CTL, ®_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
reg_value &= 0x7f;
|
|
|
|
if (axp_i2c_write(AXP2585_ADDR, PMU_BATFET_CTL, reg_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
tick_printf("before reg[10]:%x\n", reg_value);
|
|
|
|
mdelay(50);
|
|
|
|
reg_value |= 1 << 7;
|
|
|
|
if (axp_i2c_write(AXP2585_ADDR, PMU_BATFET_CTL, reg_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_set_power_onoff_vol(int set_vol, int stage)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int axp2585_set_charge_current(int current)
|
|
|
|
{
|
|
|
|
u8 reg_value;
|
|
|
|
u8 temp;
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_CHG_CUR_LIMIT, ®_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (current > 3072) {
|
|
|
|
temp = 0x3F;
|
|
|
|
} else {
|
|
|
|
temp = current / 64;
|
|
|
|
}
|
|
|
|
reg_value &= 0xB0;
|
|
|
|
reg_value |= temp;
|
|
|
|
tick_printf("Charge current:%d ma\n", current);
|
|
|
|
if (axp_i2c_write(AXP2585_ADDR, PMU_CHG_CUR_LIMIT, reg_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int axp2585_probe_charge_current(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int axp2585_set_vbus_cur_limit(int current)
|
|
|
|
{
|
|
|
|
u8 reg_value;
|
|
|
|
u8 temp;
|
|
|
|
if (axp_i2c_read(AXP2585_ADDR, PMU_BATFET_CTL, ®_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (current) {
|
|
|
|
if (current > 3250) {
|
|
|
|
temp = 0x3F;
|
|
|
|
} else if (current >= 100) {
|
|
|
|
temp = (current - 100)/50;
|
|
|
|
} else {
|
|
|
|
temp = 0x00;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*default was 2500ma*/
|
|
|
|
temp = 0x30;
|
|
|
|
}
|
|
|
|
reg_value &= 0xB0;
|
|
|
|
reg_value |= temp;
|
|
|
|
tick_printf("Input current:%d ma\n", current);
|
|
|
|
if (axp_i2c_write(AXP2585_ADDR, PMU_BATFET_CTL, reg_value)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_probe_vbus_cur_limit(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int axp2585_set_vbus_vol_limit(int vol)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int axp2585_probe_int_pending(uchar *addr)
|
|
|
|
{
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_probe_int_enable(uchar *addr)
|
|
|
|
{
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int axp2585_set_int_enable(uchar *addr)
|
|
|
|
{
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sunxi_axp_module_init("axp2585", SUNXI_AXP_2585);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|