power: rk818-charger: support temperature charge v2

Set charge current according to bat temperature and
the v1 is abandoned on kernel 4.19.

Change-Id: I6462e5de1c153c7f774136ef67a8a17a3c7fec8a
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
Joseph Chen
2019-11-13 11:19:14 +08:00
committed by Tao Huang
parent c6884c2558
commit ffc406d1d8
2 changed files with 48 additions and 54 deletions

View File

@@ -148,6 +148,8 @@ module_param_named(dbg_level, dbg_enable, int, 0644);
#define NTC_40UA_MAX_MEASURE 55000
#define NTC_20UA_MAX_MEASURE 110000
#define INPUT_CUR80MA (0x01)
static const char *bat_status[] = {
"charge off", "dead charge", "trickle charge", "cc cv",
"finish", "usb over vol", "bat temp error", "timer error",
@@ -2739,6 +2741,17 @@ static int rk818_bat_get_ntc_res(struct rk818_battery *di)
return res;
}
static void rk818_bat_set_input_current(struct rk818_battery *di,
int input_current)
{
u8 usb_ctrl;
usb_ctrl = rk818_bat_read(di, RK818_USB_CTRL_REG);
usb_ctrl &= ~0x0f;
usb_ctrl |= (input_current);
rk818_bat_write(di, RK818_USB_CTRL_REG, usb_ctrl);
}
static BLOCKING_NOTIFIER_HEAD(rk818_bat_notifier_chain);
int rk818_bat_temp_notifier_register(struct notifier_block *nb)
@@ -2771,9 +2784,13 @@ static void rk818_bat_update_temperature(struct rk818_battery *di)
if (res < ntc_table[ntc_size - 1]) {
di->temperature = di->pdata->ntc_degree_from +
di->pdata->ntc_size - 1;
if (di->pdata->bat_mode != MODE_VIRTUAL)
rk818_bat_set_input_current(di, INPUT_CUR80MA);
BAT_INFO("bat ntc upper max degree: R=%d\n", res);
} else if (res > ntc_table[0]) {
di->temperature = di->pdata->ntc_degree_from;
if (di->pdata->bat_mode != MODE_VIRTUAL)
rk818_bat_set_input_current(di, INPUT_CUR80MA);
BAT_INFO("bat ntc lower min degree: R=%d\n", res);
} else {
for (i = 0; i < ntc_size; i++) {
@@ -3275,18 +3292,13 @@ static int rk818_bat_parse_dt(struct rk818_battery *di)
pdata->ntc_size = 0;
} else {
/* get ntc degree base value */
ret = of_property_read_u32_index(np, "ntc_degree_from", 1,
&pdata->ntc_degree_from);
ret = of_property_read_s32(np, "ntc_degree_from_v2",
&pdata->ntc_degree_from);
if (ret) {
dev_err(dev, "invalid ntc_degree_from\n");
dev_err(dev, "invalid ntc_degree_from_v2\n");
return -EINVAL;
}
of_property_read_u32_index(np, "ntc_degree_from", 0,
&out_value);
if (out_value)
pdata->ntc_degree_from = -pdata->ntc_degree_from;
pdata->ntc_size = length / sizeof(u32);
}
@@ -3317,7 +3329,7 @@ static int rk818_bat_parse_dt(struct rk818_battery *di)
"pwroff_vol:%d\n"
"sample_res:%d\n"
"ntc_size=%d\n"
"ntc_degree_from:%d\n"
"ntc_degree_from_v2:%d\n"
"ntc_degree_to:%d\n",
pdata->bat_res, pdata->design_capacity, pdata->design_qmax,
pdata->sleep_enter_current, pdata->sleep_exit_current,

View File

@@ -108,9 +108,9 @@ enum {
};
struct temp_chrg_table {
int temperature;
int temp_down;
int temp_up;
u32 chrg_current;
u32 offset;
u8 set_chrg_current;
};
@@ -792,7 +792,6 @@ static u8 rk818_cg_decode_chrg_vol(struct rk818_charger *cg, u32 chrg_vol)
val = index << 4;
}
DBG("<%s>. vol=0x%x\n", __func__, val);
return val;
}
@@ -815,7 +814,6 @@ static u8 rk818_cg_decode_input_current(struct rk818_charger *cg,
}
}
DBG("<%s>. input=0x%x\n", __func__, val);
return val;
}
@@ -837,7 +835,6 @@ static u8 rk818_cg_decode_chrg_current(struct rk818_charger *cg,
val = index << 0;
}
DBG("<%s>. sel=0x%x\n", __func__, val);
return val;
}
@@ -1420,30 +1417,18 @@ static int rk818_cg_temperature_notifier_call(struct notifier_block *nb,
struct rk818_charger *cg =
container_of(nb, struct rk818_charger, temp_nb);
static int temp_triggered, config_index = -1;
int i, up_temp, down_temp, cfg_temp, cfg_offset, cfg_current;
int i, up_temp, down_temp, cfg_current;
int now_temp = temp;
u8 usb_ctrl, chrg_ctrl1;
DBG("%s: receive notify temperature = %d\n", __func__, now_temp);
for (i = 0; i < cg->pdata->tc_count; i++) {
up_temp = 0;
down_temp = 0;
cfg_temp = cg->pdata->tc_table[i].temperature;
cfg_offset = cg->pdata->tc_table[i].offset;
up_temp = cg->pdata->tc_table[i].temp_up;
down_temp = cg->pdata->tc_table[i].temp_down;
cfg_current = cg->pdata->tc_table[i].chrg_current;
/* positive: [temp, temp+offset] */
if (cfg_temp >= 0)
up_temp = cfg_temp + cfg_offset;
/* negative: [temp-offset, temp] */
if (cfg_temp < 0)
down_temp = cfg_temp - cfg_offset;
if ((now_temp >= 0 && now_temp <= up_temp &&
now_temp >= cfg_temp) ||
(now_temp < 0 && now_temp >= down_temp &&
now_temp <= cfg_temp)) {
/* if not charger or temp changed, not update */
if (now_temp >= down_temp && now_temp <= up_temp) {
/* Temp range or charger are not update, return */
if (config_index == i && !cg->charger_changed)
return NOTIFY_DONE;
@@ -1455,18 +1440,14 @@ static int rk818_cg_temperature_notifier_call(struct notifier_block *nb,
rk818_cg_set_chrg_current(cg, cfg_current);
CG_INFO("temperature = %d'C[%d~%d'C], "
"chrg current = %d\n",
now_temp,
(now_temp >= 0 ? cfg_temp : down_temp),
(now_temp >= 0 ? up_temp : cfg_temp),
now_temp, down_temp, up_temp,
chrg_cur_sel_array[cfg_current] *
cg->res_div);
} else {
rk818_cg_set_input_current(cg, cfg_current);
CG_INFO("temperature = %d'C[%d~%d'C], "
"input current = %d\n",
now_temp,
(now_temp >= 0 ? cfg_temp : down_temp),
(now_temp >= 0 ? up_temp : cfg_temp),
now_temp, down_temp, up_temp,
chrg_cur_input_array[cfg_current]);
}
return NOTIFY_DONE;
@@ -1474,14 +1455,17 @@ static int rk818_cg_temperature_notifier_call(struct notifier_block *nb,
}
/*
* means: current temperature now covers above case, temperature rolls
* means: current temperature not covers above case, temperature rolls
* back to normal range, so restore default value
*/
if (temp_triggered) {
temp_triggered = 0;
config_index = -1;
rk818_cg_set_chrg_current(cg, cg->chrg_current);
rk818_cg_set_input_current(cg, cg->chrg_input);
if (cg->ac_in || cg->dc_in)
rk818_cg_set_input_current(cg, cg->chrg_input);
else
rk818_cg_set_input_current(cg, INPUT_CUR450MA);
usb_ctrl = rk818_reg_read(cg, RK818_USB_CTRL_REG);
chrg_ctrl1 = rk818_reg_read(cg, RK818_CHRG_CTRL_REG1);
CG_INFO("roll back temp %d'C, current chrg = %d, input = %d\n",
@@ -1497,21 +1481,21 @@ static int parse_temperature_chrg_table(struct rk818_charger *cg,
struct device_node *np)
{
int size, count;
int i, sign, chrg_current;
int i, chrg_current;
const __be32 *list;
if (!of_find_property(np, "temperature_chrg_table", &size))
if (!of_find_property(np, "temperature_chrg_table_v2", &size))
return 0;
list = of_get_property(np, "temperature_chrg_table", &size);
list = of_get_property(np, "temperature_chrg_table_v2", &size);
size /= sizeof(u32);
if (!size || (size % 4)) {
if (!size || (size % 3)) {
dev_err(cg->dev,
"invalid temperature_chrg_table: size=%d\n", size);
return -EINVAL;
}
count = size / 4;
count = size / 3;
cg->pdata->tc_count = count;
cg->pdata->tc_table = devm_kzalloc(cg->dev,
count * sizeof(*cg->pdata->tc_table),
@@ -1521,9 +1505,9 @@ static int parse_temperature_chrg_table(struct rk818_charger *cg,
for (i = 0; i < count; i++) {
/* temperature */
sign = be32_to_cpu(*list++);
cg->pdata->tc_table[i].temperature = sign ?
-be32_to_cpu(*list++) : be32_to_cpu(*list++);
cg->pdata->tc_table[i].temp_down = be32_to_cpu(*list++);
cg->pdata->tc_table[i].temp_up = be32_to_cpu(*list++);
/*
* because charge current lowest level is 1000mA:
* higher than or equal 1000ma, select charge current;
@@ -1539,16 +1523,14 @@ static int parse_temperature_chrg_table(struct rk818_charger *cg,
rk818_cg_decode_input_current(cg, chrg_current);
}
/* temperature offset */
cg->pdata->tc_table[i].offset = be32_to_cpu(*list++);
DBG("temp=%d, chrg=0x%x, offset=%d\n",
cg->pdata->tc_table[i].temperature,
cg->pdata->tc_table[i].chrg_current,
cg->pdata->tc_table[i].offset);
DBG("temp%d: [%d, %d], chrg_current=%d\n",
i, cg->pdata->tc_table[i].temp_down,
cg->pdata->tc_table[i].temp_up,
cg->pdata->tc_table[i].chrg_current);
}
return 0;
}
static int rk818_cg_register_temp_notifier(struct rk818_charger *cg)