mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 18:13:04 +00:00
4c4268dc97
The AB8540 was an evolved version of the AB8500, but it was never mass produced or put into products, only reference designs exist. The upstream support was never completed and it is unlikely that this will happen so drop the support for now to simplify maintenance of the AB8500. Cc: Loic Pallardy <loic.pallardy@st.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
544 lines
14 KiB
C
544 lines
14 KiB
C
// 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");
|
|
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;
|
|
}
|