forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
544 lines
14 KiB
544 lines
14 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
#include <linux/export.h> |
|
#include <linux/power_supply.h> |
|
#include <linux/of.h> |
|
#include <linux/mfd/abx500.h> |
|
#include <linux/mfd/abx500/ab8500.h> |
|
#include <linux/mfd/abx500/ab8500-bm.h> |
|
|
|
/* |
|
* These are the defined batteries that uses a NTC and ID resistor placed |
|
* inside of the battery pack. |
|
* Note that the res_to_temp table must be strictly sorted by falling resistance |
|
* values to work. |
|
*/ |
|
const struct abx500_res_to_temp ab8500_temp_tbl_a_thermistor[] = { |
|
{-5, 53407}, |
|
{ 0, 48594}, |
|
{ 5, 43804}, |
|
{10, 39188}, |
|
{15, 34870}, |
|
{20, 30933}, |
|
{25, 27422}, |
|
{30, 24347}, |
|
{35, 21694}, |
|
{40, 19431}, |
|
{45, 17517}, |
|
{50, 15908}, |
|
{55, 14561}, |
|
{60, 13437}, |
|
{65, 12500}, |
|
}; |
|
EXPORT_SYMBOL(ab8500_temp_tbl_a_thermistor); |
|
|
|
const int ab8500_temp_tbl_a_size = ARRAY_SIZE(ab8500_temp_tbl_a_thermistor); |
|
EXPORT_SYMBOL(ab8500_temp_tbl_a_size); |
|
|
|
const struct abx500_res_to_temp ab8500_temp_tbl_b_thermistor[] = { |
|
{-5, 200000}, |
|
{ 0, 159024}, |
|
{ 5, 151921}, |
|
{10, 144300}, |
|
{15, 136424}, |
|
{20, 128565}, |
|
{25, 120978}, |
|
{30, 113875}, |
|
{35, 107397}, |
|
{40, 101629}, |
|
{45, 96592}, |
|
{50, 92253}, |
|
{55, 88569}, |
|
{60, 85461}, |
|
{65, 82869}, |
|
}; |
|
EXPORT_SYMBOL(ab8500_temp_tbl_b_thermistor); |
|
|
|
const int ab8500_temp_tbl_b_size = ARRAY_SIZE(ab8500_temp_tbl_b_thermistor); |
|
EXPORT_SYMBOL(ab8500_temp_tbl_b_size); |
|
|
|
static const struct abx500_v_to_cap cap_tbl_a_thermistor[] = { |
|
{4171, 100}, |
|
{4114, 95}, |
|
{4009, 83}, |
|
{3947, 74}, |
|
{3907, 67}, |
|
{3863, 59}, |
|
{3830, 56}, |
|
{3813, 53}, |
|
{3791, 46}, |
|
{3771, 33}, |
|
{3754, 25}, |
|
{3735, 20}, |
|
{3717, 17}, |
|
{3681, 13}, |
|
{3664, 8}, |
|
{3651, 6}, |
|
{3635, 5}, |
|
{3560, 3}, |
|
{3408, 1}, |
|
{3247, 0}, |
|
}; |
|
|
|
static const struct abx500_v_to_cap cap_tbl_b_thermistor[] = { |
|
{4161, 100}, |
|
{4124, 98}, |
|
{4044, 90}, |
|
{4003, 85}, |
|
{3966, 80}, |
|
{3933, 75}, |
|
{3888, 67}, |
|
{3849, 60}, |
|
{3813, 55}, |
|
{3787, 47}, |
|
{3772, 30}, |
|
{3751, 25}, |
|
{3718, 20}, |
|
{3681, 16}, |
|
{3660, 14}, |
|
{3589, 10}, |
|
{3546, 7}, |
|
{3495, 4}, |
|
{3404, 2}, |
|
{3250, 0}, |
|
}; |
|
|
|
static const struct abx500_v_to_cap cap_tbl[] = { |
|
{4186, 100}, |
|
{4163, 99}, |
|
{4114, 95}, |
|
{4068, 90}, |
|
{3990, 80}, |
|
{3926, 70}, |
|
{3898, 65}, |
|
{3866, 60}, |
|
{3833, 55}, |
|
{3812, 50}, |
|
{3787, 40}, |
|
{3768, 30}, |
|
{3747, 25}, |
|
{3730, 20}, |
|
{3705, 15}, |
|
{3699, 14}, |
|
{3684, 12}, |
|
{3672, 9}, |
|
{3657, 7}, |
|
{3638, 6}, |
|
{3556, 4}, |
|
{3424, 2}, |
|
{3317, 1}, |
|
{3094, 0}, |
|
}; |
|
|
|
/* |
|
* Note that the res_to_temp table must be strictly sorted by falling |
|
* resistance values to work. |
|
*/ |
|
static const struct abx500_res_to_temp temp_tbl[] = { |
|
{-5, 214834}, |
|
{ 0, 162943}, |
|
{ 5, 124820}, |
|
{10, 96520}, |
|
{15, 75306}, |
|
{20, 59254}, |
|
{25, 47000}, |
|
{30, 37566}, |
|
{35, 30245}, |
|
{40, 24520}, |
|
{45, 20010}, |
|
{50, 16432}, |
|
{55, 13576}, |
|
{60, 11280}, |
|
{65, 9425}, |
|
}; |
|
|
|
/* |
|
* Note that the batres_vs_temp table must be strictly sorted by falling |
|
* temperature values to work. |
|
*/ |
|
static const struct batres_vs_temp temp_to_batres_tbl_thermistor[] = { |
|
{ 40, 120}, |
|
{ 30, 135}, |
|
{ 20, 165}, |
|
{ 10, 230}, |
|
{ 00, 325}, |
|
{-10, 445}, |
|
{-20, 595}, |
|
}; |
|
|
|
/* |
|
* Note that the batres_vs_temp table must be strictly sorted by falling |
|
* temperature values to work. |
|
*/ |
|
static const struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[] = { |
|
{ 60, 300}, |
|
{ 30, 300}, |
|
{ 20, 300}, |
|
{ 10, 300}, |
|
{ 00, 300}, |
|
{-10, 300}, |
|
{-20, 300}, |
|
}; |
|
|
|
/* battery resistance table for LI ION 9100 battery */ |
|
static const struct batres_vs_temp temp_to_batres_tbl_9100[] = { |
|
{ 60, 180}, |
|
{ 30, 180}, |
|
{ 20, 180}, |
|
{ 10, 180}, |
|
{ 00, 180}, |
|
{-10, 180}, |
|
{-20, 180}, |
|
}; |
|
|
|
static struct abx500_battery_type bat_type_thermistor[] = { |
|
[BATTERY_UNKNOWN] = { |
|
/* First element always represent the UNKNOWN battery */ |
|
.name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, |
|
.resis_high = 0, |
|
.resis_low = 0, |
|
.battery_resistance = 300, |
|
.charge_full_design = 612, |
|
.nominal_voltage = 3700, |
|
.termination_vol = 4050, |
|
.termination_curr = 200, |
|
.recharge_cap = 95, |
|
.normal_cur_lvl = 400, |
|
.normal_vol_lvl = 4100, |
|
.maint_a_cur_lvl = 400, |
|
.maint_a_vol_lvl = 4050, |
|
.maint_a_chg_timer_h = 60, |
|
.maint_b_cur_lvl = 400, |
|
.maint_b_vol_lvl = 4000, |
|
.maint_b_chg_timer_h = 200, |
|
.low_high_cur_lvl = 300, |
|
.low_high_vol_lvl = 4000, |
|
.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), |
|
.r_to_t_tbl = temp_tbl, |
|
.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), |
|
.v_to_cap_tbl = cap_tbl, |
|
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
|
.batres_tbl = temp_to_batres_tbl_thermistor, |
|
}, |
|
{ |
|
.name = POWER_SUPPLY_TECHNOLOGY_LIPO, |
|
.resis_high = 53407, |
|
.resis_low = 12500, |
|
.battery_resistance = 300, |
|
.charge_full_design = 900, |
|
.nominal_voltage = 3600, |
|
.termination_vol = 4150, |
|
.termination_curr = 80, |
|
.recharge_cap = 95, |
|
.normal_cur_lvl = 700, |
|
.normal_vol_lvl = 4200, |
|
.maint_a_cur_lvl = 600, |
|
.maint_a_vol_lvl = 4150, |
|
.maint_a_chg_timer_h = 60, |
|
.maint_b_cur_lvl = 600, |
|
.maint_b_vol_lvl = 4100, |
|
.maint_b_chg_timer_h = 200, |
|
.low_high_cur_lvl = 300, |
|
.low_high_vol_lvl = 4000, |
|
.n_temp_tbl_elements = ARRAY_SIZE(ab8500_temp_tbl_a_thermistor), |
|
.r_to_t_tbl = ab8500_temp_tbl_a_thermistor, |
|
.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_a_thermistor), |
|
.v_to_cap_tbl = cap_tbl_a_thermistor, |
|
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
|
.batres_tbl = temp_to_batres_tbl_thermistor, |
|
|
|
}, |
|
{ |
|
.name = POWER_SUPPLY_TECHNOLOGY_LIPO, |
|
.resis_high = 200000, |
|
.resis_low = 82869, |
|
.battery_resistance = 300, |
|
.charge_full_design = 900, |
|
.nominal_voltage = 3600, |
|
.termination_vol = 4150, |
|
.termination_curr = 80, |
|
.recharge_cap = 95, |
|
.normal_cur_lvl = 700, |
|
.normal_vol_lvl = 4200, |
|
.maint_a_cur_lvl = 600, |
|
.maint_a_vol_lvl = 4150, |
|
.maint_a_chg_timer_h = 60, |
|
.maint_b_cur_lvl = 600, |
|
.maint_b_vol_lvl = 4100, |
|
.maint_b_chg_timer_h = 200, |
|
.low_high_cur_lvl = 300, |
|
.low_high_vol_lvl = 4000, |
|
.n_temp_tbl_elements = ARRAY_SIZE(ab8500_temp_tbl_b_thermistor), |
|
.r_to_t_tbl = ab8500_temp_tbl_b_thermistor, |
|
.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_b_thermistor), |
|
.v_to_cap_tbl = cap_tbl_b_thermistor, |
|
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
|
.batres_tbl = temp_to_batres_tbl_thermistor, |
|
}, |
|
}; |
|
|
|
static struct abx500_battery_type bat_type_ext_thermistor[] = { |
|
[BATTERY_UNKNOWN] = { |
|
/* First element always represent the UNKNOWN battery */ |
|
.name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, |
|
.resis_high = 0, |
|
.resis_low = 0, |
|
.battery_resistance = 300, |
|
.charge_full_design = 612, |
|
.nominal_voltage = 3700, |
|
.termination_vol = 4050, |
|
.termination_curr = 200, |
|
.recharge_cap = 95, |
|
.normal_cur_lvl = 400, |
|
.normal_vol_lvl = 4100, |
|
.maint_a_cur_lvl = 400, |
|
.maint_a_vol_lvl = 4050, |
|
.maint_a_chg_timer_h = 60, |
|
.maint_b_cur_lvl = 400, |
|
.maint_b_vol_lvl = 4000, |
|
.maint_b_chg_timer_h = 200, |
|
.low_high_cur_lvl = 300, |
|
.low_high_vol_lvl = 4000, |
|
.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), |
|
.r_to_t_tbl = temp_tbl, |
|
.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), |
|
.v_to_cap_tbl = cap_tbl, |
|
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
|
.batres_tbl = temp_to_batres_tbl_thermistor, |
|
}, |
|
/* |
|
* These are the batteries that doesn't have an internal NTC resistor to measure |
|
* its temperature. The temperature in this case is measure with a NTC placed |
|
* near the battery but on the PCB. |
|
*/ |
|
{ |
|
.name = POWER_SUPPLY_TECHNOLOGY_LIPO, |
|
.resis_high = 76000, |
|
.resis_low = 53000, |
|
.battery_resistance = 300, |
|
.charge_full_design = 900, |
|
.nominal_voltage = 3700, |
|
.termination_vol = 4150, |
|
.termination_curr = 100, |
|
.recharge_cap = 95, |
|
.normal_cur_lvl = 700, |
|
.normal_vol_lvl = 4200, |
|
.maint_a_cur_lvl = 600, |
|
.maint_a_vol_lvl = 4150, |
|
.maint_a_chg_timer_h = 60, |
|
.maint_b_cur_lvl = 600, |
|
.maint_b_vol_lvl = 4100, |
|
.maint_b_chg_timer_h = 200, |
|
.low_high_cur_lvl = 300, |
|
.low_high_vol_lvl = 4000, |
|
.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), |
|
.r_to_t_tbl = temp_tbl, |
|
.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), |
|
.v_to_cap_tbl = cap_tbl, |
|
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
|
.batres_tbl = temp_to_batres_tbl_thermistor, |
|
}, |
|
{ |
|
.name = POWER_SUPPLY_TECHNOLOGY_LION, |
|
.resis_high = 30000, |
|
.resis_low = 10000, |
|
.battery_resistance = 300, |
|
.charge_full_design = 950, |
|
.nominal_voltage = 3700, |
|
.termination_vol = 4150, |
|
.termination_curr = 100, |
|
.recharge_cap = 95, |
|
.normal_cur_lvl = 700, |
|
.normal_vol_lvl = 4200, |
|
.maint_a_cur_lvl = 600, |
|
.maint_a_vol_lvl = 4150, |
|
.maint_a_chg_timer_h = 60, |
|
.maint_b_cur_lvl = 600, |
|
.maint_b_vol_lvl = 4100, |
|
.maint_b_chg_timer_h = 200, |
|
.low_high_cur_lvl = 300, |
|
.low_high_vol_lvl = 4000, |
|
.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), |
|
.r_to_t_tbl = temp_tbl, |
|
.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), |
|
.v_to_cap_tbl = cap_tbl, |
|
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
|
.batres_tbl = temp_to_batres_tbl_thermistor, |
|
}, |
|
{ |
|
.name = POWER_SUPPLY_TECHNOLOGY_LION, |
|
.resis_high = 95000, |
|
.resis_low = 76001, |
|
.battery_resistance = 300, |
|
.charge_full_design = 950, |
|
.nominal_voltage = 3700, |
|
.termination_vol = 4150, |
|
.termination_curr = 100, |
|
.recharge_cap = 95, |
|
.normal_cur_lvl = 700, |
|
.normal_vol_lvl = 4200, |
|
.maint_a_cur_lvl = 600, |
|
.maint_a_vol_lvl = 4150, |
|
.maint_a_chg_timer_h = 60, |
|
.maint_b_cur_lvl = 600, |
|
.maint_b_vol_lvl = 4100, |
|
.maint_b_chg_timer_h = 200, |
|
.low_high_cur_lvl = 300, |
|
.low_high_vol_lvl = 4000, |
|
.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), |
|
.r_to_t_tbl = temp_tbl, |
|
.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), |
|
.v_to_cap_tbl = cap_tbl, |
|
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
|
.batres_tbl = temp_to_batres_tbl_thermistor, |
|
}, |
|
}; |
|
|
|
static const struct abx500_bm_capacity_levels cap_levels = { |
|
.critical = 2, |
|
.low = 10, |
|
.normal = 70, |
|
.high = 95, |
|
.full = 100, |
|
}; |
|
|
|
static const struct abx500_fg_parameters fg = { |
|
.recovery_sleep_timer = 10, |
|
.recovery_total_time = 100, |
|
.init_timer = 1, |
|
.init_discard_time = 5, |
|
.init_total_time = 40, |
|
.high_curr_time = 60, |
|
.accu_charging = 30, |
|
.accu_high_curr = 30, |
|
.high_curr_threshold = 50, |
|
.lowbat_threshold = 3100, |
|
.battok_falling_th_sel0 = 2860, |
|
.battok_raising_th_sel1 = 2860, |
|
.maint_thres = 95, |
|
.user_cap_limit = 15, |
|
.pcut_enable = 1, |
|
.pcut_max_time = 127, |
|
.pcut_flag_time = 112, |
|
.pcut_max_restart = 15, |
|
.pcut_debounce_time = 2, |
|
}; |
|
|
|
static const struct abx500_maxim_parameters ab8500_maxi_params = { |
|
.ena_maxi = true, |
|
.chg_curr = 910, |
|
.wait_cycles = 10, |
|
.charger_curr_step = 100, |
|
}; |
|
|
|
static const struct abx500_bm_charger_parameters chg = { |
|
.usb_volt_max = 5500, |
|
.usb_curr_max = 1500, |
|
.ac_volt_max = 7500, |
|
.ac_curr_max = 1500, |
|
}; |
|
|
|
/* |
|
* This array maps the raw hex value to charger output current used by the |
|
* AB8500 values |
|
*/ |
|
static int ab8500_charge_output_curr_map[] = { |
|
100, 200, 300, 400, 500, 600, 700, 800, |
|
900, 1000, 1100, 1200, 1300, 1400, 1500, 1500, |
|
}; |
|
|
|
/* |
|
* This array maps the raw hex value to charger input current used by the |
|
* AB8500 values |
|
*/ |
|
static int ab8500_charge_input_curr_map[] = { |
|
50, 98, 193, 290, 380, 450, 500, 600, |
|
700, 800, 900, 1000, 1100, 1300, 1400, 1500, |
|
}; |
|
|
|
struct abx500_bm_data ab8500_bm_data = { |
|
.temp_under = 3, |
|
.temp_low = 8, |
|
.temp_high = 43, |
|
.temp_over = 48, |
|
.main_safety_tmr_h = 4, |
|
.temp_interval_chg = 20, |
|
.temp_interval_nochg = 120, |
|
.usb_safety_tmr_h = 4, |
|
.bkup_bat_v = BUP_VCH_SEL_2P6V, |
|
.bkup_bat_i = BUP_ICH_SEL_150UA, |
|
.no_maintenance = false, |
|
.capacity_scaling = false, |
|
.adc_therm = ABx500_ADC_THERM_BATCTRL, |
|
.chg_unknown_bat = false, |
|
.enable_overshoot = false, |
|
.fg_res = 100, |
|
.cap_levels = &cap_levels, |
|
.bat_type = bat_type_thermistor, |
|
.n_btypes = ARRAY_SIZE(bat_type_thermistor), |
|
.batt_id = 0, |
|
.interval_charging = 5, |
|
.interval_not_charging = 120, |
|
.temp_hysteresis = 3, |
|
.gnd_lift_resistance = 34, |
|
.chg_output_curr = ab8500_charge_output_curr_map, |
|
.n_chg_out_curr = ARRAY_SIZE(ab8500_charge_output_curr_map), |
|
.maxi = &ab8500_maxi_params, |
|
.chg_params = &chg, |
|
.fg_params = &fg, |
|
.chg_input_curr = ab8500_charge_input_curr_map, |
|
.n_chg_in_curr = ARRAY_SIZE(ab8500_charge_input_curr_map), |
|
}; |
|
|
|
int ab8500_bm_of_probe(struct device *dev, |
|
struct device_node *np, |
|
struct abx500_bm_data *bm) |
|
{ |
|
const struct batres_vs_temp *tmp_batres_tbl; |
|
struct device_node *battery_node; |
|
const char *btech; |
|
int i; |
|
|
|
/* get phandle to 'battery-info' node */ |
|
battery_node = of_parse_phandle(np, "battery", 0); |
|
if (!battery_node) { |
|
dev_err(dev, "battery node or reference missing\n"); |
|
return -EINVAL; |
|
} |
|
|
|
btech = of_get_property(battery_node, "stericsson,battery-type", NULL); |
|
if (!btech) { |
|
dev_warn(dev, "missing property battery-name/type\n"); |
|
of_node_put(battery_node); |
|
return -EINVAL; |
|
} |
|
|
|
if (strncmp(btech, "LION", 4) == 0) { |
|
bm->no_maintenance = true; |
|
bm->chg_unknown_bat = true; |
|
bm->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600; |
|
bm->bat_type[BATTERY_UNKNOWN].termination_vol = 4150; |
|
bm->bat_type[BATTERY_UNKNOWN].recharge_cap = 95; |
|
bm->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520; |
|
bm->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200; |
|
} |
|
|
|
if (of_property_read_bool(battery_node, "thermistor-on-batctrl")) { |
|
if (strncmp(btech, "LION", 4) == 0) |
|
tmp_batres_tbl = temp_to_batres_tbl_9100; |
|
else |
|
tmp_batres_tbl = temp_to_batres_tbl_thermistor; |
|
} else { |
|
bm->n_btypes = 4; |
|
bm->bat_type = bat_type_ext_thermistor; |
|
bm->adc_therm = ABx500_ADC_THERM_BATTEMP; |
|
tmp_batres_tbl = temp_to_batres_tbl_ext_thermistor; |
|
} |
|
|
|
/* select the battery resolution table */ |
|
for (i = 0; i < bm->n_btypes; ++i) |
|
bm->bat_type[i].batres_tbl = tmp_batres_tbl; |
|
|
|
of_node_put(battery_node); |
|
|
|
return 0; |
|
}
|
|
|