mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
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:
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user