876 lines
20 KiB
C
876 lines
20 KiB
C
/*
|
|
* (C) Copyright 2020
|
|
* reMarkable AS - http://www.remarkable.com
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
* Author: Steinar Bakkemo <steinar.bakkemo@remarkable.com>
|
|
*/
|
|
|
|
#include "max77818_charger.h"
|
|
#include "max77818.h"
|
|
#include "max77818_battery.h"
|
|
|
|
#include <asm/arch/sys_proto.h>
|
|
#include <asm/arch/mx7-pins.h>
|
|
#include <asm/gpio.h>
|
|
#include <asm/mach-imx/iomux-v3.h>
|
|
#include <dm/uclass.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/types.h>
|
|
#include <i2c.h>
|
|
|
|
#define MAX77818_REG_DETAILS_0 0xB3
|
|
#define MAX77818_DETAILS_0__BAT_DET_MASK 0x01
|
|
#define MAX77818_DETAILS_0__BAT_DET_SHIFT 0x00
|
|
#define MAX77818_DETAILS_0__BAT_PRESENT 0x00
|
|
#define MAX77818_DETAILS_0__BAT_NOT_PRESENT 0x01
|
|
#define MAX77818_DETAILS_0__WCIN_DETAILS_MASK 0x18
|
|
#define MAX77818_DETAILS_0__WCIN_DETAILS_SHIFT 0x03
|
|
#define MAX77818_DETAILS_0__INV_WCIN_BELOW_WCINUVLO 0x00
|
|
#define MAX77818_DETAILS_0__INV_WCIN_ABOVE_WCINUVLO 0x01
|
|
#define MAX77818_DETAILS_0__INV_WCIN_ABOVE_WCINOVLO 0x02
|
|
#define MAX77818_DETAILS_0__OK_WCIN_BELOW_WCINOVLO 0x03
|
|
#define MAX77818_DETAILS_0__CHGIN_DETAILS_MASK 0x60
|
|
#define MAX77818_DETAILS_0__CHGIN_DETAILS_SHIFT 0x05
|
|
#define MAX77818_DETAILS_0__INV_CHGIN_BELOW_CHGINUVLO 0x00
|
|
#define MAX77818_DETAILS_0__INV_CHGIN_ABOVE_CHGINUVLO 0x01
|
|
#define MAX77818_DETAILS_0__INV_CHGIN_ABOVE_CHGINOVLO 0x02
|
|
#define MAX77818_DETAILS_0__OK_CHGIN_BELOW_CHGINOVLO 0x03
|
|
|
|
#define MAX77818_REG_DETAILS_1 0xB4
|
|
|
|
#define MAX77818_REG_DETAILS_2 0xB5
|
|
|
|
#define MAX77818_REG_CHGPROT 0xBD
|
|
#define MAX77818_CHGPROT__MASK 0x0C
|
|
#define MAX77818_CHGPROT__UNLOCK 0x0C
|
|
#define MAX77818_CHGPROT__LOCK 0x00
|
|
|
|
#define MAX77818_REG_CHG_CNFG_0 0xB7
|
|
#define MAX77818_CHG_CNFG_0__MODE__MASK 0x0F
|
|
#define MAX77818_CHG_CNFG_0__MODE__OTG_BOOST_BUCK_ON 0x0E
|
|
#define MAX77818_CHG_CNFG_0__MODE__CHARGER_BUCK_O 0x05
|
|
|
|
#define MAX77818_REG_CHG_CNFG_02 0xB9
|
|
#define MAX77818_CHG_CNFG_02__CHARGE_CC__MASK 0x3F
|
|
#define MAX77818_CHG_CNFG_02__CHARGE_CC__FAST_CHARGE_1P5_A 0x1E
|
|
#define MAX77818_CHG_CNFG_02__CHARGE_CC__FAST_CHARGE_2P8_A 0x38
|
|
|
|
#define MAX77818_REG_CHG_CNFG_04 0xBB
|
|
#define MAX77818_CHG_CNFG_04__CHG_CV_PRM__MASK 0x3F
|
|
#define MAX77818_CHG_CNFG_04__CHG_CV_PRM__4V3 0x1A
|
|
#define MAX77818_CHG_CNFG_04__MINVSYS__MASK 0xC0
|
|
#define MAX77818_CHG_CNFG_04__MINVSYS__3P4V_VSYS_MIN 0x00
|
|
|
|
#define MAX77818_REG_CHG_CNFG_09 0xC0
|
|
#define MAX77818_CHG_CNFG_09__CHGIN_ILIM__MASK 0x7f
|
|
#define MAX77818_CHG_CNFG_09__CHGIN_ILIM_500_MA 0x0f
|
|
#define MAX77818_CHG_CNFG_09__CHGIN_ILIM_1P5_A 0x2D
|
|
#define MAX77818_CHG_CNFG_09__CHGIN_ILIM_2P8_A 0x54
|
|
|
|
#define MAX77818_REG_CHG_CNFG_10 0xC1
|
|
#define MAX77818_CHG_CNFG_10__WCIN_ILIM_500_MA 0x19
|
|
#define MAX77818_CHG_CNFG_10__WCIN_ILIM__MASK 0x3F
|
|
#define MAX77818_CHG_CNFG_10__WCIN_ILIM__1P26_A 0x3F
|
|
|
|
static struct udevice *chDev = NULL;
|
|
|
|
static int max77818_init_charger_device(bool leave_fgcc_disabled, bool *restore_state)
|
|
{
|
|
int ret;
|
|
bool fgcc_restore_state;
|
|
|
|
struct udevice *bus = max77818_get_bus();
|
|
if (!bus) {
|
|
ret = max77818_init_i2c_bus();
|
|
if (ret) {
|
|
printf("%s: Unable to complete charger device initialization",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/* Turn off FGCC in order to do required charger config, if enabled */
|
|
printf("Disabling FGCC mode in order to do minimal charger config\n");
|
|
ret = max77818_set_fgcc_state(false, &fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to disable FGCC mode: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
|
|
/* Slight delay to let the charger device get back online */
|
|
mdelay(100);
|
|
|
|
ret = dm_i2c_probe(bus, MAX77818_CHARGER_I2C_ADDR, 0, &chDev);
|
|
if (ret) {
|
|
printf("%s: Can't find device id=0x%x, on bus %d\n",
|
|
__func__, MAX77818_CHARGER_I2C_ADDR, MAX77818_I2C_BUS);
|
|
return -ENODEV;
|
|
}
|
|
|
|
if (!leave_fgcc_disabled) {
|
|
ret = max77818_restore_fgcc(fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to restore FGCC mode: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
*restore_state = fgcc_restore_state;
|
|
return 0;
|
|
}
|
|
|
|
static int max77818_set_reg_lock(struct udevice *dev, bool locked)
|
|
{
|
|
u8 regVal;
|
|
|
|
regVal = (locked ? MAX77818_CHGPROT__LOCK : MAX77818_CHGPROT__UNLOCK);
|
|
return max77818_i2c_reg_write8(dev,
|
|
MAX77818_REG_CHGPROT,
|
|
MAX77818_CHGPROT__MASK, regVal);
|
|
}
|
|
|
|
static int max77818_get_details_1(struct udevice *dev)
|
|
{
|
|
u8 regVal;
|
|
int ret;
|
|
|
|
ret = dm_i2c_read(dev, MAX77818_REG_DETAILS_1, ®Val, 1);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
|
|
printf("Read DETAILS_1: 0x%02X\n", regVal);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int max77818_get_details_2(struct udevice *dev)
|
|
{
|
|
u8 regVal;
|
|
int ret;
|
|
|
|
ret = dm_i2c_read(dev, MAX77818_REG_DETAILS_2, ®Val, 1);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
|
|
printf("Read DETAILS_2: 0x%02X\n", regVal);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int max77818_get_battery_status(struct udevice *dev)
|
|
{
|
|
u8 regVal;
|
|
int ret;
|
|
|
|
ret = dm_i2c_read(dev, MAX77818_REG_DETAILS_0, ®Val, 1);
|
|
if (ret) {
|
|
printf("Failed to read DETAIL_0 register !\n");
|
|
return ret;
|
|
}
|
|
|
|
regVal &= MAX77818_DETAILS_0__BAT_DET_MASK;
|
|
regVal >>= MAX77818_DETAILS_0__BAT_DET_SHIFT;
|
|
|
|
switch(regVal) {
|
|
case MAX77818_DETAILS_0__BAT_PRESENT:
|
|
printf("Battery is present\n");
|
|
break;
|
|
case MAX77818_DETAILS_0__BAT_NOT_PRESENT:
|
|
printf("Battery is NOT present\n");
|
|
break;
|
|
default:
|
|
printf("Unknown battery detection state: 0x%02X\n", regVal);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int max77818_get_wcin_details(struct udevice *dev)
|
|
{
|
|
u8 regVal;
|
|
int ret;
|
|
|
|
ret = dm_i2c_read(dev, MAX77818_REG_DETAILS_0, ®Val, 1);
|
|
if (ret) {
|
|
printf("Failed to read DETAIL_0 register !\n");
|
|
return ret;
|
|
}
|
|
|
|
regVal &= MAX77818_DETAILS_0__WCIN_DETAILS_MASK;
|
|
regVal >>= MAX77818_DETAILS_0__WCIN_DETAILS_SHIFT;
|
|
|
|
switch(regVal) {
|
|
case MAX77818_DETAILS_0__INV_WCIN_BELOW_WCINUVLO:
|
|
printf("INVALID VWCIN:\nWCIN < VWCIN_UVLO\n");
|
|
break;
|
|
|
|
case MAX77818_DETAILS_0__INV_WCIN_ABOVE_WCINUVLO:
|
|
printf("INVALID VWCIN: VWCIN < VMBAT + VWCIN2SYS and "
|
|
"VWCIN > VWCIN_UVLO\n");
|
|
break;
|
|
|
|
case MAX77818_DETAILS_0__INV_WCIN_ABOVE_WCINOVLO:
|
|
printf("INVALID VWCIN:\nVWCIN is invalid. VWCIN>VWCIN_OVLO\n");
|
|
break;
|
|
|
|
case MAX77818_DETAILS_0__OK_WCIN_BELOW_WCINOVLO:
|
|
printf("VWCIN OK:\n"
|
|
"VWCIN > VWCIN_UVLO, VWCIN > VMBAT + VWCIN2SYS, "
|
|
"VWCIN < VWCIN_OVLO\n");
|
|
break;
|
|
|
|
default:
|
|
printf("Unknown winc status: 0x%02X\n", regVal);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int max77818_get_chgin_details(struct udevice *dev)
|
|
{
|
|
u8 regVal;
|
|
int ret;
|
|
|
|
ret = dm_i2c_read(dev, MAX77818_REG_DETAILS_0, ®Val, 1);
|
|
if (ret) {
|
|
printf("Failed to read DETAIL_0 register !\n");
|
|
return ret;
|
|
}
|
|
|
|
regVal &= (u8)MAX77818_DETAILS_0__CHGIN_DETAILS_MASK;
|
|
printf("CHING DETAIL VALUE: 0x%02X\n", regVal);
|
|
|
|
regVal = regVal >> (u8)MAX77818_DETAILS_0__CHGIN_DETAILS_SHIFT;
|
|
printf("CHING DETAIL VALUE: 0x%02X\n", regVal);
|
|
switch(regVal) {
|
|
case MAX77818_DETAILS_0__INV_CHGIN_BELOW_CHGINUVLO:
|
|
printf("INVALID VBUS:\nCHGIN < VCHGIN_UVLO\n");
|
|
break;
|
|
|
|
case MAX77818_DETAILS_0__INV_CHGIN_ABOVE_CHGINUVLO:
|
|
printf("INVALID VBUS: VCHGIN < VMBAT + VCHGIN2SYS and "
|
|
"VCHGIN > VCHGIN_UVLO");
|
|
break;
|
|
|
|
case MAX77818_DETAILS_0__INV_CHGIN_ABOVE_CHGINOVLO:
|
|
printf("INVALID VBUS:\n"
|
|
"VCHGIN is invalid. "
|
|
"VCHGIN>VCHGIN_OVLO\n");
|
|
break;
|
|
|
|
case MAX77818_DETAILS_0__OK_CHGIN_BELOW_CHGINOVLO:
|
|
printf("VBUS OK:\n"
|
|
"VCHGIN > VCHGIN_UVLO, VCHGIN > VMBAT + VCHGIN2SYS, "
|
|
"VCHGIN < VCHGIN_OVLO\n");
|
|
break;
|
|
|
|
default:
|
|
printf("Unknown winc status: 0x%02X\n", regVal);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int max77818_set_otg_pwr(struct udevice *dev, bool otg_on)
|
|
{
|
|
u8 regVal;
|
|
|
|
dev = (dev ? dev : chDev);
|
|
if (!dev)
|
|
return -1;
|
|
|
|
regVal = (otg_on ?
|
|
MAX77818_CHG_CNFG_0__MODE__OTG_BOOST_BUCK_ON :
|
|
MAX77818_CHG_CNFG_0__MODE__CHARGER_BUCK_O);
|
|
|
|
return max77818_i2c_reg_write8(dev, MAX77818_REG_CHG_CNFG_0,
|
|
MAX77818_CHG_CNFG_0__MODE__MASK, regVal);
|
|
}
|
|
|
|
int max77818_set_fast_charge_current(struct udevice *dev,
|
|
enum fast_charge_current fsc)
|
|
{
|
|
int ret;
|
|
uint fc_config_value;
|
|
|
|
dev = (dev ? dev : chDev);
|
|
if (!dev)
|
|
return -1;
|
|
|
|
ret = max77818_set_reg_lock(dev, false);
|
|
if (ret)
|
|
return ret;
|
|
|
|
switch(fsc) {
|
|
case FASTCHARGE_1P5_A:
|
|
fc_config_value =
|
|
MAX77818_CHG_CNFG_02__CHARGE_CC__FAST_CHARGE_1P5_A;
|
|
break;
|
|
case FASTCHARGE_2P8_A:
|
|
fc_config_value =
|
|
MAX77818_CHG_CNFG_02__CHARGE_CC__FAST_CHARGE_2P8_A;
|
|
break;
|
|
default:
|
|
/* Invalid value, just set default 1.5A */
|
|
fc_config_value =
|
|
MAX77818_CHG_CNFG_02__CHARGE_CC__FAST_CHARGE_1P5_A;
|
|
}
|
|
|
|
ret = max77818_i2c_reg_write8(dev,
|
|
MAX77818_REG_CHG_CNFG_02,
|
|
MAX77818_CHG_CNFG_02__CHARGE_CC__MASK,
|
|
fc_config_value);
|
|
if (ret)
|
|
return ret;
|
|
|
|
return max77818_set_reg_lock(dev, true);
|
|
}
|
|
|
|
int max77818_set_charge_termination_voltage(struct udevice *dev)
|
|
{
|
|
int ret;
|
|
|
|
dev = (dev ? dev : chDev);
|
|
if (!dev)
|
|
return -1;
|
|
|
|
ret = max77818_set_reg_lock(dev, false);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = max77818_i2c_reg_write8(dev,
|
|
MAX77818_REG_CHG_CNFG_04,
|
|
MAX77818_CHG_CNFG_04__CHG_CV_PRM__MASK,
|
|
MAX77818_CHG_CNFG_04__CHG_CV_PRM__4V3);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = max77818_i2c_reg_write8(dev,
|
|
MAX77818_REG_CHG_CNFG_04,
|
|
MAX77818_CHG_CNFG_04__MINVSYS__MASK,
|
|
MAX77818_CHG_CNFG_04__MINVSYS__3P4V_VSYS_MIN);
|
|
if (ret)
|
|
return ret;
|
|
|
|
return max77818_set_reg_lock(dev, true);
|
|
}
|
|
|
|
int max77818_set_pogo_input_current_limit(struct udevice *dev,
|
|
enum pogo_ilim ilim)
|
|
{
|
|
uint ilim_config_value;
|
|
|
|
dev = (dev ? dev : chDev);
|
|
if (!dev)
|
|
return -1;
|
|
|
|
switch(ilim) {
|
|
case ILIM_500_MA:
|
|
ilim_config_value = MAX77818_CHG_CNFG_09__CHGIN_ILIM_500_MA;
|
|
break;
|
|
case ILIM_1P5_A:
|
|
ilim_config_value = MAX77818_CHG_CNFG_09__CHGIN_ILIM_1P5_A;
|
|
break;
|
|
case ILIM_2P8_A:
|
|
ilim_config_value = MAX77818_CHG_CNFG_09__CHGIN_ILIM_2P8_A;
|
|
break;
|
|
default:
|
|
/* Invalid value, just set default 500 mA */
|
|
ilim_config_value = MAX77818_CHG_CNFG_09__CHGIN_ILIM_500_MA;
|
|
}
|
|
|
|
return max77818_i2c_reg_write8(dev,
|
|
MAX77818_REG_CHG_CNFG_09,
|
|
MAX77818_CHG_CNFG_09__CHGIN_ILIM__MASK,
|
|
ilim_config_value);
|
|
}
|
|
|
|
int max77818_set_usbc_input_current_limit(struct udevice *dev)
|
|
{
|
|
dev = (dev ? dev : chDev);
|
|
if (!dev)
|
|
return -1;
|
|
|
|
return max77818_i2c_reg_write8(dev,
|
|
MAX77818_REG_CHG_CNFG_10,
|
|
MAX77818_CHG_CNFG_10__WCIN_ILIM__MASK,
|
|
MAX77818_CHG_CNFG_10__WCIN_ILIM_500_MA);
|
|
}
|
|
|
|
int max77818_set_minimal_charger_config(void)
|
|
{
|
|
int ret;
|
|
bool fgcc_restore_state;
|
|
|
|
if (!chDev) {
|
|
ret = max77818_init_charger_device(true, &fgcc_restore_state);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
printf("Trying to set fast charge current: 1.5A\n");
|
|
ret = max77818_set_fast_charge_current(NULL, FASTCHARGE_1P5_A);
|
|
if (ret != 0)
|
|
printf("%s Failed to set fast charger current\n",
|
|
__func__);
|
|
|
|
printf("Trying to set pogo input current limit: 500 mA\n");
|
|
ret = max77818_set_pogo_input_current_limit(NULL, ILIM_500_MA);
|
|
if (ret != 0)
|
|
printf("%s: Failed to set pogo input current limit\n",
|
|
__func__);
|
|
|
|
printf("Trying to set USB-C input current limit: 500 mA\n");
|
|
ret = max77818_set_usbc_input_current_limit(NULL);
|
|
if (ret != 0)
|
|
printf("%s: Failed to set USB-C input current limit\n",
|
|
__func__);
|
|
|
|
printf("Trying to set normal charge mode (turn off OTG mode if set)\n");
|
|
ret = max77818_set_otg_pwr(NULL, false);
|
|
if (ret != 0)
|
|
printf("%s: Failed to set normal charge mode\n",
|
|
__func__);
|
|
|
|
ret = max77818_restore_fgcc(fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to restore FGCC: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int zs_do_get_battery_charge_status(cmd_tbl_t *cmdtp,
|
|
int flag,
|
|
int argc,
|
|
char * const argv[])
|
|
{
|
|
int ret;
|
|
bool fgcc_restore_state;
|
|
|
|
if (!chDev) {
|
|
ret = max77818_init_charger_device(true, &fgcc_restore_state);
|
|
if(ret) {
|
|
printf("%s: Unable to get battery charge status\n",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = max77818_get_battery_status(chDev);
|
|
if (ret) {
|
|
printf("Failed to get battery detection status: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_get_wcin_details(chDev);
|
|
if (ret) {
|
|
printf("Failed to get wcin (USB-C) status: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_get_chgin_details(chDev);
|
|
if (ret) {
|
|
printf("Failed to get chgin (POGO) status: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_get_details_1(chDev);
|
|
if (ret) {
|
|
printf("Failed to get DETAILS_1 status: 0x%02X\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_get_details_2(chDev);
|
|
if (ret) {
|
|
printf("Failed to get DETAILS_2 status: 0x%02X\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_restore_fgcc(fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to restore FGCC: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
U_BOOT_CMD(
|
|
max77818_get_battery_charge_status, 1, 1, zs_do_get_battery_charge_status,
|
|
"Get battery and charge voltage status",
|
|
"Read battery detection status, USB-C voltage status and POGO input voltage status"
|
|
);
|
|
|
|
static int zs_do_set_otg_pwr(cmd_tbl_t *cmdtp,
|
|
int flag,
|
|
int argc,
|
|
char * const argv[])
|
|
{
|
|
int ret;
|
|
bool fgcc_restore_state;
|
|
|
|
if (argc != 2) {
|
|
printf("Usage: set_otg_power <on | off>\n");
|
|
return -1;
|
|
}
|
|
|
|
if ((strcmp(argv[1], "on") != 0) && (strcmp(argv[1], "off") != 0)) {
|
|
printf("Usage: set_otg_power <on | off>\n");
|
|
return -1;
|
|
}
|
|
|
|
if (!chDev) {
|
|
ret = max77818_init_charger_device(true, &fgcc_restore_state);
|
|
if(ret) {
|
|
printf("%s: Unable to set OTG power\n",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
if (strcmp(argv[1], "on") == 0) {
|
|
ret = max77818_set_otg_pwr(chDev, true);
|
|
if (ret) {
|
|
printf("Failed to turn OTG power on: %d\n", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
else {
|
|
ret = max77818_set_otg_pwr(chDev, false);
|
|
if (ret) {
|
|
printf("Failed to turn OTG power off: %d\n", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = max77818_restore_fgcc(fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to restore FGCC: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
U_BOOT_CMD(
|
|
max77818_set_otg_pwr, 2, 1, zs_do_set_otg_pwr,
|
|
"Turn on/off OTG power",
|
|
"Turn off charging, and enable OTG power output to connected device"
|
|
);
|
|
|
|
static int zs_do_set_fastcharge_current_1P5_A(cmd_tbl_t *cmdtp,
|
|
int flag,
|
|
int argc,
|
|
char * const argv[])
|
|
{
|
|
int ret;
|
|
bool fgcc_restore_state;
|
|
|
|
if (argc != 1) {
|
|
printf("Usage: set_fastcharge_current_2P8_A\n");
|
|
return -1;
|
|
}
|
|
|
|
if (!chDev) {
|
|
ret = max77818_init_charger_device(true, &fgcc_restore_state);
|
|
if(ret) {
|
|
printf("%s: Unable to set fastcharge current (1.5A)\n",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = max77818_set_fast_charge_current(chDev, FASTCHARGE_1P5_A);
|
|
if (ret) {
|
|
printf("Failed to set fast charge current: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_restore_fgcc(fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to restore FGCC: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
U_BOOT_CMD(
|
|
max77818_set_fast_charge_current_1P5_A, 1, 1, zs_do_set_fastcharge_current_1P5_A,
|
|
"Set fastcharge current (1.5A)",
|
|
"Set fastcharge current to 1.5A for the pogo pin charge input"
|
|
);
|
|
|
|
static int zs_do_set_fastcharge_current_2P8_A(cmd_tbl_t *cmdtp,
|
|
int flag,
|
|
int argc,
|
|
char * const argv[])
|
|
{
|
|
int ret;
|
|
bool fgcc_restore_state;
|
|
|
|
if (argc != 1) {
|
|
printf("Usage: set_fastcharge_current_2P8_A\n");
|
|
return -1;
|
|
}
|
|
|
|
if (!chDev) {
|
|
ret = max77818_init_charger_device(true, &fgcc_restore_state);
|
|
if(ret) {
|
|
printf("%s: Unable to set fastcharge current (2.8A)\n",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = max77818_set_fast_charge_current(chDev, FASTCHARGE_2P8_A);
|
|
if (ret) {
|
|
printf("Failed to set fast charge current: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_restore_fgcc(fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to restore FGCC: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
U_BOOT_CMD(
|
|
max77818_set_fast_charge_current_2P8_A, 1, 1, zs_do_set_fastcharge_current_2P8_A,
|
|
"Set fastcharge current (2.8A)",
|
|
"Set fastcharge current to 2.8A for the pogo pin charge input"
|
|
);
|
|
|
|
static int zs_do_set_charge_termination_voltage(cmd_tbl_t *cmdtp,
|
|
int flag,
|
|
int argc,
|
|
char * const argv[])
|
|
{
|
|
int ret;
|
|
bool fgcc_restore_state;
|
|
|
|
if (argc != 1) {
|
|
printf("Usage: set_charge_termination_voltage\n");
|
|
return -1;
|
|
}
|
|
|
|
if (!chDev) {
|
|
ret = max77818_init_charger_device(true, &fgcc_restore_state);
|
|
if(ret) {
|
|
printf("%s: Unable to set fastcharge current (2.8A)\n",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = max77818_set_charge_termination_voltage(chDev);
|
|
if (ret) {
|
|
printf("Failed to set charge termination voltage: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_restore_fgcc(fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to restore FGCC: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
U_BOOT_CMD(
|
|
max77818_set_charge_termination_voltage, 1, 1, zs_do_set_charge_termination_voltage,
|
|
"Set charge termination voltage (3.4V)",
|
|
"Set charge termination voltage to 3.4V"
|
|
);
|
|
|
|
static int zs_do_set_pogo_input_current_limit_1P5_A(cmd_tbl_t *cmdtp,
|
|
int flag,
|
|
int argc,
|
|
char * const argv[])
|
|
{
|
|
int ret;
|
|
bool fgcc_restore_state;
|
|
|
|
if (argc != 1) {
|
|
printf("Usage: set_pogo_input_current_limit\n");
|
|
return -1;
|
|
}
|
|
|
|
if (!chDev) {
|
|
ret = max77818_init_charger_device(true, &fgcc_restore_state);
|
|
if(ret) {
|
|
printf("%s: Unable to set fastcharge current (2.8A)\n",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = max77818_set_pogo_input_current_limit(chDev, ILIM_1P5_A);
|
|
if (ret) {
|
|
printf("Failed to set pogo input current limit: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_restore_fgcc(fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to restore FGCC: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
U_BOOT_CMD(
|
|
max77818_set_pogo_input_current_limit_1P5_A, 1, 1, zs_do_set_pogo_input_current_limit_1P5_A,
|
|
"Set max pogo input current (1.5A)",
|
|
"Set max charge input current limit to 1.5A for the pogo pin charge input"
|
|
);
|
|
|
|
static int zs_do_set_pogo_input_current_limit_2P8_A(cmd_tbl_t *cmdtp,
|
|
int flag,
|
|
int argc,
|
|
char * const argv[])
|
|
{
|
|
int ret;
|
|
bool fgcc_restore_state;
|
|
|
|
if (argc != 1) {
|
|
printf("Usage: set_pogo_input_current_limit\n");
|
|
return -1;
|
|
}
|
|
|
|
if (!chDev) {
|
|
ret = max77818_init_charger_device(true, &fgcc_restore_state);
|
|
if(ret) {
|
|
printf("%s: Unable to set fastcharge current (2.8A)\n",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = max77818_set_pogo_input_current_limit(chDev, ILIM_2P8_A);
|
|
if (ret) {
|
|
printf("Failed to set pogo input current limit: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_restore_fgcc(fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to restore FGCC: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
U_BOOT_CMD(
|
|
max77818_set_pogo_input_current_limit_2P8_A, 1, 1, zs_do_set_pogo_input_current_limit_2P8_A,
|
|
"Set max pogo input current (2.8A)",
|
|
"Set max charge input current limit to 2.8A for the pogo pin charge input"
|
|
);
|
|
|
|
static int zs_do_set_usbc_input_current_limit(cmd_tbl_t *cmdtp,
|
|
int flag,
|
|
int argc,
|
|
char * const argv[])
|
|
{
|
|
int ret;
|
|
bool fgcc_restore_state;
|
|
|
|
if (argc != 1) {
|
|
printf("Usage: set_usbc_input_current_limit\n");
|
|
return -1;
|
|
}
|
|
|
|
if (!chDev) {
|
|
ret = max77818_init_charger_device(true, &fgcc_restore_state);
|
|
if(ret) {
|
|
printf("%s: Unable to set fastcharge current (2.8A)\n",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = max77818_set_usbc_input_current_limit(chDev);
|
|
if (ret) {
|
|
printf("Failed to turn OTG power off: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = max77818_restore_fgcc(fgcc_restore_state);
|
|
if (ret) {
|
|
printf("%s: Failed to restore FGCC: %d\n",
|
|
__func__,
|
|
ret);
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
U_BOOT_CMD(
|
|
max77818_set_usbc_input_current_limit, 1, 1, zs_do_set_usbc_input_current_limit,
|
|
"Set max USB-C input current (500 mA)",
|
|
"Set max charge input current limit to 500 mA for the USB-C charge input"
|
|
);
|
|
|
|
static int read_gpio(unsigned gpio)
|
|
{
|
|
int ret;
|
|
|
|
ret = gpio_request(gpio, "gpio");
|
|
if (ret) {
|
|
printf("gpio_request failed for gpio: %u\n", gpio);
|
|
return ret;
|
|
}
|
|
|
|
ret = gpio_direction_input(gpio);
|
|
if (ret) {
|
|
printf("gpio_direction_input failed for gpio: %u\n", gpio);
|
|
return ret;
|
|
}
|
|
|
|
return gpio_get_value(gpio);
|
|
}
|
|
|
|
static iomux_v3_cfg_t const chargestat_pads[] = {
|
|
MX7D_PAD_SAI2_TX_SYNC__GPIO6_IO19 | MUX_PAD_CTRL(PAD_CTL_PUS_PU100KOHM),
|
|
MX7D_PAD_SAI2_TX_BCLK__GPIO6_IO20 | MUX_PAD_CTRL(PAD_CTL_PUS_PU100KOHM),
|
|
};
|
|
|
|
bool max77818_is_charging(void)
|
|
{
|
|
int ret;
|
|
unsigned gpio_chgin = IMX_GPIO_NR(6, 19);
|
|
unsigned gpio_wcin = IMX_GPIO_NR(6, 20);
|
|
bool stat_chgin, stat_wcin;
|
|
|
|
imx_iomux_v3_setup_multiple_pads(chargestat_pads, ARRAY_SIZE(chargestat_pads));
|
|
|
|
ret = read_gpio(gpio_chgin);
|
|
stat_chgin = (ret == 0);
|
|
|
|
ret = read_gpio(gpio_wcin);
|
|
stat_wcin = (ret == 0);
|
|
|
|
return (stat_chgin || stat_wcin);
|
|
}
|