power: pm8921-bms: scale rbatt with temperature and soc
The rbatt was observed to change with battery temperature and the state of charge of the battery. Update the BMS driver and the battery data to include and use a rbatt table indicating its changes w.r.t temperature and state of charge. On similar lines provide api for other systems to query battery resistance. Change-Id: I681675db537b70919e6e0437bd400ce53bf97096 Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
This commit is contained in:
@@ -65,10 +65,11 @@ static struct pc_temp_ocv_lut desay_5200_pc_temp_ocv = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct pc_sf_lut desay_5200_pc_sf = {
|
||||
static struct sf_lut desay_5200_pc_sf = {
|
||||
.rows = 1,
|
||||
.cols = 1,
|
||||
.cycles = {0},
|
||||
/* row_entries are cycles here */
|
||||
.row_entries = {0},
|
||||
.percent = {100},
|
||||
.sf = {
|
||||
{100}
|
||||
@@ -81,4 +82,5 @@ struct pm8921_bms_battery_data desay_5200_data = {
|
||||
.fcc_sf_lut = &desay_5200_fcc_sf,
|
||||
.pc_temp_ocv_lut = &desay_5200_pc_temp_ocv,
|
||||
.pc_sf_lut = &desay_5200_pc_sf,
|
||||
.default_rbatt_mohm = 156,
|
||||
};
|
||||
|
||||
@@ -24,10 +24,11 @@ static struct single_row_lut palladium_1500_fcc_sf = {
|
||||
.cols = 5,
|
||||
};
|
||||
|
||||
static struct pc_sf_lut palladium_1500_pc_sf = {
|
||||
static struct sf_lut palladium_1500_pc_sf = {
|
||||
.rows = 10,
|
||||
.cols = 5,
|
||||
.cycles = {100, 200, 300, 400, 500},
|
||||
/* row_entries are chargecycles */
|
||||
.row_entries = {100, 200, 300, 400, 500},
|
||||
.percent = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10},
|
||||
.sf = {
|
||||
{97, 93, 93, 90, 87},
|
||||
@@ -43,6 +44,36 @@ static struct pc_sf_lut palladium_1500_pc_sf = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct sf_lut palladium_1500_rbatt_sf = {
|
||||
.rows = 19,
|
||||
.cols = 5,
|
||||
/* row_entries are temperature */
|
||||
.row_entries = {-20, 0, 20, 40, 65},
|
||||
.percent = {100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50,
|
||||
45, 40, 35, 30, 25, 20, 15, 10
|
||||
},
|
||||
.sf = {
|
||||
{645, 301, 100, 80, 69},
|
||||
{616, 290, 100, 79, 69},
|
||||
{586, 279, 100, 78, 68},
|
||||
{564, 270, 100, 78, 68},
|
||||
{546, 262, 100, 78, 68},
|
||||
{537, 256, 100, 79, 68},
|
||||
{536, 253, 100, 79, 69},
|
||||
{552, 258, 100, 81, 71},
|
||||
{618, 284, 100, 80, 72},
|
||||
{643, 290, 100, 77, 68},
|
||||
{673, 294, 100, 77, 68},
|
||||
{720, 296, 100, 77, 69},
|
||||
{769, 294, 100, 76, 68},
|
||||
{821, 288, 100, 74, 67},
|
||||
{892, 284, 100, 74, 61},
|
||||
{1003, 290, 100, 71, 58},
|
||||
{1192, 307, 100, 70, 58},
|
||||
{1579, 345, 100, 68, 57},
|
||||
{1261, 324, 100, 68, 57},
|
||||
}
|
||||
};
|
||||
static struct pc_temp_ocv_lut palladium_1500_pc_temp_ocv = {
|
||||
.rows = 29,
|
||||
.cols = 8,
|
||||
@@ -90,4 +121,6 @@ struct pm8921_bms_battery_data palladium_1500_data = {
|
||||
.fcc_sf_lut = &palladium_1500_fcc_sf,
|
||||
.pc_temp_ocv_lut = &palladium_1500_pc_temp_ocv,
|
||||
.pc_sf_lut = &palladium_1500_pc_sf,
|
||||
.rbatt_sf_lut = &palladium_1500_rbatt_sf,
|
||||
.default_rbatt_mohm = 254,
|
||||
};
|
||||
|
||||
@@ -90,7 +90,8 @@ struct pm8921_bms_chip {
|
||||
struct single_row_lut *fcc_temp_lut;
|
||||
struct single_row_lut *fcc_sf_lut;
|
||||
struct pc_temp_ocv_lut *pc_temp_ocv_lut;
|
||||
struct pc_sf_lut *pc_sf_lut;
|
||||
struct sf_lut *pc_sf_lut;
|
||||
struct sf_lut *rbatt_sf_lut;
|
||||
struct work_struct calib_hkadc_work;
|
||||
struct delayed_work calib_ccadc_work;
|
||||
unsigned int calib_delay_ms;
|
||||
@@ -118,6 +119,8 @@ struct pm8921_bms_chip {
|
||||
int max_voltage_uv;
|
||||
|
||||
int batt_temp_suspend;
|
||||
int soc_rbatt_suspend;
|
||||
int default_rbatt_mohm;
|
||||
};
|
||||
|
||||
static struct pm8921_bms_chip *the_chip;
|
||||
@@ -620,8 +623,9 @@ static int interpolate_scalingfactor_fcc(struct pm8921_bms_chip *chip,
|
||||
return 100;
|
||||
}
|
||||
|
||||
static int interpolate_scalingfactor_pc(struct pm8921_bms_chip *chip,
|
||||
int cycles, int pc)
|
||||
static int interpolate_scalingfactor(struct pm8921_bms_chip *chip,
|
||||
struct sf_lut *sf_lut,
|
||||
int row_entry, int pc)
|
||||
{
|
||||
int i, scalefactorrow1, scalefactorrow2, scalefactor;
|
||||
int rows, cols;
|
||||
@@ -632,71 +636,71 @@ static int interpolate_scalingfactor_pc(struct pm8921_bms_chip *chip,
|
||||
* sf table could be null when no battery aging data is available, in
|
||||
* that case return 100%
|
||||
*/
|
||||
if (!chip->pc_sf_lut)
|
||||
if (!sf_lut)
|
||||
return 100;
|
||||
|
||||
rows = chip->pc_sf_lut->rows;
|
||||
cols = chip->pc_sf_lut->cols;
|
||||
if (pc > chip->pc_sf_lut->percent[0]) {
|
||||
rows = sf_lut->rows;
|
||||
cols = sf_lut->cols;
|
||||
if (pc > sf_lut->percent[0]) {
|
||||
pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
|
||||
row1 = 0;
|
||||
row2 = 0;
|
||||
}
|
||||
if (pc < chip->pc_sf_lut->percent[rows - 1]) {
|
||||
if (pc < sf_lut->percent[rows - 1]) {
|
||||
pr_debug("pc %d less than known pc ranges for sf", pc);
|
||||
row1 = rows - 1;
|
||||
row2 = rows - 1;
|
||||
}
|
||||
for (i = 0; i < rows; i++) {
|
||||
if (pc == chip->pc_sf_lut->percent[i]) {
|
||||
if (pc == sf_lut->percent[i]) {
|
||||
row1 = i;
|
||||
row2 = i;
|
||||
break;
|
||||
}
|
||||
if (pc > chip->pc_sf_lut->percent[i]) {
|
||||
if (pc > sf_lut->percent[i]) {
|
||||
row1 = i - 1;
|
||||
row2 = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cycles < chip->pc_sf_lut->cycles[0])
|
||||
cycles = chip->pc_sf_lut->cycles[0];
|
||||
if (cycles > chip->pc_sf_lut->cycles[cols - 1])
|
||||
cycles = chip->pc_sf_lut->cycles[cols - 1];
|
||||
if (row_entry < sf_lut->row_entries[0])
|
||||
row_entry = sf_lut->row_entries[0];
|
||||
if (row_entry > sf_lut->row_entries[cols - 1])
|
||||
row_entry = sf_lut->row_entries[cols - 1];
|
||||
|
||||
for (i = 0; i < cols; i++)
|
||||
if (cycles <= chip->pc_sf_lut->cycles[i])
|
||||
if (row_entry <= sf_lut->row_entries[i])
|
||||
break;
|
||||
if (cycles == chip->pc_sf_lut->cycles[i]) {
|
||||
if (row_entry == sf_lut->row_entries[i]) {
|
||||
scalefactor = linear_interpolate(
|
||||
chip->pc_sf_lut->sf[row1][i],
|
||||
chip->pc_sf_lut->percent[row1],
|
||||
chip->pc_sf_lut->sf[row2][i],
|
||||
chip->pc_sf_lut->percent[row2],
|
||||
sf_lut->sf[row1][i],
|
||||
sf_lut->percent[row1],
|
||||
sf_lut->sf[row2][i],
|
||||
sf_lut->percent[row2],
|
||||
pc);
|
||||
return scalefactor;
|
||||
}
|
||||
|
||||
scalefactorrow1 = linear_interpolate(
|
||||
chip->pc_sf_lut->sf[row1][i - 1],
|
||||
chip->pc_sf_lut->cycles[i - 1],
|
||||
chip->pc_sf_lut->sf[row1][i],
|
||||
chip->pc_sf_lut->cycles[i],
|
||||
cycles);
|
||||
sf_lut->sf[row1][i - 1],
|
||||
sf_lut->row_entries[i - 1],
|
||||
sf_lut->sf[row1][i],
|
||||
sf_lut->row_entries[i],
|
||||
row_entry);
|
||||
|
||||
scalefactorrow2 = linear_interpolate(
|
||||
chip->pc_sf_lut->sf[row2][i - 1],
|
||||
chip->pc_sf_lut->cycles[i - 1],
|
||||
chip->pc_sf_lut->sf[row2][i],
|
||||
chip->pc_sf_lut->cycles[i],
|
||||
cycles);
|
||||
sf_lut->sf[row2][i - 1],
|
||||
sf_lut->row_entries[i - 1],
|
||||
sf_lut->sf[row2][i],
|
||||
sf_lut->row_entries[i],
|
||||
row_entry);
|
||||
|
||||
scalefactor = linear_interpolate(
|
||||
scalefactorrow1,
|
||||
chip->pc_sf_lut->percent[row1],
|
||||
sf_lut->percent[row1],
|
||||
scalefactorrow2,
|
||||
chip->pc_sf_lut->percent[row2],
|
||||
sf_lut->percent[row2],
|
||||
pc);
|
||||
|
||||
return scalefactor;
|
||||
@@ -927,6 +931,27 @@ static int read_soc_params_raw(struct pm8921_bms_chip *chip,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_rbatt(struct pm8921_bms_chip *chip, int soc_rbatt, int batt_temp)
|
||||
{
|
||||
int rbatt, scalefactor;
|
||||
|
||||
rbatt = (last_rbatt < 0) ? chip->default_rbatt_mohm : last_rbatt;
|
||||
pr_debug("rbatt before scaling = %d\n", rbatt);
|
||||
if (chip->rbatt_sf_lut == NULL) {
|
||||
pr_debug("RBATT = %d\n", rbatt);
|
||||
return rbatt;
|
||||
}
|
||||
|
||||
scalefactor = interpolate_scalingfactor(chip, chip->rbatt_sf_lut,
|
||||
batt_temp, soc_rbatt);
|
||||
pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
|
||||
scalefactor, batt_temp, soc_rbatt);
|
||||
rbatt = (rbatt * scalefactor) / 100;
|
||||
|
||||
pr_debug("RBATT = %d\n", rbatt);
|
||||
return rbatt;
|
||||
}
|
||||
|
||||
static int calculate_rbatt_resume(struct pm8921_bms_chip *chip,
|
||||
struct pm8921_rbatt_params *raw)
|
||||
{
|
||||
@@ -1000,7 +1025,7 @@ static int adc_based_ocv(struct pm8921_bms_chip *chip, int *ocv)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rbatt = (last_rbatt < 0) ? DEFAULT_RBATT_MOHMS : last_rbatt;
|
||||
rbatt = (last_rbatt < 0) ? chip->default_rbatt_mohm : last_rbatt;
|
||||
*ocv = vbatt + (ibatt_ua * rbatt)/1000;
|
||||
return 0;
|
||||
}
|
||||
@@ -1014,7 +1039,8 @@ static int calculate_pc(struct pm8921_bms_chip *chip, int ocv_uv, int batt_temp,
|
||||
pr_debug("pc = %u for ocv = %dmicroVolts batt_temp = %d\n",
|
||||
pc, ocv_uv, batt_temp);
|
||||
|
||||
scalefactor = interpolate_scalingfactor_pc(chip, chargecycles, pc);
|
||||
scalefactor = interpolate_scalingfactor(chip,
|
||||
chip->pc_sf_lut, chargecycles, pc);
|
||||
pr_debug("scalefactor = %u batt_temp = %d\n", scalefactor, batt_temp);
|
||||
|
||||
/* Multiply the initial FCC value by the scale factor. */
|
||||
@@ -1051,12 +1077,10 @@ static void calculate_cc_uah(struct pm8921_bms_chip *chip, int cc, int *val)
|
||||
}
|
||||
|
||||
static int calculate_unusable_charge_uah(struct pm8921_bms_chip *chip,
|
||||
struct pm8921_soc_params *raw,
|
||||
int fcc_uah, int batt_temp, int chargecycles)
|
||||
int rbatt, int fcc_uah,
|
||||
int batt_temp, int chargecycles)
|
||||
{
|
||||
int rbatt, voltage_unusable_uv, pc_unusable;
|
||||
|
||||
rbatt = (last_rbatt < 0) ? DEFAULT_RBATT_MOHMS : last_rbatt;
|
||||
int voltage_unusable_uv, pc_unusable;
|
||||
|
||||
/* calculate unusable charge */
|
||||
voltage_unusable_uv = (rbatt * chip->i_test)
|
||||
@@ -1106,18 +1130,16 @@ static void calculate_soc_params(struct pm8921_bms_chip *chip,
|
||||
int *fcc_uah,
|
||||
int *unusable_charge_uah,
|
||||
int *remaining_charge_uah,
|
||||
int *cc_uah)
|
||||
int *cc_uah,
|
||||
int *rbatt)
|
||||
{
|
||||
unsigned long flags;
|
||||
int soc_rbatt;
|
||||
|
||||
*fcc_uah = calculate_fcc_uah(chip, batt_temp, chargecycles);
|
||||
pr_debug("FCC = %uuAh batt_temp = %d, cycles = %d\n",
|
||||
*fcc_uah, batt_temp, chargecycles);
|
||||
|
||||
*unusable_charge_uah = calculate_unusable_charge_uah(chip, raw,
|
||||
*fcc_uah, batt_temp, chargecycles);
|
||||
|
||||
pr_debug("UUC = %uuAh\n", *unusable_charge_uah);
|
||||
|
||||
spin_lock_irqsave(&chip->bms_100_lock, flags);
|
||||
/* calculate remainging charge */
|
||||
@@ -1132,6 +1154,15 @@ static void calculate_soc_params(struct pm8921_bms_chip *chip,
|
||||
(int64_t)raw->cc - chip->cc_reading_at_100,
|
||||
chip->cc_reading_at_100);
|
||||
spin_unlock_irqrestore(&chip->bms_100_lock, flags);
|
||||
|
||||
soc_rbatt = ((*remaining_charge_uah - *cc_uah) * 100) / *fcc_uah;
|
||||
if (soc_rbatt < 0)
|
||||
soc_rbatt = 0;
|
||||
*rbatt = get_rbatt(chip, soc_rbatt, batt_temp);
|
||||
|
||||
*unusable_charge_uah = calculate_unusable_charge_uah(chip, *rbatt,
|
||||
*fcc_uah, batt_temp, chargecycles);
|
||||
pr_debug("UUC = %uuAh\n", *unusable_charge_uah);
|
||||
}
|
||||
|
||||
static int calculate_real_fcc_uah(struct pm8921_bms_chip *chip,
|
||||
@@ -1143,12 +1174,14 @@ static int calculate_real_fcc_uah(struct pm8921_bms_chip *chip,
|
||||
int remaining_charge_uah;
|
||||
int cc_uah;
|
||||
int real_fcc_uah;
|
||||
int rbatt;
|
||||
|
||||
calculate_soc_params(chip, raw, batt_temp, chargecycles,
|
||||
&fcc_uah,
|
||||
&unusable_charge_uah,
|
||||
&remaining_charge_uah,
|
||||
&cc_uah);
|
||||
&cc_uah,
|
||||
&rbatt);
|
||||
|
||||
real_fcc_uah = remaining_charge_uah - cc_uah;
|
||||
*ret_fcc_uah = fcc_uah;
|
||||
@@ -1170,12 +1203,14 @@ static int calculate_state_of_charge(struct pm8921_bms_chip *chip,
|
||||
int remaining_charge_uah, soc;
|
||||
int update_userspace = 1;
|
||||
int cc_uah;
|
||||
int rbatt;
|
||||
|
||||
calculate_soc_params(chip, raw, batt_temp, chargecycles,
|
||||
&fcc_uah,
|
||||
&unusable_charge_uah,
|
||||
&remaining_charge_uah,
|
||||
&cc_uah);
|
||||
&cc_uah,
|
||||
&rbatt);
|
||||
|
||||
/* calculate remaining usable charge */
|
||||
remaining_usable_charge_uah = remaining_charge_uah
|
||||
@@ -1384,6 +1419,44 @@ int pm8921_bms_get_percent_charge(void)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm8921_bms_get_percent_charge);
|
||||
|
||||
int pm8921_bms_get_rbatt(void)
|
||||
{
|
||||
int batt_temp, rc;
|
||||
struct pm8xxx_adc_chan_result result;
|
||||
struct pm8921_soc_params raw;
|
||||
int fcc_uah;
|
||||
int unusable_charge_uah;
|
||||
int remaining_charge_uah;
|
||||
int cc_uah;
|
||||
int rbatt;
|
||||
|
||||
if (!the_chip) {
|
||||
pr_err("called before initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
|
||||
if (rc) {
|
||||
pr_err("error reading adc channel = %d, rc = %d\n",
|
||||
the_chip->batt_temp_channel, rc);
|
||||
return rc;
|
||||
}
|
||||
pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
|
||||
result.measurement);
|
||||
batt_temp = (int)result.physical;
|
||||
|
||||
read_soc_params_raw(the_chip, &raw);
|
||||
|
||||
calculate_soc_params(the_chip, &raw, batt_temp, last_chargecycles,
|
||||
&fcc_uah,
|
||||
&unusable_charge_uah,
|
||||
&remaining_charge_uah,
|
||||
&cc_uah,
|
||||
&rbatt);
|
||||
return rbatt;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm8921_bms_get_rbatt);
|
||||
|
||||
int pm8921_bms_get_fcc(void)
|
||||
{
|
||||
int batt_temp, rc;
|
||||
@@ -1652,6 +1725,10 @@ static int pm8921_bms_suspend(struct device *dev)
|
||||
int rc;
|
||||
struct pm8xxx_adc_chan_result result;
|
||||
struct pm8921_bms_chip *chip = dev_get_drvdata(dev);
|
||||
struct pm8921_soc_params raw;
|
||||
int fcc_uah;
|
||||
int remaining_charge_uah;
|
||||
int cc_uah;
|
||||
|
||||
chip->batt_temp_suspend = 0;
|
||||
rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
|
||||
@@ -1660,20 +1737,66 @@ static int pm8921_bms_suspend(struct device *dev)
|
||||
chip->batt_temp_channel, rc);
|
||||
}
|
||||
chip->batt_temp_suspend = (int)result.physical;
|
||||
read_soc_params_raw(chip, &raw);
|
||||
|
||||
fcc_uah = calculate_fcc_uah(chip,
|
||||
chip->batt_temp_suspend, last_chargecycles);
|
||||
pr_debug("FCC = %uuAh batt_temp = %d, cycles = %d\n",
|
||||
fcc_uah, chip->batt_temp_suspend, last_chargecycles);
|
||||
/* calculate remainging charge */
|
||||
remaining_charge_uah = calculate_remaining_charge_uah(chip, &raw,
|
||||
fcc_uah, chip->batt_temp_suspend,
|
||||
last_chargecycles);
|
||||
pr_debug("RC = %uuAh\n", remaining_charge_uah);
|
||||
|
||||
/* calculate cc micro_volt_hour */
|
||||
calculate_cc_uah(chip, raw.cc, &cc_uah);
|
||||
pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %d\n",
|
||||
cc_uah, raw.cc,
|
||||
(int64_t)raw.cc - chip->cc_reading_at_100,
|
||||
chip->cc_reading_at_100);
|
||||
chip->soc_rbatt_suspend = ((remaining_charge_uah - cc_uah) * 100)
|
||||
/ fcc_uah;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DELTA_RBATT_PERCENT 10
|
||||
static int pm8921_bms_resume(struct device *dev)
|
||||
{
|
||||
struct pm8921_rbatt_params raw;
|
||||
struct pm8921_bms_chip *chip = dev_get_drvdata(dev);
|
||||
int rbatt;
|
||||
int expected_rbatt;
|
||||
int scalefactor;
|
||||
int delta_rbatt;
|
||||
|
||||
read_rbatt_params_raw(chip, &raw);
|
||||
rbatt = calculate_rbatt_resume(chip, &raw);
|
||||
if (rbatt > 0) /* TODO Check for rbatt values bound based on cycles */
|
||||
|
||||
if (rbatt < 0)
|
||||
return 0;
|
||||
|
||||
expected_rbatt
|
||||
= (last_rbatt < 0) ? chip->default_rbatt_mohm : last_rbatt;
|
||||
|
||||
if (chip->rbatt_sf_lut) {
|
||||
scalefactor = interpolate_scalingfactor(chip,
|
||||
chip->rbatt_sf_lut,
|
||||
chip->batt_temp_suspend,
|
||||
chip->soc_rbatt_suspend);
|
||||
rbatt = rbatt * 100 / scalefactor;
|
||||
}
|
||||
|
||||
delta_rbatt = expected_rbatt - rbatt;
|
||||
if (delta_rbatt)
|
||||
delta_rbatt = -delta_rbatt;
|
||||
/*
|
||||
* only update last_rbatt if rbatt is within some
|
||||
* percent of expected_rbatt
|
||||
*/
|
||||
if (delta_rbatt * 100 <= DELTA_RBATT_PERCENT * expected_rbatt)
|
||||
last_rbatt = rbatt;
|
||||
chip->batt_temp_suspend = -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1767,7 +1890,9 @@ static int set_battery_data(struct pm8921_bms_chip *chip)
|
||||
battery_id)) {
|
||||
goto desay;
|
||||
} else {
|
||||
goto unknown;
|
||||
pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
|
||||
battery_id);
|
||||
goto palladium;
|
||||
}
|
||||
|
||||
palladium:
|
||||
@@ -1776,22 +1901,17 @@ palladium:
|
||||
chip->fcc_sf_lut = palladium_1500_data.fcc_sf_lut;
|
||||
chip->pc_temp_ocv_lut = palladium_1500_data.pc_temp_ocv_lut;
|
||||
chip->pc_sf_lut = palladium_1500_data.pc_sf_lut;
|
||||
chip->rbatt_sf_lut = palladium_1500_data.rbatt_sf_lut;
|
||||
chip->default_rbatt_mohm
|
||||
= palladium_1500_data.default_rbatt_mohm;
|
||||
return 0;
|
||||
desay:
|
||||
chip->fcc = desay_5200_data.fcc;
|
||||
chip->fcc_temp_lut = desay_5200_data.fcc_temp_lut;
|
||||
chip->fcc_sf_lut = desay_5200_data.fcc_sf_lut;
|
||||
chip->pc_temp_ocv_lut = desay_5200_data.pc_temp_ocv_lut;
|
||||
chip->pc_sf_lut = desay_5200_data.pc_sf_lut;
|
||||
return 0;
|
||||
unknown:
|
||||
pr_warn("invalid battery id, palladium 1500 assumed batt_id %llx\n",
|
||||
battery_id);
|
||||
chip->fcc = palladium_1500_data.fcc;
|
||||
chip->fcc_temp_lut = palladium_1500_data.fcc_temp_lut;
|
||||
chip->fcc_sf_lut = palladium_1500_data.fcc_sf_lut;
|
||||
chip->pc_temp_ocv_lut = palladium_1500_data.pc_temp_ocv_lut;
|
||||
chip->pc_sf_lut = palladium_1500_data.pc_sf_lut;
|
||||
chip->rbatt_sf_lut = desay_5200_data.rbatt_sf_lut;
|
||||
chip->default_rbatt_mohm = desay_5200_data.default_rbatt_mohm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2087,6 +2207,16 @@ static int __devinit pm8921_bms_probe(struct platform_device *pdev)
|
||||
goto free_chip;
|
||||
}
|
||||
|
||||
if (chip->pc_temp_ocv_lut == NULL) {
|
||||
pr_err("temp ocv lut table is NULL\n");
|
||||
rc = -EINVAL;
|
||||
goto free_chip;
|
||||
}
|
||||
|
||||
/* set defaults in the battery data */
|
||||
if (chip->default_rbatt_mohm <= 0)
|
||||
chip->default_rbatt_mohm = DEFAULT_RBATT_MOHMS;
|
||||
|
||||
chip->batt_temp_channel = pdata->bms_cdata.batt_temp_channel;
|
||||
chip->vbat_channel = pdata->bms_cdata.vbat_channel;
|
||||
chip->ref625mv_channel = pdata->bms_cdata.ref625mv_channel;
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#define FCC_CC_COLS 5
|
||||
#define FCC_TEMP_COLS 8
|
||||
|
||||
#define PC_CC_ROWS 10
|
||||
#define PC_CC_COLS 5
|
||||
#define PC_CC_ROWS 29
|
||||
#define PC_CC_COLS 13
|
||||
|
||||
#define PC_TEMP_ROWS 29
|
||||
#define PC_TEMP_COLS 8
|
||||
@@ -35,19 +35,20 @@ struct single_row_lut {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pc_sf_lut -
|
||||
* struct sf_lut -
|
||||
* @rows: number of percent charge entries should be <= PC_CC_ROWS
|
||||
* @cols: number of charge cycle entries should be <= PC_CC_COLS
|
||||
* @cycles: the charge cycles at which sf data is available in the table.
|
||||
* @row_entries: the charge cycles/temperature at which sf data
|
||||
* is available in the table.
|
||||
* The charge cycles must be in increasing order from 0 to rows.
|
||||
* @percent: the percent charge at which sf data is available in the table
|
||||
* The percentcharge must be in decreasing order from 0 to cols.
|
||||
* @sf: the scaling factor data
|
||||
*/
|
||||
struct pc_sf_lut {
|
||||
struct sf_lut {
|
||||
int rows;
|
||||
int cols;
|
||||
int cycles[PC_CC_COLS];
|
||||
int row_entries[PC_CC_COLS];
|
||||
int percent[PC_CC_ROWS];
|
||||
int sf[PC_CC_ROWS][PC_CC_COLS];
|
||||
};
|
||||
@@ -74,17 +75,22 @@ struct pc_temp_ocv_lut {
|
||||
* struct pm8921_bms_battery_data -
|
||||
* @fcc: full charge capacity (mAmpHour)
|
||||
* @fcc_temp_lut: table to get fcc at a given temp
|
||||
* @fcc_sf_lut: table to get fcc scaling factor for given charge cycles
|
||||
* @pc_temp_ocv_lut: table to get percent charge given batt temp and cycles
|
||||
* @pc_sf_lut: table to get percent charge scaling factor given cycles
|
||||
* and percent charge
|
||||
* @rbatt_sf_lut: table to get battery resistance scaling factor given
|
||||
* temperature and percent charge
|
||||
* default_rbatt_mohm: the default value of battery resistance to use when
|
||||
* readings from bms are not available.
|
||||
*/
|
||||
struct pm8921_bms_battery_data {
|
||||
unsigned int fcc;
|
||||
struct single_row_lut *fcc_temp_lut;
|
||||
struct single_row_lut *fcc_sf_lut;
|
||||
struct pc_temp_ocv_lut *pc_temp_ocv_lut;
|
||||
struct pc_sf_lut *pc_sf_lut;
|
||||
unsigned int fcc;
|
||||
struct single_row_lut *fcc_temp_lut;
|
||||
struct single_row_lut *fcc_sf_lut;
|
||||
struct pc_temp_ocv_lut *pc_temp_ocv_lut;
|
||||
struct sf_lut *pc_sf_lut;
|
||||
struct sf_lut *rbatt_sf_lut;
|
||||
int default_rbatt_mohm;
|
||||
};
|
||||
|
||||
struct pm8xxx_bms_core_data {
|
||||
@@ -185,6 +191,10 @@ void pm8921_bms_calibrate_hkadc(void);
|
||||
*/
|
||||
int pm8921_bms_get_simultaneous_battery_voltage_and_current(int *ibat_ua,
|
||||
int *vbat_uv);
|
||||
/**
|
||||
* pm8921_bms_get_rbatt - function to get the battery resistance in mOhm.
|
||||
*/
|
||||
int pm8921_bms_get_rbatt(void);
|
||||
#else
|
||||
static inline int pm8921_bms_get_vsense_avg(int *result)
|
||||
{
|
||||
@@ -216,6 +226,10 @@ static inline int pm8921_bms_get_simultaneous_battery_voltage_and_current(
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
static inline int pm8921_bms_get_rbatt(void)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user