From 4e5b768771bba978e9213002e81abd3b52ed00e7 Mon Sep 17 00:00:00 2001 From: Zhangbin Tong Date: Mon, 28 Sep 2015 11:36:31 +0800 Subject: [PATCH] power_supply: cw2015_battery: code style fixes Change-Id: I3cf0af574e11b7fd32adaaecbd6dbe83e72c83c9 Signed-off-by: Zhangbin Tong --- drivers/power/cw2015_battery.c | 2150 +++++++++++++------------- include/linux/power/cw2015_battery.h | 120 +- 2 files changed, 1167 insertions(+), 1103 deletions(-) diff --git a/drivers/power/cw2015_battery.c b/drivers/power/cw2015_battery.c index 47cd9bd6024b..2eca11cce96e 100755 --- a/drivers/power/cw2015_battery.c +++ b/drivers/power/cw2015_battery.c @@ -1,5 +1,6 @@ /* - * RockChip ADC Battery Driver + * Fuel gauge driver for CellWise 2013 / 2015 + * * Copyright (C) 2012, RockChip * * Authors: xuhuicong @@ -10,7 +11,6 @@ * */ -//#define DEBUG 1 #include #include #include @@ -20,93 +20,27 @@ #include #include #include -#include #include #include #include #include -#define CW2015_GPIO_HIGH 1 -#define CW2015_GPIO_LOW 0 - -#define REG_VERSION 0x0 -#define REG_VCELL 0x2 -#define REG_SOC 0x4 -#define REG_RRT_ALERT 0x6 -#define REG_CONFIG 0x8 -#define REG_MODE 0xA -#define REG_BATINFO 0x10 - -#define MODE_SLEEP_MASK (0x3<<6) -#define MODE_SLEEP (0x3<<6) -#define MODE_NORMAL (0x0<<6) -#define MODE_QUICK_START (0x3<<4) -#define MODE_RESTART (0xf<<0) - -#define CONFIG_UPDATE_FLG (0x1<<1) -#define ATHD (0x0<<3) //ATHD = 0% - -#define CW_I2C_SPEED 100000 // default i2c speed set 100khz -#define BATTERY_UP_MAX_CHANGE 420 // the max time allow battery change quantity -#define BATTERY_DOWN_CHANGE 60 // the max time allow battery change quantity -#define BATTERY_DOWN_MIN_CHANGE_RUN 30 // the min time allow battery change quantity when run -#define BATTERY_DOWN_MIN_CHANGE_SLEEP 1800 // the min time allow battery change quantity when run 30min - -#define BATTERY_DOWN_MAX_CHANGE_RUN_AC_ONLINE 3600 - -#define NO_STANDARD_AC_BIG_CHARGE_MODE 1 -// #define SYSTEM_SHUTDOWN_VOLTAGE 3400000 //set system shutdown voltage related in battery info. -#define BAT_LOW_INTERRUPT 1 - -#define USB_CHARGER_MODE 1 -#define AC_CHARGER_MODE 2 -#define CW_QUICKSTART 0 - -extern int dwc_otg_check_dpdm(void); -extern int get_gadget_connect_flag(void); -extern int dwc_vbus_status( void ); - -struct cw_battery { - struct i2c_client *client; - struct workqueue_struct *battery_workqueue; - struct delayed_work battery_delay_work; - struct delayed_work dc_wakeup_work; - struct delayed_work bat_low_wakeup_work; - struct cw_bat_platform_data plat_data; - - struct power_supply rk_bat; - struct power_supply rk_ac; - struct power_supply rk_usb; - - long sleep_time_capacity_change; // the sleep time from capacity change to present, it will set 0 when capacity change - long run_time_capacity_change; - - long sleep_time_charge_start; // the sleep time from insert ac to present, it will set 0 when insert ac - long run_time_charge_start; - - int dc_online; - int usb_online; - int charger_mode; - int charger_init_mode; - int capacity; - int voltage; - int status; - int time_to_empty; - int alt; - - int bat_change; -}; +#include -static int i2c_master_reg8_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate) +static int i2c_master_reg8_send(const struct i2c_client *client, const char reg, + const char *buf, int count, int scl_rate) { - struct i2c_adapter *adap=client->adapter; - struct i2c_msg msg; int ret; - char *tx_buf = (char *)kzalloc(count + 1, GFP_KERNEL); - if(!tx_buf) + char *tx_buf; + struct i2c_msg msg; + struct i2c_adapter *adap = client->adapter; + + tx_buf = kzalloc(count + 1, GFP_KERNEL); + if (!tx_buf) return -ENOMEM; + tx_buf[0] = reg; - memcpy(tx_buf+1, buf, count); + memcpy(tx_buf + 1, buf, count); msg.addr = client->addr; msg.flags = client->flags; @@ -116,17 +50,18 @@ static int i2c_master_reg8_send(const struct i2c_client *client, const char reg, ret = i2c_transfer(adap, &msg, 1); kfree(tx_buf); - return (ret == 1) ? count : ret; + return (ret == 1) ? count : ret; } -static int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate) +static int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, + char *buf, int count, int scl_rate) { - struct i2c_adapter *adap=client->adapter; + struct i2c_adapter *adap = client->adapter; struct i2c_msg msgs[2]; int ret; char reg_buf = reg; - + msgs[0].addr = client->addr; msgs[0].flags = client->flags; msgs[0].len = 1; @@ -141,987 +76,1014 @@ static int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, ret = i2c_transfer(adap, msgs, 2); - return (ret == 2)? count : ret; + return (ret == 2) ? count : ret; } static int cw_read(struct i2c_client *client, u8 reg, u8 buf[]) { - int ret; - ret = i2c_master_reg8_recv(client, reg, buf, 1, CW_I2C_SPEED); - return ret; + int ret; + + ret = i2c_master_reg8_recv(client, reg, buf, 1, CW_I2C_SPEED); + + return ret; } static int cw_write(struct i2c_client *client, u8 reg, u8 const buf[]) { - int ret; - ret = i2c_master_reg8_send(client, reg, buf, 1, CW_I2C_SPEED); - return ret; + int ret; + + ret = i2c_master_reg8_send(client, reg, buf, 1, CW_I2C_SPEED); + + return ret; } static int cw_read_word(struct i2c_client *client, u8 reg, u8 buf[]) { - int ret; - ret = i2c_master_reg8_recv(client, reg, buf, 2, CW_I2C_SPEED); - return ret; + int ret; + + ret = i2c_master_reg8_recv(client, reg, buf, 2, CW_I2C_SPEED); + + return ret; } -#if 0 -static int cw_write_word(struct i2c_client *client, u8 reg, u8 const buf[]) +static int cw_update_config_info(struct cw_battery *cw_bat) { - int ret; - ret = i2c_master_reg8_send(client, reg, buf, 2, CW_I2C_SPEED); - return ret; -} -#endif + int ret; + u8 reg_val; + u8 i; + u8 reset_val; + dev_info(&cw_bat->client->dev, "func: %s-------\n", __func__); + /* make sure no in sleep mode */ + ret = cw_read(cw_bat->client, REG_MODE, ®_val); + if (ret < 0) + return ret; -static int cw_update_config_info(struct cw_battery *cw_bat) -{ - int ret; - u8 reg_val; - u8 i; - u8 reset_val; - - dev_info(&cw_bat->client->dev, "func: %s-------\n", __func__); - - /* make sure no in sleep mode */ - ret = cw_read(cw_bat->client, REG_MODE, ®_val); - if (ret < 0) - return ret; - - reset_val = reg_val; - if((reg_val & MODE_SLEEP_MASK) == MODE_SLEEP) { - dev_err(&cw_bat->client->dev, "Error, device in sleep mode, cannot update battery info\n"); - return -1; - } - - /* update new battery info */ - for (i = 0; i < SIZE_BATINFO; i++) { - // dev_info(&cw_bat->client->dev, "cw_bat->plat_data.cw_bat_config_info[%d] = 0x%x\n", i, cw_bat->plat_data.cw_bat_config_info[i]); - ret = cw_write(cw_bat->client, REG_BATINFO + i, (u8 *)&cw_bat->plat_data.cw_bat_config_info[i]); - - if (ret < 0) - return ret; - } - - /* readback & check */ - for (i = 0; i < SIZE_BATINFO; i++) { - ret = cw_read(cw_bat->client, REG_BATINFO + i, ®_val); - if (reg_val != cw_bat->plat_data.cw_bat_config_info[i]) - return -1; - } - - /* set cw2015/cw2013 to use new battery info */ - ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); - if (ret < 0) - return ret; - - reg_val |= CONFIG_UPDATE_FLG; /* set UPDATE_FLAG */ - reg_val &= 0x07; /* clear ATHD */ - reg_val |= ATHD; /* set ATHD */ - ret = cw_write(cw_bat->client, REG_CONFIG, ®_val); - if (ret < 0) - return ret; - - /* check 2015/cw2013 for ATHD & update_flag */ - ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); - if (ret < 0) - return ret; - - if (!(reg_val & CONFIG_UPDATE_FLG)) { - dev_info(&cw_bat->client->dev, "update flag for new battery info have not set..\n"); - } - - if ((reg_val & 0xf8) != ATHD) { - dev_info(&cw_bat->client->dev, "the new ATHD have not set..\n"); - } - - /* reset */ - reset_val &= ~(MODE_RESTART); - reg_val = reset_val | MODE_RESTART; - ret = cw_write(cw_bat->client, REG_MODE, ®_val); - if (ret < 0) - return ret; - - msleep(10); - ret = cw_write(cw_bat->client, REG_MODE, &reset_val); - if (ret < 0) - return ret; - - return 0; + reset_val = reg_val; + if ((reg_val & MODE_SLEEP_MASK) == MODE_SLEEP) { + dev_err(&cw_bat->client->dev, + "Error, device in sleep mode, cannot update battery info\n"); + return -1; + } + + /* update new battery info */ + for (i = 0; i < SIZE_BATINFO; i++) { + ret = + cw_write(cw_bat->client, REG_BATINFO + i, + (u8 *)&cw_bat->plat_data.cw_bat_config_info[i]); + + if (ret < 0) + return ret; + } + + /* readback & check */ + for (i = 0; i < SIZE_BATINFO; i++) { + ret = cw_read(cw_bat->client, REG_BATINFO + i, ®_val); + if (reg_val != cw_bat->plat_data.cw_bat_config_info[i]) + return -1; + } + + /* set cw2015/cw2013 to use new battery info */ + ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); + if (ret < 0) + return ret; + + reg_val |= CONFIG_UPDATE_FLG; /* set UPDATE_FLAG */ + reg_val &= 0x07; /* clear ATHD */ + reg_val |= ATHD; /* set ATHD */ + ret = cw_write(cw_bat->client, REG_CONFIG, ®_val); + if (ret < 0) + return ret; + + /* check 2015/cw2013 for ATHD & update_flag */ + ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); + if (ret < 0) + return ret; + + if (!(reg_val & CONFIG_UPDATE_FLG)) { + dev_info(&cw_bat->client->dev, + "update flag for new battery info have not set..\n"); + } + + if ((reg_val & 0xf8) != ATHD) + dev_info(&cw_bat->client->dev, "the new ATHD have not set..\n"); + + /* reset */ + reset_val &= ~(MODE_RESTART); + reg_val = reset_val | MODE_RESTART; + ret = cw_write(cw_bat->client, REG_MODE, ®_val); + if (ret < 0) + return ret; + + msleep(10); + ret = cw_write(cw_bat->client, REG_MODE, &reset_val); + if (ret < 0) + return ret; + + return 0; } static int cw_init(struct cw_battery *cw_bat) { - int ret; - int i; - u8 reg_val = MODE_SLEEP; -#if 0 - ret = cw_read(cw_bat->client, REG_MODE, ®_val); - if (ret < 0) - return ret; -#endif - if ((reg_val & MODE_SLEEP_MASK) == MODE_SLEEP) { - reg_val = MODE_NORMAL; - ret = cw_write(cw_bat->client, REG_MODE, ®_val); - if (ret < 0) - return ret; - } - - ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); - if (ret < 0) - return ret; - - if ((reg_val & 0xf8) != ATHD) { - dev_info(&cw_bat->client->dev, "the new ATHD have not set\n"); - reg_val &= 0x07; /* clear ATHD */ - reg_val |= ATHD; /* set ATHD */ - ret = cw_write(cw_bat->client, REG_CONFIG, ®_val); - if (ret < 0) - return ret; - } - - ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); - if (ret < 0) - return ret; - - if (!(reg_val & CONFIG_UPDATE_FLG)) { - dev_info(&cw_bat->client->dev, "update flag for new battery info have not set\n"); - ret = cw_update_config_info(cw_bat); - if (ret < 0) - return ret; - } else { - for(i = 0; i < SIZE_BATINFO; i++) { - ret = cw_read(cw_bat->client, (REG_BATINFO + i), ®_val); - if (ret < 0) - return ret; - - if (cw_bat->plat_data.cw_bat_config_info[i] != reg_val) - break; - } - - if (i != SIZE_BATINFO) { - dev_info(&cw_bat->client->dev, "update flag for new battery info have not set\n"); - ret = cw_update_config_info(cw_bat); - if (ret < 0) - return ret; - } - } - - for (i = 0; i < 30; i++) { - ret = cw_read(cw_bat->client, REG_SOC, ®_val); - if (ret < 0) - return ret; - else if (reg_val <= 0x64) - break; - - msleep(100); - if (i > 25) - dev_err(&cw_bat->client->dev, "cw2015/cw2013 input unvalid power error\n"); - - } - if (i >=30){ - reg_val = MODE_SLEEP; - ret = cw_write(cw_bat->client, REG_MODE, ®_val); - dev_info(&cw_bat->client->dev, "report battery capacity error"); - return -1; - } - return 0; + int ret; + int i; + u8 reg_val = MODE_SLEEP; + + if ((reg_val & MODE_SLEEP_MASK) == MODE_SLEEP) { + reg_val = MODE_NORMAL; + ret = cw_write(cw_bat->client, REG_MODE, ®_val); + if (ret < 0) + return ret; + } + + ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); + if (ret < 0) + return ret; + + if ((reg_val & 0xf8) != ATHD) { + dev_info(&cw_bat->client->dev, "the new ATHD have not set\n"); + reg_val &= 0x07; /* clear ATHD */ + reg_val |= ATHD; /* set ATHD */ + ret = cw_write(cw_bat->client, REG_CONFIG, ®_val); + if (ret < 0) + return ret; + } + + ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); + if (ret < 0) + return ret; + + if (!(reg_val & CONFIG_UPDATE_FLG)) { + dev_info(&cw_bat->client->dev, + "update flag for new battery info have not set\n"); + ret = cw_update_config_info(cw_bat); + if (ret < 0) + return ret; + } else { + for (i = 0; i < SIZE_BATINFO; i++) { + ret = + cw_read(cw_bat->client, (REG_BATINFO + i), + ®_val); + if (ret < 0) + return ret; + + if (cw_bat->plat_data.cw_bat_config_info[i] != reg_val) + break; + } + + if (i != SIZE_BATINFO) { + dev_info(&cw_bat->client->dev, + "update flag for new battery info have not set\n"); + ret = cw_update_config_info(cw_bat); + if (ret < 0) + return ret; + } + } + + for (i = 0; i < 30; i++) { + ret = cw_read(cw_bat->client, REG_SOC, ®_val); + if (ret < 0) + return ret; + else if (reg_val <= 0x64) + break; + + msleep(100); + if (i > 25) + dev_err(&cw_bat->client->dev, + "cw2015/cw2013 input unvalid power error\n"); + } + + if (i >= 30) { + reg_val = MODE_SLEEP; + ret = cw_write(cw_bat->client, REG_MODE, ®_val); + dev_info(&cw_bat->client->dev, "report battery capacity error"); + return -1; + } + return 0; } static void cw_update_time_member_charge_start(struct cw_battery *cw_bat) { - struct timespec ts; - int new_run_time; - int new_sleep_time; + struct timespec ts; + int new_run_time; + int new_sleep_time; - ktime_get_ts(&ts); - new_run_time = ts.tv_sec; + ktime_get_ts(&ts); + new_run_time = ts.tv_sec; - get_monotonic_boottime(&ts); - new_sleep_time = ts.tv_sec - new_run_time; + get_monotonic_boottime(&ts); + new_sleep_time = ts.tv_sec - new_run_time; - cw_bat->run_time_charge_start = new_run_time; - cw_bat->sleep_time_charge_start = new_sleep_time; + cw_bat->run_time_charge_start = new_run_time; + cw_bat->sleep_time_charge_start = new_sleep_time; } static void cw_update_time_member_capacity_change(struct cw_battery *cw_bat) { - struct timespec ts; - int new_run_time; - int new_sleep_time; + struct timespec ts; + int new_run_time; + int new_sleep_time; - ktime_get_ts(&ts); - new_run_time = ts.tv_sec; + ktime_get_ts(&ts); + new_run_time = ts.tv_sec; - get_monotonic_boottime(&ts); - new_sleep_time = ts.tv_sec - new_run_time; + get_monotonic_boottime(&ts); + new_sleep_time = ts.tv_sec - new_run_time; - cw_bat->run_time_capacity_change = new_run_time; - cw_bat->sleep_time_capacity_change = new_sleep_time; + cw_bat->run_time_capacity_change = new_run_time; + cw_bat->sleep_time_capacity_change = new_sleep_time; } -#if(CW_QUICKSTART) +#if (CW_QUICKSTART) static int cw_quickstart(struct cw_battery *cw_bat) { - int ret = 0; - u8 reg_val = MODE_QUICK_START; - - ret = cw_write(cw_bat->client, REG_MODE, ®_val); //(MODE_QUICK_START | MODE_NORMAL)); // 0x30 - if(ret < 0) { - dev_err(&cw_bat->client->dev, "Error quick start1\n"); - return ret; - } - - reg_val = MODE_NORMAL; - ret = cw_write(cw_bat->client, REG_MODE, ®_val); - if(ret < 0) { - dev_err(&cw_bat->client->dev, "Error quick start2\n"); - return ret; - } - return 1; + int ret = 0; + u8 reg_val = MODE_QUICK_START; + + ret = cw_write(cw_bat->client, REG_MODE, ®_val); + if (ret < 0) { + dev_err(&cw_bat->client->dev, "Error quick start1\n"); + return ret; + } + + reg_val = MODE_NORMAL; + ret = cw_write(cw_bat->client, REG_MODE, ®_val); + if (ret < 0) { + dev_err(&cw_bat->client->dev, "Error quick start2\n"); + return ret; + } + return 1; } #endif static int cw_get_capacity(struct cw_battery *cw_bat) { - int cw_capacity; - int ret; - u8 reg_val; - - struct timespec ts; - long new_run_time; - long new_sleep_time; - long capacity_or_aconline_time; - int allow_change; - int allow_capacity; - static int if_quickstart = 0; - static int jump_flag =0; - static int reset_loop =0; - int charge_time; - u8 reset_val; - - - ret = cw_read(cw_bat->client, REG_SOC, ®_val); - //ret = cw_read_word(cw_bat->client, REG_SOC, reg_val); - if (ret < 0) - return ret; - cw_capacity = reg_val; - - if ((cw_capacity == 0)&&(if_quickstart ==0)) { - dev_info(&cw_bat->client->dev, "the cw201x capacity is 0 !!!!!!!, funciton: %s, line: %d\n", __func__, __LINE__); - - reset_val = MODE_SLEEP; - ret = cw_write(cw_bat->client, REG_MODE, &reset_val); - if (ret < 0) - return ret; - reset_val = MODE_NORMAL; - msleep(10); - ret = cw_write(cw_bat->client, REG_MODE, &reset_val); - if (ret < 0) - return ret; - dev_info(&cw_bat->client->dev, "report battery capacity error1"); -// ret = cw_update_config_info(cw_bat); -// if (ret) -// return ret; - if_quickstart =1; - } - else - dev_dbg(&cw_bat->client->dev, "the cw201x capacity is %d, funciton: %s\n", cw_capacity, __func__); - - if ((cw_capacity < 0) || (cw_capacity > 100)) { - dev_err(&cw_bat->client->dev, "get cw_capacity error; cw_capacity = %d\n", cw_capacity); - reset_loop++; - - if (reset_loop >5){ - - reset_val = MODE_SLEEP; - ret = cw_write(cw_bat->client, REG_MODE, &reset_val); - if (ret < 0) - return ret; - reset_val = MODE_NORMAL; - msleep(10); - ret = cw_write(cw_bat->client, REG_MODE, &reset_val); - if (ret < 0) - return ret; - dev_info(&cw_bat->client->dev, "report battery capacity error"); - ret = cw_update_config_info(cw_bat); - if (ret) - return ret; - reset_loop =0; - - } - - return cw_capacity; - }else { - reset_loop =0; - } - - ktime_get_ts(&ts); - new_run_time = ts.tv_sec; - - get_monotonic_boottime(&ts); - new_sleep_time = ts.tv_sec - new_run_time; - - if (((cw_bat->charger_mode > 0) && (cw_capacity <= (cw_bat->capacity - 1)) && (cw_capacity > (cw_bat->capacity - 9))) - || ((cw_bat->charger_mode == 0) && (cw_capacity == (cw_bat->capacity + 1)))) { // modify battery level swing - - if (!(cw_capacity == 0 && cw_bat->capacity <= 2)) { - cw_capacity = cw_bat->capacity; - } - } - - if ((cw_bat->charger_mode > 0) && (cw_capacity >= 95) && (cw_capacity <= cw_bat->capacity)) { // avoid no charge full - - capacity_or_aconline_time = (cw_bat->sleep_time_capacity_change > cw_bat->sleep_time_charge_start) ? cw_bat->sleep_time_capacity_change : cw_bat->sleep_time_charge_start; - capacity_or_aconline_time += (cw_bat->run_time_capacity_change > cw_bat->run_time_charge_start) ? cw_bat->run_time_capacity_change : cw_bat->run_time_charge_start; - allow_change = (new_sleep_time + new_run_time - capacity_or_aconline_time) / BATTERY_UP_MAX_CHANGE; - if (allow_change > 0) { - allow_capacity = cw_bat->capacity + allow_change; - cw_capacity = (allow_capacity <= 100) ? allow_capacity : 100; - jump_flag =1; - } else if (cw_capacity <= cw_bat->capacity) { - cw_capacity = cw_bat->capacity; - } - - } - - else if ((cw_bat->charger_mode == 0) && (cw_capacity <= cw_bat->capacity ) && (cw_capacity >= 90) && (jump_flag == 1)) { // avoid battery level jump to CW_BAT - capacity_or_aconline_time = (cw_bat->sleep_time_capacity_change > cw_bat->sleep_time_charge_start) ? cw_bat->sleep_time_capacity_change : cw_bat->sleep_time_charge_start; - capacity_or_aconline_time += (cw_bat->run_time_capacity_change > cw_bat->run_time_charge_start) ? cw_bat->run_time_capacity_change : cw_bat->run_time_charge_start; - allow_change = (new_sleep_time + new_run_time - capacity_or_aconline_time) / BATTERY_DOWN_CHANGE; - if (allow_change > 0) { - allow_capacity = cw_bat->capacity - allow_change; - if (cw_capacity >= allow_capacity){ - jump_flag =0; - } - else{ - cw_capacity = (allow_capacity <= 100) ? allow_capacity : 100; - } - } else if (cw_capacity <= cw_bat->capacity) { - cw_capacity = cw_bat->capacity; - } - } - - if ((cw_capacity == 0) && (cw_bat->capacity > 1)) { // avoid battery level jump to 0% at a moment from more than 2% - allow_change = ((new_run_time - cw_bat->run_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_RUN); - allow_change += ((new_sleep_time - cw_bat->sleep_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_SLEEP); - - allow_capacity = cw_bat->capacity - allow_change; - cw_capacity = (allow_capacity >= cw_capacity) ? allow_capacity: cw_capacity; - dev_info(&cw_bat->client->dev, "report GGIC POR happened"); - reset_val = MODE_SLEEP; - ret = cw_write(cw_bat->client, REG_MODE, &reset_val); - if (ret < 0) - return ret; - reset_val = MODE_NORMAL; - msleep(10); - ret = cw_write(cw_bat->client, REG_MODE, &reset_val); - if (ret < 0) - return ret; - dev_info(&cw_bat->client->dev, "report battery capacity error"); - ret = cw_update_config_info(cw_bat); - if (ret) - return ret; - dev_info(&cw_bat->client->dev, "report battery capacity jump 0 "); - } - -#if 1 - if((cw_bat->charger_mode > 0) &&(cw_capacity == 0)) - { - charge_time = new_sleep_time + new_run_time - cw_bat->sleep_time_charge_start - cw_bat->run_time_charge_start; - if ((charge_time > BATTERY_DOWN_MAX_CHANGE_RUN_AC_ONLINE) && (if_quickstart == 0)) { - //cw_quickstart(cw_bat); // if the cw_capacity = 0 the cw2015 will qstrt/ - reset_val = MODE_SLEEP; - ret = cw_write(cw_bat->client, REG_MODE, &reset_val); - if (ret < 0) - return ret; - reset_val = MODE_NORMAL; - msleep(10); - ret = cw_write(cw_bat->client, REG_MODE, &reset_val); - if (ret < 0) - return ret; - dev_info(&cw_bat->client->dev, "report battery capacity error"); - ret = cw_update_config_info(cw_bat); - if (ret) - return ret; - dev_info(&cw_bat->client->dev, "report battery capacity still 0 if in changing"); - if_quickstart = 1; - } - } else if ((if_quickstart == 1)&&(cw_bat->charger_mode == 0)) { - if_quickstart = 0; - } + u8 reg_val; + u8 reset_val; + int ret; + int cw_capacity; + int charge_time; + int allow_change; + int allow_capacity; + long new_run_time; + long new_sleep_time; + long capacity_or_aconline_time; + static int if_quickstart; + static int jump_flag; + static int reset_loop; + struct timespec ts; + + ret = cw_read(cw_bat->client, REG_SOC, ®_val); + if (ret < 0) + return ret; + cw_capacity = reg_val; -#endif + if (cw_capacity == 0 && if_quickstart == 0) { + dev_info(&cw_bat->client->dev, + "the cw201x capacity is 0 !!!!!!!, funciton: %s, line: %d\n", + __func__, __LINE__); + + reset_val = MODE_SLEEP; + ret = cw_write(cw_bat->client, REG_MODE, &reset_val); + if (ret < 0) + return ret; + reset_val = MODE_NORMAL; + msleep(10); + ret = cw_write(cw_bat->client, REG_MODE, &reset_val); + if (ret < 0) + return ret; + dev_info(&cw_bat->client->dev, + "report battery capacity error1"); + if_quickstart = 1; + } else + dev_dbg(&cw_bat->client->dev, + "the cw201x capacity is %d, funciton: %s\n", + cw_capacity, __func__); + + if (cw_capacity < 0 || cw_capacity > 100) { + dev_err(&cw_bat->client->dev, + "get cw_capacity error; cw_capacity = %d\n", + cw_capacity); + reset_loop++; + + if (reset_loop > 5) { + reset_val = MODE_SLEEP; + ret = cw_write(cw_bat->client, REG_MODE, &reset_val); + if (ret < 0) + return ret; + reset_val = MODE_NORMAL; + msleep(10); + ret = cw_write(cw_bat->client, REG_MODE, &reset_val); + if (ret < 0) + return ret; + dev_info(&cw_bat->client->dev, + "report battery capacity error"); + ret = cw_update_config_info(cw_bat); + if (ret) + return ret; + reset_loop = 0; + } + + return cw_capacity; + } else { + reset_loop = 0; + } + + ktime_get_ts(&ts); + new_run_time = ts.tv_sec; + + get_monotonic_boottime(&ts); + new_sleep_time = ts.tv_sec - new_run_time; -#if 0 - if (gpio_is_valid(cw_bat->plat_data.chg_ok_pin)) { - if(gpio_get_value(cw_bat->plat_data.chg_ok_pin) != cw_bat->plat_data.chg_ok_level) { - if (cw_capacity == 100) { - cw_capacity = 99; - } - } else { - if (cw_bat->charger_mode > 0) { - cw_capacity = 100; - } - } - } + /* modify battery level swing */ + if ((cw_bat->charger_mode > 0 && + cw_capacity <= (cw_bat->capacity - 1) && + cw_capacity > (cw_bat->capacity - 9)) || + (cw_bat->charger_mode == 0 && + cw_capacity == (cw_bat->capacity + 1))) { + if (!(cw_capacity == 0 && cw_bat->capacity <= 2)) + cw_capacity = cw_bat->capacity; + } + + /* avoid no charge full */ + if (cw_bat->charger_mode > 0 && + cw_capacity >= 95 && + cw_capacity <= cw_bat->capacity) { + capacity_or_aconline_time = + (cw_bat->sleep_time_capacity_change > + cw_bat->sleep_time_charge_start) ? cw_bat-> + sleep_time_capacity_change : cw_bat-> + sleep_time_charge_start; + capacity_or_aconline_time += + (cw_bat->run_time_capacity_change > + cw_bat->run_time_charge_start) ? cw_bat-> + run_time_capacity_change : cw_bat->run_time_charge_start; + allow_change = + (new_sleep_time + new_run_time - + capacity_or_aconline_time) / BATTERY_UP_MAX_CHANGE; + if (allow_change > 0) { + allow_capacity = cw_bat->capacity + allow_change; + cw_capacity = + (allow_capacity <= 100) ? allow_capacity : 100; + jump_flag = 1; + } else if (cw_capacity <= cw_bat->capacity) { + cw_capacity = cw_bat->capacity; + } + } + /* avoid battery level jump to CW_BAT */ + else if (cw_bat->charger_mode == 0 && + cw_capacity <= cw_bat->capacity && + cw_capacity >= 90 && jump_flag == 1) { + capacity_or_aconline_time = + (cw_bat->sleep_time_capacity_change > + cw_bat->sleep_time_charge_start) ? cw_bat-> + sleep_time_capacity_change : cw_bat-> + sleep_time_charge_start; + capacity_or_aconline_time += + (cw_bat->run_time_capacity_change > + cw_bat->run_time_charge_start) ? cw_bat-> + run_time_capacity_change : cw_bat->run_time_charge_start; + allow_change = + (new_sleep_time + new_run_time - + capacity_or_aconline_time) / BATTERY_DOWN_CHANGE; + if (allow_change > 0) { + allow_capacity = cw_bat->capacity - allow_change; + if (cw_capacity >= allow_capacity) { + jump_flag = 0; + } else { + cw_capacity = + (allow_capacity <= + 100) ? allow_capacity : 100; + } + } else if (cw_capacity <= cw_bat->capacity) { + cw_capacity = cw_bat->capacity; + } + } + + /* avoid battery level jump to 0% at a moment from more than 2% */ + if (cw_capacity == 0 && cw_bat->capacity > 1) { + allow_change = + ((new_run_time - + cw_bat->run_time_capacity_change) / + BATTERY_DOWN_MIN_CHANGE_RUN); + allow_change += + ((new_sleep_time - + cw_bat->sleep_time_capacity_change) / + BATTERY_DOWN_MIN_CHANGE_SLEEP); + + allow_capacity = cw_bat->capacity - allow_change; + cw_capacity = + (allow_capacity >= + cw_capacity) ? allow_capacity : cw_capacity; + dev_info(&cw_bat->client->dev, "report GGIC POR happened"); + reset_val = MODE_SLEEP; + ret = cw_write(cw_bat->client, REG_MODE, &reset_val); + if (ret < 0) + return ret; + reset_val = MODE_NORMAL; + msleep(10); + ret = cw_write(cw_bat->client, REG_MODE, &reset_val); + if (ret < 0) + return ret; + dev_info(&cw_bat->client->dev, "report battery capacity error"); + ret = cw_update_config_info(cw_bat); + if (ret) + return ret; + dev_info(&cw_bat->client->dev, + "report battery capacity jump 0 "); + } +#if 1 + if (cw_bat->charger_mode > 0 && cw_capacity == 0) { + charge_time = + new_sleep_time + new_run_time - + cw_bat->sleep_time_charge_start - + cw_bat->run_time_charge_start; + if (charge_time > BATTERY_DOWN_MAX_CHANGE_RUN_AC_ONLINE && + if_quickstart == 0) { + reset_val = MODE_SLEEP; + ret = cw_write(cw_bat->client, REG_MODE, &reset_val); + if (ret < 0) + return ret; + reset_val = MODE_NORMAL; + msleep(10); + ret = cw_write(cw_bat->client, REG_MODE, &reset_val); + if (ret < 0) + return ret; + dev_info(&cw_bat->client->dev, + "report battery capacity error"); + ret = cw_update_config_info(cw_bat); + if (ret) + return ret; + dev_info(&cw_bat->client->dev, + "report battery capacity still 0 if in changing"); + if_quickstart = 1; + } + } else if (if_quickstart == 1 && cw_bat->charger_mode == 0) { + if_quickstart = 0; + } #endif #ifdef SYSTEM_SHUTDOWN_VOLTAGE - if ((cw_bat->charger_mode == 0) && (cw_capacity <= 10) && (cw_bat->voltage <= SYSTEM_SHUTDOWN_VOLTAGE)){ - if (if_quickstart == 10){ - cw_quickstart(cw_bat); - if_quickstart = 12; - cw_capacity = 0; - } else if (if_quickstart <= 10) - if_quickstart =if_quickstart+2; - dev_info(&cw_bat->client->dev, "the cw201x voltage is less than SYSTEM_SHUTDOWN_VOLTAGE !!!!!!!, funciton: %s, line: %d\n", __func__, __LINE__); - } else if ((cw_bat->charger_mode > 0)&& (if_quickstart <= 12)) { - if_quickstart = 0; - } + if (cw_bat->charger_mode == 0 && cw_capacity <= 10 && + cw_bat->voltage <= SYSTEM_SHUTDOWN_VOLTAGE) { + if (if_quickstart == 10) { + cw_quickstart(cw_bat); + if_quickstart = 12; + cw_capacity = 0; + } else if (if_quickstart <= 10) { + if_quickstart = if_quickstart + 2; + } + dev_info(&cw_bat->client->dev, + "voltage is less than shutdown voltage\n"); + } else if ((cw_bat->charger_mode > 0) && (if_quickstart <= 12)) { + if_quickstart = 0; + } #endif - return cw_capacity; + return cw_capacity; } static int cw_get_vol(struct cw_battery *cw_bat) { - int ret; - u8 reg_val[2]; - u16 value16, value16_1, value16_2, value16_3; - int voltage; - - ret = cw_read_word(cw_bat->client, REG_VCELL, reg_val); - if (ret < 0) - return ret; - value16 = (reg_val[0] << 8) + reg_val[1]; - - ret = cw_read_word(cw_bat->client, REG_VCELL, reg_val); - if (ret < 0) - return ret; - value16_1 = (reg_val[0] << 8) + reg_val[1]; - - ret = cw_read_word(cw_bat->client, REG_VCELL, reg_val); - if (ret < 0) - return ret; - value16_2 = (reg_val[0] << 8) + reg_val[1]; - - - if(value16 > value16_1) - { - value16_3 = value16; - value16 = value16_1; - value16_1 = value16_3; - } - - if(value16_1 > value16_2) - { - value16_3 =value16_1; - value16_1 =value16_2; - value16_2 =value16_3; - } - - if(value16 >value16_1) - { - value16_3 =value16; - value16 =value16_1; - value16_1 =value16_3; - } - - voltage = value16_1 * 305; - - dev_dbg(&cw_bat->client->dev, "the cw201x voltage=%d,reg_val=%x %x\n",voltage,reg_val[0],reg_val[1]); - return voltage; + int ret; + u8 reg_val[2]; + u16 value16, value16_1, value16_2, value16_3; + int voltage; + + ret = cw_read_word(cw_bat->client, REG_VCELL, reg_val); + if (ret < 0) + return ret; + value16 = (reg_val[0] << 8) + reg_val[1]; + + ret = cw_read_word(cw_bat->client, REG_VCELL, reg_val); + if (ret < 0) + return ret; + value16_1 = (reg_val[0] << 8) + reg_val[1]; + + ret = cw_read_word(cw_bat->client, REG_VCELL, reg_val); + if (ret < 0) + return ret; + value16_2 = (reg_val[0] << 8) + reg_val[1]; + + if (value16 > value16_1) { + value16_3 = value16; + value16 = value16_1; + value16_1 = value16_3; + } + + if (value16_1 > value16_2) { + value16_3 = value16_1; + value16_1 = value16_2; + value16_2 = value16_3; + } + + if (value16 > value16_1) { + value16_3 = value16; + value16 = value16_1; + value16_1 = value16_3; + } + + voltage = value16_1 * 305; + + dev_dbg(&cw_bat->client->dev, "the cw201x voltage=%d,reg_val=%x %x\n", + voltage, reg_val[0], reg_val[1]); + return voltage; } #ifdef BAT_LOW_INTERRUPT static int cw_get_alt(struct cw_battery *cw_bat) { - int ret = 0; - u8 reg_val; - u8 value8 = 0; - int alrt; - - ret = cw_read(cw_bat->client, REG_RRT_ALERT, ®_val); - if (ret < 0) - return ret; - value8 = reg_val; - alrt = value8 >>7; - - //dev_info(&cw_bat->client->dev, "read RRT %d%%. value16 0x%x\n", alrt, value16); - value8 = value8&0x7f; - reg_val = value8; - ret = cw_write(cw_bat->client, REG_RRT_ALERT, ®_val); - if(ret < 0) { - dev_err(&cw_bat->client->dev, "Error clear ALRT\n"); - return ret; - } - - return alrt; + int ret = 0; + u8 reg_val; + u8 value8 = 0; + int alrt; + + ret = cw_read(cw_bat->client, REG_RRT_ALERT, ®_val); + if (ret < 0) + return ret; + value8 = reg_val; + alrt = value8 >> 7; + + value8 = value8 & 0x7f; + reg_val = value8; + ret = cw_write(cw_bat->client, REG_RRT_ALERT, ®_val); + if (ret < 0) { + dev_err(&cw_bat->client->dev, "Error clear ALRT\n"); + return ret; + } + + return alrt; } #endif - static int cw_get_time_to_empty(struct cw_battery *cw_bat) { - int ret; - u8 reg_val; - u16 value16; + int ret; + u8 reg_val; + u16 value16; - ret = cw_read(cw_bat->client, REG_RRT_ALERT, ®_val); - if (ret < 0) - return ret; + ret = cw_read(cw_bat->client, REG_RRT_ALERT, ®_val); + if (ret < 0) + return ret; - value16 = reg_val; + value16 = reg_val; - ret = cw_read(cw_bat->client, REG_RRT_ALERT + 1, ®_val); - if (ret < 0) - return ret; + ret = cw_read(cw_bat->client, REG_RRT_ALERT + 1, ®_val); + if (ret < 0) + return ret; - value16 = ((value16 << 8) + reg_val) & 0x1fff; - return value16; + value16 = ((value16 << 8) + reg_val) & 0x1fff; + return value16; } static void rk_bat_update_capacity(struct cw_battery *cw_bat) { - int cw_capacity; - - cw_capacity = cw_get_capacity(cw_bat); - if ((cw_capacity >= 0) && (cw_capacity <= 100) && (cw_bat->capacity != cw_capacity)) { - cw_bat->capacity = cw_capacity; - cw_bat->bat_change = 1; - cw_update_time_member_capacity_change(cw_bat); - - if (cw_bat->capacity == 0) - dev_info(&cw_bat->client->dev, "report battery capacity 0 and will shutdown if no changing"); - - } + int cw_capacity; + + cw_capacity = cw_get_capacity(cw_bat); + if ((cw_capacity >= 0) && (cw_capacity <= 100) && + (cw_bat->capacity != cw_capacity)) { + cw_bat->capacity = cw_capacity; + cw_bat->bat_change = 1; + cw_update_time_member_capacity_change(cw_bat); + + if (cw_bat->capacity == 0) + dev_info(&cw_bat->client->dev, + "report battery capacity 0 and will shutdown if no changing"); + } } - - static void rk_bat_update_vol(struct cw_battery *cw_bat) { - int ret; - ret = cw_get_vol(cw_bat); - if ((ret >= 0) && (cw_bat->voltage != ret)) { - cw_bat->voltage = ret; - // cw_bat->bat_change = 1; - } + int ret; + + ret = cw_get_vol(cw_bat); + if ((ret >= 0) && (cw_bat->voltage != ret)) + cw_bat->voltage = ret; } static void rk_bat_update_status(struct cw_battery *cw_bat) { - int status; - - - if (cw_bat->charger_mode > 0) { - if (cw_bat->capacity >= 100) - status=POWER_SUPPLY_STATUS_FULL; - else - status=POWER_SUPPLY_STATUS_CHARGING; - } else { - status = POWER_SUPPLY_STATUS_NOT_CHARGING; - } - - if (cw_bat->status != status) { - cw_bat->status = status; - cw_bat->bat_change = 1; - - } + int status; + + if (cw_bat->charger_mode > 0) { + if (cw_bat->capacity >= 100) + status = POWER_SUPPLY_STATUS_FULL; + else + status = POWER_SUPPLY_STATUS_CHARGING; + } else { + status = POWER_SUPPLY_STATUS_NOT_CHARGING; + } + + if (cw_bat->status != status) { + cw_bat->status = status; + cw_bat->bat_change = 1; + } } static void rk_bat_update_time_to_empty(struct cw_battery *cw_bat) { - int ret; - ret = cw_get_time_to_empty(cw_bat); - if ((ret >= 0) && (cw_bat->time_to_empty != ret)) { - cw_bat->time_to_empty = ret; - // cw_bat->bat_change = 1; - } - + int ret; + + ret = cw_get_time_to_empty(cw_bat); + if ((ret >= 0) && (cw_bat->time_to_empty != ret)) + cw_bat->time_to_empty = ret; } static int rk_ac_update_online(struct cw_battery *cw_bat) { - int ret = 0; - - if(!gpio_is_valid(cw_bat->plat_data.dc_det_pin)) { - cw_bat->dc_online = 0; - printk("%s cw2015 dc charger but without dc_det_pin,maybe error\n",__func__); - return 0; - } - - if (gpio_get_value(cw_bat->plat_data.dc_det_pin) == cw_bat->plat_data.dc_det_level) { - if (cw_bat->dc_online != 1) { - cw_update_time_member_charge_start(cw_bat); - cw_bat->dc_online = 1; - if (cw_bat->charger_mode != AC_CHARGER_MODE) - cw_bat->charger_mode = AC_CHARGER_MODE; - - ret = 1; - } - } else { - if (cw_bat->dc_online != 0) { - cw_update_time_member_charge_start(cw_bat); - cw_bat->dc_online = 0; - if (cw_bat->usb_online == 0) - cw_bat->charger_mode = 0; - ret = 1; - } - } - return ret; + int ret = 0; + + if (!gpio_is_valid(cw_bat->plat_data.dc_det_pin)) { + cw_bat->dc_online = 0; + pr_info("%s dc charger without dc_det_pin\n", __func__); + return 0; + } + + if (gpio_get_value(cw_bat->plat_data.dc_det_pin) == + cw_bat->plat_data.dc_det_level) { + if (cw_bat->dc_online != 1) { + cw_update_time_member_charge_start(cw_bat); + cw_bat->dc_online = 1; + if (cw_bat->charger_mode != AC_CHARGER_MODE) + cw_bat->charger_mode = AC_CHARGER_MODE; + + ret = 1; + } + } else { + if (cw_bat->dc_online != 0) { + cw_update_time_member_charge_start(cw_bat); + cw_bat->dc_online = 0; + if (cw_bat->usb_online == 0) + cw_bat->charger_mode = 0; + ret = 1; + } + } + return ret; } static int get_usb_charge_state(struct cw_battery *cw_bat) { - int charge_time; - int time_from_boot; - struct timespec ts; - - int gadget_status = get_gadget_connect_flag(); - int usb_status = dwc_vbus_status(); - - get_monotonic_boottime(&ts); - time_from_boot = ts.tv_sec; - - if (cw_bat->charger_init_mode) { - if (usb_status == 1 || usb_status == 2) { - cw_bat->charger_init_mode = 0; - } else if (time_from_boot < 8) { - usb_status = cw_bat->charger_init_mode; - } else if (strstr(saved_command_line,"charger")) { - cw_bat->charger_init_mode = dwc_otg_check_dpdm(); - usb_status = cw_bat->charger_init_mode; - } - } -#ifdef NO_STANDARD_AC_BIG_CHARGE_MODE - if (cw_bat->usb_online == 1) { - - charge_time = time_from_boot - cw_bat->sleep_time_charge_start - cw_bat->run_time_charge_start; - if (charge_time > 3) { - if (gadget_status == 0 && dwc_vbus_status() == 1) { - usb_status = 2; - } - } - } + int charge_time; + int time_from_boot; + struct timespec ts; + + int gadget_status = get_gadget_connect_flag(); + int usb_status = dwc_vbus_status(); + + get_monotonic_boottime(&ts); + time_from_boot = ts.tv_sec; + + if (cw_bat->charger_init_mode) { + if (usb_status == 1 || usb_status == 2) { + cw_bat->charger_init_mode = 0; + } else if (time_from_boot < 8) { + usb_status = cw_bat->charger_init_mode; + } else if (strstr(saved_command_line, "charger")) { + cw_bat->charger_init_mode = dwc_otg_check_dpdm(); + usb_status = cw_bat->charger_init_mode; + } + } +#ifdef NO_STANDARD_AC_BIG_CHARGE_MODE + if (cw_bat->usb_online == 1) { + charge_time = + time_from_boot - cw_bat->sleep_time_charge_start - + cw_bat->run_time_charge_start; + if (charge_time > 3) { + if (gadget_status == 0 && dwc_vbus_status() == 1) + usb_status = 2; + } + } #endif - dev_dbg(&cw_bat->client->dev, "%s usb_status=[%d],cw_bat->charger_mode=[%d],cw_bat->gadget_status=[%d], cw_bat->charger_init_mode = [%d]\n",__func__,usb_status,cw_bat->charger_mode,gadget_status, cw_bat->charger_init_mode); + dev_dbg(&cw_bat->client->dev, + "%s usb_status=[%d],cw_bat->charger_mode=[%d],cw_bat->gadget_status=[%d], cw_bat->charger_init_mode = [%d]\n", + __func__, usb_status, cw_bat->charger_mode, gadget_status, + cw_bat->charger_init_mode); - return usb_status; + return usb_status; } static int rk_usb_update_online(struct cw_battery *cw_bat) { - int ret = 0; - int usb_status = 0; - - - usb_status = get_usb_charge_state(cw_bat); - if (usb_status == 2) { - if (cw_bat->charger_mode != AC_CHARGER_MODE) { - cw_bat->charger_mode = AC_CHARGER_MODE; - ret = 1; - } - if (gpio_is_valid(cw_bat->plat_data.chg_mode_sel_pin)) { - if (gpio_get_value (cw_bat->plat_data.chg_mode_sel_pin) != cw_bat->plat_data.chg_mode_sel_level) - gpio_direction_output(cw_bat->plat_data.chg_mode_sel_pin, (cw_bat->plat_data.chg_mode_sel_level==CW2015_GPIO_LOW) ? CW2015_GPIO_LOW : CW2015_GPIO_HIGH); - } - - if (cw_bat->usb_online != 1) { - cw_bat->usb_online = 1; - cw_update_time_member_charge_start(cw_bat); - } - - } else if (usb_status == 1) { - if ((cw_bat->charger_mode != USB_CHARGER_MODE) && (cw_bat->dc_online == 0)) { - cw_bat->charger_mode = USB_CHARGER_MODE; - ret = 1; - } - - if (gpio_is_valid(cw_bat->plat_data.chg_mode_sel_pin)) { - if (gpio_get_value (cw_bat->plat_data.chg_mode_sel_pin) == cw_bat->plat_data.chg_mode_sel_level) - gpio_direction_output(cw_bat->plat_data.chg_mode_sel_pin, (cw_bat->plat_data.chg_mode_sel_level==CW2015_GPIO_LOW) ? CW2015_GPIO_HIGH : CW2015_GPIO_LOW); - } - if (cw_bat->usb_online != 1){ - cw_bat->usb_online = 1; - cw_update_time_member_charge_start(cw_bat); - } - - } else if (usb_status == 0 && cw_bat->usb_online != 0) { - - if (gpio_is_valid(cw_bat->plat_data.chg_mode_sel_pin)) { - if (gpio_get_value (cw_bat->plat_data.chg_mode_sel_pin == cw_bat->plat_data.chg_mode_sel_level)) - gpio_direction_output(cw_bat->plat_data.chg_mode_sel_pin, (cw_bat->plat_data.chg_mode_sel_level==CW2015_GPIO_LOW) ? CW2015_GPIO_HIGH : CW2015_GPIO_LOW); - } - - if (cw_bat->dc_online == 0) - cw_bat->charger_mode = 0; - - cw_update_time_member_charge_start(cw_bat); - cw_bat->usb_online = 0; - ret = 1; - } - - return ret; + int gpio; + int value; + int ret = 0; + int usb_status = 0; + + gpio = cw_bat->plat_data.chg_mode_sel_pin; + value = cw_bat->plat_data.chg_mode_sel_level; + usb_status = get_usb_charge_state(cw_bat); + if (usb_status == 2) { + if (cw_bat->charger_mode != AC_CHARGER_MODE) { + cw_bat->charger_mode = AC_CHARGER_MODE; + ret = 1; + } + if (gpio_is_valid(gpio)) { + if (gpio_get_value(gpio) != value) + gpio_direction_output(gpio, value); + } + + if (cw_bat->usb_online != 1) { + cw_bat->usb_online = 1; + cw_update_time_member_charge_start(cw_bat); + } + + } else if (usb_status == 1) { + if (cw_bat->charger_mode != USB_CHARGER_MODE && + cw_bat->dc_online == 0) { + cw_bat->charger_mode = USB_CHARGER_MODE; + ret = 1; + } + + if (gpio_is_valid(gpio)) { + if (gpio_get_value(gpio) == value) + gpio_direction_output(gpio, !value); + } + if (cw_bat->usb_online != 1) { + cw_bat->usb_online = 1; + cw_update_time_member_charge_start(cw_bat); + } + + } else if (usb_status == 0 && cw_bat->usb_online != 0) { + if (gpio_is_valid(gpio)) { + if (gpio_get_value(gpio == value)) + gpio_direction_output(gpio, !value); + } + + if (cw_bat->dc_online == 0) + cw_bat->charger_mode = 0; + + cw_update_time_member_charge_start(cw_bat); + cw_bat->usb_online = 0; + ret = 1; + } + + return ret; } static void cw_bat_work(struct work_struct *work) { - struct delayed_work *delay_work; - struct cw_battery *cw_bat; - int ret; - - delay_work = container_of(work, struct delayed_work, work); - cw_bat = container_of(delay_work, struct cw_battery, battery_delay_work); - - if (cw_bat->plat_data.is_dc_charge == 1) { - ret = rk_ac_update_online(cw_bat); - if (ret == 1) { - power_supply_changed(&cw_bat->rk_ac); - } - } + struct delayed_work *delay_work; + struct cw_battery *cw_bat; + int ret; - if (cw_bat->plat_data.is_usb_charge == 1) { - ret = rk_usb_update_online(cw_bat); - if (ret == 1) { - power_supply_changed(&cw_bat->rk_usb); - power_supply_changed(&cw_bat->rk_ac); - } - } + delay_work = container_of(work, struct delayed_work, work); + cw_bat = + container_of(delay_work, struct cw_battery, battery_delay_work); + + if (cw_bat->plat_data.is_dc_charge == 1) { + ret = rk_ac_update_online(cw_bat); + if (ret == 1) + power_supply_changed(&cw_bat->rk_ac); + } + if (cw_bat->plat_data.is_usb_charge == 1) { + ret = rk_usb_update_online(cw_bat); + if (ret == 1) { + power_supply_changed(&cw_bat->rk_usb); + power_supply_changed(&cw_bat->rk_ac); + } + } - rk_bat_update_status(cw_bat); - rk_bat_update_capacity(cw_bat); - rk_bat_update_vol(cw_bat); - rk_bat_update_time_to_empty(cw_bat); + rk_bat_update_status(cw_bat); + rk_bat_update_capacity(cw_bat); + rk_bat_update_vol(cw_bat); + rk_bat_update_time_to_empty(cw_bat); - if (cw_bat->bat_change) { - power_supply_changed(&cw_bat->rk_bat); - cw_bat->bat_change = 0; - } + if (cw_bat->bat_change) { + power_supply_changed(&cw_bat->rk_bat); + cw_bat->bat_change = 0; + } - queue_delayed_work(cw_bat->battery_workqueue, &cw_bat->battery_delay_work, msecs_to_jiffies(1000)); + queue_delayed_work(cw_bat->battery_workqueue, + &cw_bat->battery_delay_work, msecs_to_jiffies(1000)); - dev_dbg(&cw_bat->client->dev, "cw_bat->bat_change = %d, cw_bat->time_to_empty = %d, cw_bat->capacity = %d\n",\ - cw_bat->bat_change, cw_bat->time_to_empty, cw_bat->capacity); + dev_dbg(&cw_bat->client->dev, + "cw_bat->bat_change = %d, cw_bat->time_to_empty = %d, cw_bat->capacity = %d\n", + cw_bat->bat_change, cw_bat->time_to_empty, cw_bat->capacity); - dev_dbg(&cw_bat->client->dev, "cw_bat->voltage = %d, cw_bat->dc_online = %d, cw_bat->usb_online = %d\n",\ - cw_bat->voltage, cw_bat->dc_online, cw_bat->usb_online); + dev_dbg(&cw_bat->client->dev, + "cw_bat->voltage = %d, cw_bat->dc_online = %d, cw_bat->usb_online = %d\n", + cw_bat->voltage, cw_bat->dc_online, cw_bat->usb_online); } -static int rk_usb_get_property (struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) +static int rk_usb_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) { - int ret = 0; - struct cw_battery *cw_bat; - - cw_bat = container_of(psy, struct cw_battery, rk_usb); - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - // val->intval = cw_bat->usb_online; - val->intval = (cw_bat->charger_mode == USB_CHARGER_MODE); - break; - default: - break; - } - return ret; + int ret = 0; + struct cw_battery *cw_bat; + + cw_bat = container_of(psy, struct cw_battery, rk_usb); + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval = (cw_bat->charger_mode == USB_CHARGER_MODE); + break; + default: + break; + } + return ret; } static enum power_supply_property rk_usb_properties[] = { - POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_ONLINE, }; - -static int rk_ac_get_property (struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) +static int rk_ac_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) { - int ret = 0; - struct cw_battery *cw_bat; - - cw_bat = container_of(psy, struct cw_battery, rk_ac); - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - // val->intval = cw_bat->dc_online; - val->intval = (cw_bat->charger_mode == AC_CHARGER_MODE); - break; - default: - break; - } - return ret; + int ret = 0; + struct cw_battery *cw_bat; + + cw_bat = container_of(psy, struct cw_battery, rk_ac); + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval = (cw_bat->charger_mode == AC_CHARGER_MODE); + break; + default: + break; + } + return ret; } static enum power_supply_property rk_ac_properties[] = { - POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_ONLINE, }; static int rk_battery_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) + enum power_supply_property psp, + union power_supply_propval *val) { - int ret = 0; - struct cw_battery *cw_bat; - - cw_bat = container_of(psy, struct cw_battery, rk_bat); - switch (psp) { - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = cw_bat->capacity; - break; - case POWER_SUPPLY_PROP_STATUS: - val->intval = cw_bat->status; - break; - - case POWER_SUPPLY_PROP_HEALTH: - val->intval= POWER_SUPPLY_HEALTH_GOOD; - break; - case POWER_SUPPLY_PROP_PRESENT: - val->intval = cw_bat->voltage <= 0 ? 0 : 1; - break; - - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = cw_bat->voltage; - break; - - case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: - val->intval = cw_bat->time_to_empty; - break; - - case POWER_SUPPLY_PROP_TECHNOLOGY: - val->intval = POWER_SUPPLY_TECHNOLOGY_LION; - break; - - default: - break; - } - return ret; + int ret = 0; + struct cw_battery *cw_bat; + + cw_bat = container_of(psy, struct cw_battery, rk_bat); + switch (psp) { + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = cw_bat->capacity; + break; + case POWER_SUPPLY_PROP_STATUS: + val->intval = cw_bat->status; + break; + + case POWER_SUPPLY_PROP_HEALTH: + val->intval = POWER_SUPPLY_HEALTH_GOOD; + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = cw_bat->voltage <= 0 ? 0 : 1; + break; + + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = cw_bat->voltage; + break; + + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: + val->intval = cw_bat->time_to_empty; + break; + + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; + break; + + default: + break; + } + return ret; } static enum power_supply_property rk_battery_properties[] = { - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, - POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, + POWER_SUPPLY_PROP_TECHNOLOGY, }; static int cw_bat_gpio_init(struct cw_battery *cw_bat) { + int ret; - int ret; - - if (gpio_is_valid(cw_bat->plat_data.dc_det_pin)) { - ret = gpio_request(cw_bat->plat_data.dc_det_pin, NULL); - if (ret) { - dev_err(&cw_bat->client->dev, "failed to request dc_det_pin gpio\n"); - goto request_dc_det_pin_fail; - } - ret = gpio_direction_input(cw_bat->plat_data.dc_det_pin); - if (ret) { - dev_err(&cw_bat->client->dev, "failed to set dc_det_pin input\n"); - goto request_bat_low_pin_fail; - } - } - if (gpio_is_valid(cw_bat->plat_data.bat_low_pin)) { - ret = gpio_request(cw_bat->plat_data.bat_low_pin, NULL); - if (ret) { - dev_err(&cw_bat->client->dev, "failed to request bat_low_pin gpio\n"); - goto request_bat_low_pin_fail; - } - - ret = gpio_direction_input(cw_bat->plat_data.bat_low_pin); - if (ret) { - dev_err(&cw_bat->client->dev, "failed to set bat_low_pin input\n"); - goto request_bat_low_pin_fail; - } - } - if (gpio_is_valid(cw_bat->plat_data.chg_ok_pin)) { - ret = gpio_request(cw_bat->plat_data.chg_ok_pin, NULL); - if (ret) { - dev_err(&cw_bat->client->dev, "failed to request chg_ok_pin gpio\n"); - goto request_chg_ok_pin_fail; - } - - ret = gpio_direction_input(cw_bat->plat_data.chg_ok_pin); - if (ret) { - dev_err(&cw_bat->client->dev, "failed to set chg_ok_pin input\n"); - gpio_free(cw_bat->plat_data.chg_ok_pin); - goto request_chg_ok_pin_fail; - } - } - - if ((gpio_is_valid(cw_bat->plat_data.chg_mode_sel_pin))) { - ret = gpio_request(cw_bat->plat_data.chg_mode_sel_pin, NULL); - if (ret) { - dev_err(&cw_bat->client->dev, "failed to request chg_mode_sel_pin gpio\n"); - goto request_chg_mode_sel_pin_fail; - } - ret = gpio_direction_output(cw_bat->plat_data.chg_mode_sel_pin, (cw_bat->plat_data.chg_mode_sel_level==CW2015_GPIO_LOW) ? CW2015_GPIO_HIGH : CW2015_GPIO_LOW); - if (ret) { - dev_err(&cw_bat->client->dev, "failed to set chg_mode_sel_pin output\n"); - gpio_free(cw_bat->plat_data.chg_mode_sel_pin); - goto request_chg_mode_sel_pin_fail; - } - } - - return 0; + if (gpio_is_valid(cw_bat->plat_data.dc_det_pin)) { + ret = gpio_request(cw_bat->plat_data.dc_det_pin, NULL); + if (ret) { + dev_err(&cw_bat->client->dev, + "failed to request dc_det_pin gpio\n"); + goto request_dc_det_pin_fail; + } + ret = gpio_direction_input(cw_bat->plat_data.dc_det_pin); + if (ret) { + dev_err(&cw_bat->client->dev, + "failed to set dc_det_pin input\n"); + goto request_bat_low_pin_fail; + } + } + if (gpio_is_valid(cw_bat->plat_data.bat_low_pin)) { + ret = gpio_request(cw_bat->plat_data.bat_low_pin, NULL); + if (ret) { + dev_err(&cw_bat->client->dev, + "failed to request bat_low_pin gpio\n"); + goto request_bat_low_pin_fail; + } + + ret = gpio_direction_input(cw_bat->plat_data.bat_low_pin); + if (ret) { + dev_err(&cw_bat->client->dev, + "failed to set bat_low_pin input\n"); + goto request_bat_low_pin_fail; + } + } + if (gpio_is_valid(cw_bat->plat_data.chg_ok_pin)) { + ret = gpio_request(cw_bat->plat_data.chg_ok_pin, NULL); + if (ret) { + dev_err(&cw_bat->client->dev, + "failed to request chg_ok_pin gpio\n"); + goto request_chg_ok_pin_fail; + } + + ret = gpio_direction_input(cw_bat->plat_data.chg_ok_pin); + if (ret) { + dev_err(&cw_bat->client->dev, + "failed to set chg_ok_pin input\n"); + gpio_free(cw_bat->plat_data.chg_ok_pin); + goto request_chg_ok_pin_fail; + } + } + + if ((gpio_is_valid(cw_bat->plat_data.chg_mode_sel_pin))) { + ret = gpio_request(cw_bat->plat_data.chg_mode_sel_pin, NULL); + if (ret) { + dev_err(&cw_bat->client->dev, + "failed to request chg_mode_sel_pin gpio\n"); + goto request_chg_mode_sel_pin_fail; + } + ret = + gpio_direction_output(cw_bat->plat_data.chg_mode_sel_pin, + (cw_bat->plat_data. + chg_mode_sel_level == + CW2015_GPIO_LOW) ? CW2015_GPIO_HIGH : + CW2015_GPIO_LOW); + if (ret) { + dev_err(&cw_bat->client->dev, + "failed to set chg_mode_sel_pin output\n"); + gpio_free(cw_bat->plat_data.chg_mode_sel_pin); + goto request_chg_mode_sel_pin_fail; + } + } + + return 0; request_chg_mode_sel_pin_fail: - gpio_free(cw_bat->plat_data.chg_mode_sel_pin); - + gpio_free(cw_bat->plat_data.chg_mode_sel_pin); request_chg_ok_pin_fail: - if (gpio_is_valid(cw_bat->plat_data.bat_low_pin)) - gpio_free(cw_bat->plat_data.bat_low_pin); - + if (gpio_is_valid(cw_bat->plat_data.bat_low_pin)) + gpio_free(cw_bat->plat_data.bat_low_pin); request_bat_low_pin_fail: - if (gpio_is_valid(cw_bat->plat_data.dc_det_pin)) - gpio_free(cw_bat->plat_data.dc_det_pin); - + if (gpio_is_valid(cw_bat->plat_data.dc_det_pin)) + gpio_free(cw_bat->plat_data.dc_det_pin); request_dc_det_pin_fail: - return ret; + return ret; } - static void dc_detect_do_wakeup(struct work_struct *work) { - int ret; - int irq; - unsigned int type; - - struct delayed_work *delay_work; - struct cw_battery *cw_bat; - - delay_work = container_of(work, struct delayed_work, work); - cw_bat = container_of(delay_work, struct cw_battery, dc_wakeup_work); - - rk_send_wakeup_key(); - - /* this assume if usb insert or extract dc_det pin is change */ -#if 0 - if(cw_bat->charger_init_mode) - cw_bat->charger_init_mode=0; -#endif - - irq = gpio_to_irq(cw_bat->plat_data.dc_det_pin); - type = gpio_get_value(cw_bat->plat_data.dc_det_pin) ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING; - ret = irq_set_irq_type(irq, type); - if (ret < 0) { - pr_err("%s: irq_set_irq_type(%d, %d) failed\n", __func__, irq, type); - } - enable_irq(irq); + int ret; + int irq; + unsigned int type; + + struct delayed_work *delay_work; + struct cw_battery *cw_bat; + + delay_work = container_of(work, struct delayed_work, work); + cw_bat = container_of(delay_work, struct cw_battery, dc_wakeup_work); + + rk_send_wakeup_key(); + + irq = gpio_to_irq(cw_bat->plat_data.dc_det_pin); + type = + gpio_get_value(cw_bat->plat_data. + dc_det_pin) ? IRQ_TYPE_EDGE_FALLING : + IRQ_TYPE_EDGE_RISING; + ret = irq_set_irq_type(irq, type); + if (ret < 0) { + pr_err("%s: irq_set_irq_type(%d, %d) failed\n", __func__, irq, + type); + } + enable_irq(irq); } static irqreturn_t dc_detect_irq_handler(int irq, void *dev_id) { - struct cw_battery *cw_bat = dev_id; - disable_irq_nosync(irq); // for irq debounce - queue_delayed_work(cw_bat->battery_workqueue, &cw_bat->dc_wakeup_work, msecs_to_jiffies(20)); - return IRQ_HANDLED; + struct cw_battery *cw_bat = dev_id; + + /* for irq debounce */ + disable_irq_nosync(irq); + queue_delayed_work(cw_bat->battery_workqueue, &cw_bat->dc_wakeup_work, + msecs_to_jiffies(20)); + return IRQ_HANDLED; } #ifdef BAT_LOW_INTERRUPT @@ -1130,28 +1092,29 @@ static irqreturn_t dc_detect_irq_handler(int irq, void *dev_id) static void bat_low_detect_do_wakeup(struct work_struct *work) { - struct delayed_work *delay_work; - struct cw_battery *cw_bat; - - delay_work = container_of(work, struct delayed_work, work); - cw_bat = container_of(delay_work, struct cw_battery, bat_low_wakeup_work); - dev_info(&cw_bat->client->dev, "func: %s-------\n", __func__); - cw_get_alt(cw_bat); - //enable_irq(irq); + struct delayed_work *delay_work; + struct cw_battery *cw_bat; + + delay_work = container_of(work, struct delayed_work, work); + cw_bat = + container_of(delay_work, struct cw_battery, bat_low_wakeup_work); + dev_info(&cw_bat->client->dev, "func: %s-------\n", __func__); + cw_get_alt(cw_bat); } static irqreturn_t bat_low_detect_irq_handler(int irq, void *dev_id) { - struct cw_battery *cw_bat = dev_id; - // disable_irq_nosync(irq); // for irq debounce - queue_delayed_work(cw_bat->battery_workqueue, &cw_bat->bat_low_wakeup_work, msecs_to_jiffies(20)); - return IRQ_HANDLED; + struct cw_battery *cw_bat = dev_id; + + queue_delayed_work(cw_bat->battery_workqueue, + &cw_bat->bat_low_wakeup_work, msecs_to_jiffies(20)); + return IRQ_HANDLED; } #endif #ifdef CONFIG_OF static int cw2015_parse_dt(struct device *dev, - struct cw_bat_platform_data *data) + struct cw_bat_platform_data *data) { struct device_node *node = dev->of_node; enum of_gpio_flags flags; @@ -1174,136 +1137,137 @@ static int cw2015_parse_dt(struct device *dev, if (length > 0) { size_t size = sizeof(*data->cw_bat_config_info) * length; + data->cw_bat_config_info = devm_kzalloc(dev, size, GFP_KERNEL); if (!data->cw_bat_config_info) return -ENOMEM; ret = of_property_read_u32_array(node, "bat_config_info", - data->cw_bat_config_info, - length); + data->cw_bat_config_info, + length); if (ret < 0) return ret; } data->dc_det_pin = of_get_named_gpio_flags(node, "dc_det_gpio", 0, - &flags); + &flags); if (data->dc_det_pin == -EPROBE_DEFER) - printk("%s dc_det_gpio error\n",__func__); + pr_info("%s dc_det_gpio error\n", __func__); if (gpio_is_valid(data->dc_det_pin)) - data->dc_det_level = (flags & OF_GPIO_ACTIVE_LOW)? CW2015_GPIO_LOW:CW2015_GPIO_HIGH; - + data->dc_det_level = + (flags & OF_GPIO_ACTIVE_LOW) ? CW2015_GPIO_LOW : + CW2015_GPIO_HIGH; data->bat_low_pin = of_get_named_gpio_flags(node, "bat_low_gpio", 0, &flags); if (data->bat_low_pin == -EPROBE_DEFER) - printk("%s bat_low_gpio error\n",__func__); + pr_info("%s bat_low_gpio error\n", __func__); if (gpio_is_valid(data->bat_low_pin)) - data->bat_low_level = (flags & OF_GPIO_ACTIVE_LOW)? CW2015_GPIO_LOW:CW2015_GPIO_HIGH; - + data->bat_low_level = + (flags & OF_GPIO_ACTIVE_LOW) ? CW2015_GPIO_LOW : + CW2015_GPIO_HIGH; data->chg_ok_pin = of_get_named_gpio_flags(node, "chg_ok_gpio", 0, - &flags); + &flags); if (data->chg_ok_pin == -EPROBE_DEFER) - printk("%s chg_ok_gpio error\n",__func__); + pr_info("%s chg_ok_gpio error\n", __func__); if (gpio_is_valid(data->chg_ok_pin)) - data->chg_ok_level = (flags & OF_GPIO_ACTIVE_LOW)? CW2015_GPIO_LOW:CW2015_GPIO_HIGH; + data->chg_ok_level = + (flags & OF_GPIO_ACTIVE_LOW) ? CW2015_GPIO_LOW : + CW2015_GPIO_HIGH; - data->chg_mode_sel_pin = of_get_named_gpio_flags(node, "chg_mode_sel_gpio", 0, - &flags); + data->chg_mode_sel_pin = + of_get_named_gpio_flags(node, "chg_mode_sel_gpio", 0, &flags); if (data->chg_mode_sel_pin == -EPROBE_DEFER) - printk("%s chg_mod_sel_gpio error\n",__func__); + pr_info("%s chg_mod_sel_gpio error\n", __func__); if (gpio_is_valid(data->chg_mode_sel_pin)) - data->chg_mode_sel_level = (flags & OF_GPIO_ACTIVE_LOW)? CW2015_GPIO_LOW:CW2015_GPIO_HIGH; - + data->chg_mode_sel_level = + (flags & OF_GPIO_ACTIVE_LOW) ? CW2015_GPIO_LOW : + CW2015_GPIO_HIGH; - ret = of_property_read_u32(node, "is_dc_charge", - &value); - if (ret < 0) - { - printk("%s:hardware unsupport dc charge\n",__func__); + ret = of_property_read_u32(node, "is_dc_charge", &value); + if (ret < 0) { + pr_info("%s:hardware unsupport dc charge\n", __func__); value = 0; } data->is_dc_charge = value; - ret = of_property_read_u32(node, "is_usb_charge", - &value); - if (ret < 0) - { - printk("%s:hardware unsupport usb charge\n",__func__); + ret = of_property_read_u32(node, "is_usb_charge", &value); + if (ret < 0) { + pr_info("%s:hardware unsupport usb charge\n", __func__); value = 0; } data->is_usb_charge = value; - printk("cw201x:support %s %s charger\n", - data->is_dc_charge ? "DC" : "", data->is_usb_charge ? "USB" : ""); + pr_info("cw201x:support %s %s charger\n", + data->is_dc_charge ? "DC" : "", + data->is_usb_charge ? "USB" : ""); return 0; } #else static int cw2015_parse_dt(struct device *dev, - struct cw_bat_platform_data *data) + struct cw_bat_platform_data *data) { return -ENODEV; } #endif -static int cw_bat_probe(struct i2c_client *client, const struct i2c_device_id *id) +static int cw_bat_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct cw_battery *cw_bat; + struct cw_battery *cw_bat; struct cw_bat_platform_data *plat_data = client->dev.platform_data; - int ret; - int irq; - int irq_flags; + int ret; + int irq; + int irq_flags; int level = 0; - cw_bat = devm_kzalloc(&client->dev, sizeof(*cw_bat), GFP_KERNEL); - if (!cw_bat) { - dev_err(&cw_bat->client->dev, "fail to allocate memory for cw2015\n"); - return -ENOMEM; - } - i2c_set_clientdata(client, cw_bat); + cw_bat = devm_kzalloc(&client->dev, sizeof(*cw_bat), GFP_KERNEL); + if (!cw_bat) { + dev_err(&cw_bat->client->dev, + "fail to allocate memory for cw2015\n"); + return -ENOMEM; + } + i2c_set_clientdata(client, cw_bat); if (!plat_data) { ret = cw2015_parse_dt(&client->dev, &(cw_bat->plat_data)); if (ret < 0) { - dev_err(&client->dev, "failed to find cw2015 platform data\n"); + dev_err(&client->dev, + "failed to find cw2015 platform data\n"); goto pdate_fail; } } - cw_bat->client = client; - ret = cw_bat_gpio_init(cw_bat); - if (ret) { - dev_err(&cw_bat->client->dev, "cw_bat_gpio_init error\n"); - return ret; - } - - ret = cw_init(cw_bat); -#if 0 - while ((loop++ < 200) && (ret != 0)) { - ret = cw_init(cw_bat); - } -#endif - if (ret) - { - printk("%s cw_init error\n",__func__); - return ret; + cw_bat->client = client; + ret = cw_bat_gpio_init(cw_bat); + if (ret) { + dev_err(&cw_bat->client->dev, "cw_bat_gpio_init error\n"); + return ret; + } + + ret = cw_init(cw_bat); + if (ret) { + pr_err("%s cw_init error\n", __func__); + return ret; + } + + cw_bat->rk_bat.name = "rk-bat"; + cw_bat->rk_bat.type = POWER_SUPPLY_TYPE_BATTERY; + cw_bat->rk_bat.properties = rk_battery_properties; + cw_bat->rk_bat.num_properties = ARRAY_SIZE(rk_battery_properties); + cw_bat->rk_bat.get_property = rk_battery_get_property; + ret = power_supply_register(&client->dev, &cw_bat->rk_bat); + if (ret < 0) { + dev_err(&cw_bat->client->dev, + "power supply register rk_bat error\n"); + goto rk_bat_register_fail; } - - cw_bat->rk_bat.name = "rk-bat"; - cw_bat->rk_bat.type = POWER_SUPPLY_TYPE_BATTERY; - cw_bat->rk_bat.properties = rk_battery_properties; - cw_bat->rk_bat.num_properties = ARRAY_SIZE(rk_battery_properties); - cw_bat->rk_bat.get_property = rk_battery_get_property; - ret = power_supply_register(&client->dev, &cw_bat->rk_bat); - if(ret < 0) { - dev_err(&cw_bat->client->dev, "power supply register rk_bat error\n"); - goto rk_bat_register_fail; - } cw_bat->rk_ac.name = "rk-ac"; cw_bat->rk_ac.type = POWER_SUPPLY_TYPE_MAINS; @@ -1311,158 +1275,166 @@ static int cw_bat_probe(struct i2c_client *client, const struct i2c_device_id *i cw_bat->rk_ac.num_properties = ARRAY_SIZE(rk_ac_properties); cw_bat->rk_ac.get_property = rk_ac_get_property; ret = power_supply_register(&client->dev, &cw_bat->rk_ac); - if(ret < 0) { - dev_err(&cw_bat->client->dev, "power supply register rk_ac error\n"); - goto rk_ac_register_fail; - } + if (ret < 0) { + dev_err(&cw_bat->client->dev, + "power supply register rk_ac error\n"); + goto rk_ac_register_fail; + } - if (cw_bat->plat_data.is_usb_charge == 1) { + if (cw_bat->plat_data.is_usb_charge == 1) { cw_bat->rk_usb.name = "rk-usb"; cw_bat->rk_usb.type = POWER_SUPPLY_TYPE_USB; cw_bat->rk_usb.properties = rk_usb_properties; cw_bat->rk_usb.num_properties = ARRAY_SIZE(rk_usb_properties); cw_bat->rk_usb.get_property = rk_usb_get_property; ret = power_supply_register(&client->dev, &cw_bat->rk_usb); - if(ret < 0) { - dev_err(&cw_bat->client->dev, "power supply register rk_usb error\n"); - goto rk_usb_register_fail; + if (ret < 0) { + dev_err(&cw_bat->client->dev, + "power supply register rk_usb error\n"); + goto rk_usb_register_fail; } - cw_bat->charger_init_mode = dwc_otg_check_dpdm(); - printk("%s cw2015 support charger by usb. usb_mode=%d\n",__func__,cw_bat->charger_init_mode); + cw_bat->charger_init_mode = dwc_otg_check_dpdm(); + pr_info("%s cw2015 support charger by usb. usb_mode=%d\n", + __func__, cw_bat->charger_init_mode); } - cw_bat->dc_online = 0; - cw_bat->usb_online = 0; - cw_bat->charger_mode = 0; - cw_bat->capacity = 2; - cw_bat->voltage = 0; - cw_bat->status = 0; - cw_bat->time_to_empty = 0; - cw_bat->bat_change = 0; - - cw_update_time_member_capacity_change(cw_bat); - cw_update_time_member_charge_start(cw_bat); - - cw_bat->battery_workqueue = create_singlethread_workqueue("rk_battery"); - INIT_DELAYED_WORK(&cw_bat->battery_delay_work, cw_bat_work); - INIT_DELAYED_WORK(&cw_bat->dc_wakeup_work, dc_detect_do_wakeup); - queue_delayed_work(cw_bat->battery_workqueue, &cw_bat->battery_delay_work, msecs_to_jiffies(10)); - - if (gpio_is_valid(cw_bat->plat_data.dc_det_pin)) { - irq = gpio_to_irq(cw_bat->plat_data.dc_det_pin); + cw_bat->dc_online = 0; + cw_bat->usb_online = 0; + cw_bat->charger_mode = 0; + cw_bat->capacity = 2; + cw_bat->voltage = 0; + cw_bat->status = 0; + cw_bat->time_to_empty = 0; + cw_bat->bat_change = 0; + + cw_update_time_member_capacity_change(cw_bat); + cw_update_time_member_charge_start(cw_bat); + + cw_bat->battery_workqueue = create_singlethread_workqueue("rk_battery"); + INIT_DELAYED_WORK(&cw_bat->battery_delay_work, cw_bat_work); + INIT_DELAYED_WORK(&cw_bat->dc_wakeup_work, dc_detect_do_wakeup); + queue_delayed_work(cw_bat->battery_workqueue, + &cw_bat->battery_delay_work, msecs_to_jiffies(10)); + + if (gpio_is_valid(cw_bat->plat_data.dc_det_pin)) { + irq = gpio_to_irq(cw_bat->plat_data.dc_det_pin); level = gpio_get_value(cw_bat->plat_data.dc_det_pin); - if (level == cw_bat->plat_data.dc_det_level) - { - printk("%s booting up with dc plug\n",__func__); + if (level == cw_bat->plat_data.dc_det_level) { + pr_info("%s booting up with dc plug\n", __func__); cw_bat->status = POWER_SUPPLY_STATUS_CHARGING; } - irq_flags = level ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; - ret = request_irq(irq, dc_detect_irq_handler, irq_flags, "dc_detect", cw_bat); - if (ret < 0) { - pr_err("%s: request_irq(%d) failed\n", __func__, irq); - } - enable_irq_wake(irq); - } - + irq_flags = level ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; + ret = + request_irq(irq, dc_detect_irq_handler, irq_flags, + "dc_detect", cw_bat); + if (ret < 0) + pr_err("%s: request_irq(%d) failed\n", __func__, irq); + enable_irq_wake(irq); + } if (gpio_is_valid(cw_bat->plat_data.bat_low_pin)) { - INIT_DELAYED_WORK(&cw_bat->bat_low_wakeup_work, bat_low_detect_do_wakeup); - level = gpio_get_value(cw_bat->plat_data.bat_low_pin); - if (level == cw_bat->plat_data.dc_det_level) - { - printk("%s booting up with lower power\n",__func__); + INIT_DELAYED_WORK(&cw_bat->bat_low_wakeup_work, + bat_low_detect_do_wakeup); + level = gpio_get_value(cw_bat->plat_data.bat_low_pin); + if (level == cw_bat->plat_data.dc_det_level) { + pr_info("%s booting up with lower power\n", __func__); cw_bat->capacity = 1; } - irq = gpio_to_irq(cw_bat->plat_data.bat_low_pin); - ret = request_irq(irq, bat_low_detect_irq_handler, IRQF_TRIGGER_RISING, "bat_low_detect", cw_bat); - if (ret < 0) { - gpio_free(cw_bat->plat_data.bat_low_pin); - } - enable_irq_wake(irq); - } + irq = gpio_to_irq(cw_bat->plat_data.bat_low_pin); + ret = + request_irq(irq, bat_low_detect_irq_handler, + IRQF_TRIGGER_RISING, "bat_low_detect", cw_bat); + if (ret < 0) + gpio_free(cw_bat->plat_data.bat_low_pin); + + enable_irq_wake(irq); + } - dev_info(&cw_bat->client->dev, "cw2015/cw2013 driver v1.2 probe sucess\n"); - return 0; + dev_info(&cw_bat->client->dev, + "cw2015/cw2013 driver v1.2 probe sucess\n"); + return 0; rk_usb_register_fail: - power_supply_unregister(&cw_bat->rk_usb); + power_supply_unregister(&cw_bat->rk_usb); rk_ac_register_fail: - power_supply_unregister(&cw_bat->rk_ac); + power_supply_unregister(&cw_bat->rk_ac); rk_bat_register_fail: - power_supply_unregister(&cw_bat->rk_bat); + power_supply_unregister(&cw_bat->rk_bat); pdate_fail: - dev_info(&cw_bat->client->dev, "cw2015/cw2013 driver v1.2 probe error!!!!\n"); - return ret; + dev_info(&cw_bat->client->dev, + "cw2015/cw2013 driver v1.2 probe error!!!!\n"); + return ret; } static int cw_bat_remove(struct i2c_client *client) { - struct cw_battery *cw_bat = i2c_get_clientdata(client); - dev_dbg(&cw_bat->client->dev, "%s\n", __func__); - cancel_delayed_work(&cw_bat->battery_delay_work); - return 0; + struct cw_battery *cw_bat = i2c_get_clientdata(client); + + dev_dbg(&cw_bat->client->dev, "%s\n", __func__); + cancel_delayed_work(&cw_bat->battery_delay_work); + return 0; } #ifdef CONFIG_PM static int cw_bat_suspend(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct cw_battery *cw_bat = i2c_get_clientdata(client); - dev_dbg(&cw_bat->client->dev, "%s\n", __func__); - cancel_delayed_work(&cw_bat->battery_delay_work); - return 0; + struct i2c_client *client = to_i2c_client(dev); + struct cw_battery *cw_bat = i2c_get_clientdata(client); + + dev_dbg(&cw_bat->client->dev, "%s\n", __func__); + cancel_delayed_work(&cw_bat->battery_delay_work); + return 0; } static int cw_bat_resume(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct cw_battery *cw_bat = i2c_get_clientdata(client); - dev_dbg(&cw_bat->client->dev, "%s\n", __func__); - queue_delayed_work(cw_bat->battery_workqueue, &cw_bat->battery_delay_work, msecs_to_jiffies(100)); - return 0; + struct i2c_client *client = to_i2c_client(dev); + struct cw_battery *cw_bat = i2c_get_clientdata(client); + + dev_dbg(&cw_bat->client->dev, "%s\n", __func__); + queue_delayed_work(cw_bat->battery_workqueue, + &cw_bat->battery_delay_work, msecs_to_jiffies(100)); + return 0; } static const struct i2c_device_id cw_id[] = { - { "cw201x", 0 }, - { } + {"cw201x", 0}, + {} }; MODULE_DEVICE_TABLE(i2c, cw_id); static const struct dev_pm_ops cw_bat_pm_ops = { - .suspend = cw_bat_suspend, - .resume = cw_bat_resume, + .suspend = cw_bat_suspend, + .resume = cw_bat_resume, }; #endif static struct i2c_driver cw_bat_driver = { - .driver = { - .name = "cw201x", + .driver = { + .name = "cw201x", #ifdef CONFIG_PM - .pm = &cw_bat_pm_ops, + .pm = &cw_bat_pm_ops, #endif - }, - - .probe = cw_bat_probe, - .remove = cw_bat_remove, - .id_table = cw_id, + }, + + .probe = cw_bat_probe, + .remove = cw_bat_remove, + .id_table = cw_id, }; static int __init cw_bat_init(void) { - return i2c_add_driver(&cw_bat_driver); + return i2c_add_driver(&cw_bat_driver); } static void __exit cw_bat_exit(void) { - i2c_del_driver(&cw_bat_driver); + i2c_del_driver(&cw_bat_driver); } fs_initcall(cw_bat_init); module_exit(cw_bat_exit); - MODULE_AUTHOR("xhc"); MODULE_DESCRIPTION("cw2015/cw2013 battery driver"); MODULE_LICENSE("GPL"); - - diff --git a/include/linux/power/cw2015_battery.h b/include/linux/power/cw2015_battery.h index edd4ca36bced..5f711443bb6c 100644 --- a/include/linux/power/cw2015_battery.h +++ b/include/linux/power/cw2015_battery.h @@ -1,5 +1,6 @@ /* - * RockChip ADC Battery Driver + * Fuel gauge driver for CellWise 2013 / 2015 + * * Copyright (C) 2012, RockChip * * Authors: xuhuicong @@ -15,24 +16,115 @@ #ifndef CW2015_BATTERY_H #define CW2015_BATTERY_H -#define SIZE_BATINFO 64 +#define SIZE_BATINFO 64 + +#define CW2015_GPIO_HIGH 1 +#define CW2015_GPIO_LOW 0 + +#define REG_VERSION 0x0 +#define REG_VCELL 0x2 +#define REG_SOC 0x4 +#define REG_RRT_ALERT 0x6 +#define REG_CONFIG 0x8 +#define REG_MODE 0xA +#define REG_BATINFO 0x10 + +#define MODE_SLEEP_MASK (0x3<<6) +#define MODE_SLEEP (0x3<<6) +#define MODE_NORMAL (0x0<<6) +#define MODE_QUICK_START (0x3<<4) +#define MODE_RESTART (0xf<<0) + +#define CONFIG_UPDATE_FLG (0x1<<1) +#define ATHD (0x0<<3) + +#define CW_I2C_SPEED 100000 +#define BATTERY_UP_MAX_CHANGE 420 +#define BATTERY_DOWN_CHANGE 60 +#define BATTERY_DOWN_MIN_CHANGE_RUN 30 +#define BATTERY_DOWN_MIN_CHANGE_SLEEP 1800 + +#define BATTERY_DOWN_MAX_CHANGE_RUN_AC_ONLINE 3600 + +#define NO_STANDARD_AC_BIG_CHARGE_MODE 1 +/* #define SYSTEM_SHUTDOWN_VOLTAGE 3400000 */ +#define BAT_LOW_INTERRUPT 1 + +#define USB_CHARGER_MODE 1 +#define AC_CHARGER_MODE 2 +#define CW_QUICKSTART 0 -extern void rk_send_wakeup_key(void); struct cw_bat_platform_data { + int is_dc_charge; + int dc_det_pin; + int dc_det_level; + + int is_usb_charge; + int chg_mode_sel_pin; + int chg_mode_sel_level; - int is_dc_charge; - int dc_det_pin; - int dc_det_level; + int bat_low_pin; + int bat_low_level; + int chg_ok_pin; + int chg_ok_level; + u32 *cw_bat_config_info; +}; + +struct cw_battery { + struct i2c_client *client; + struct workqueue_struct *battery_workqueue; + struct delayed_work battery_delay_work; + struct delayed_work dc_wakeup_work; + struct delayed_work bat_low_wakeup_work; + struct cw_bat_platform_data plat_data; + + struct power_supply rk_bat; + struct power_supply rk_ac; + struct power_supply rk_usb; + + long sleep_time_capacity_change; + long run_time_capacity_change; + + long sleep_time_charge_start; + long run_time_charge_start; - int is_usb_charge; - int chg_mode_sel_pin; - int chg_mode_sel_level; + int dc_online; + int usb_online; + int charger_mode; + int charger_init_mode; + int capacity; + int voltage; + int status; + int time_to_empty; + int alt; - int bat_low_pin; - int bat_low_level; - int chg_ok_pin; - int chg_ok_level; - u32* cw_bat_config_info; + int bat_change; }; +#if defined(CONFIG_ARCH_ROCKCHIP) +int get_gadget_connect_flag(void); +int dwc_otg_check_dpdm(void); +void rk_send_wakeup_key(void); +int dwc_vbus_status(void); +#else +static inline int get_gadget_connect_flag(void) +{ + return 0; +} + +static inline int dwc_otg_check_dpdm(bool wait) +{ + return 0; +} + +static inline void rk_send_wakeup_key(void) +{ +} + +static inline int dwc_vbus_status(void); +{ + return 0; +} +#endif + #endif -- 2.34.1