Commit 240fbe23 authored by Anton Vorontsov's avatar Anton Vorontsov
parents 2fbb520d 215cf5c9
...@@ -1011,40 +1011,32 @@ static struct mfd_cell ab8500_bm_devs[] = { ...@@ -1011,40 +1011,32 @@ static struct mfd_cell ab8500_bm_devs[] = {
.of_compatible = "stericsson,ab8500-charger", .of_compatible = "stericsson,ab8500-charger",
.num_resources = ARRAY_SIZE(ab8500_charger_resources), .num_resources = ARRAY_SIZE(ab8500_charger_resources),
.resources = ab8500_charger_resources, .resources = ab8500_charger_resources,
#ifndef CONFIG_OF
.platform_data = &ab8500_bm_data, .platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data), .pdata_size = sizeof(ab8500_bm_data),
#endif
}, },
{ {
.name = "ab8500-btemp", .name = "ab8500-btemp",
.of_compatible = "stericsson,ab8500-btemp", .of_compatible = "stericsson,ab8500-btemp",
.num_resources = ARRAY_SIZE(ab8500_btemp_resources), .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
.resources = ab8500_btemp_resources, .resources = ab8500_btemp_resources,
#ifndef CONFIG_OF
.platform_data = &ab8500_bm_data, .platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data), .pdata_size = sizeof(ab8500_bm_data),
#endif
}, },
{ {
.name = "ab8500-fg", .name = "ab8500-fg",
.of_compatible = "stericsson,ab8500-fg", .of_compatible = "stericsson,ab8500-fg",
.num_resources = ARRAY_SIZE(ab8500_fg_resources), .num_resources = ARRAY_SIZE(ab8500_fg_resources),
.resources = ab8500_fg_resources, .resources = ab8500_fg_resources,
#ifndef CONFIG_OF
.platform_data = &ab8500_bm_data, .platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data), .pdata_size = sizeof(ab8500_bm_data),
#endif
}, },
{ {
.name = "ab8500-chargalg", .name = "ab8500-chargalg",
.of_compatible = "stericsson,ab8500-chargalg", .of_compatible = "stericsson,ab8500-chargalg",
.num_resources = ARRAY_SIZE(ab8500_chargalg_resources), .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
.resources = ab8500_chargalg_resources, .resources = ab8500_chargalg_resources,
#ifndef CONFIG_OF
.platform_data = &ab8500_bm_data, .platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data), .pdata_size = sizeof(ab8500_bm_data),
#endif
}, },
}; };
......
...@@ -38,7 +38,7 @@ obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o ...@@ -38,7 +38,7 @@ obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o
obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o
obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
......
...@@ -182,7 +182,7 @@ static struct batres_vs_temp temp_to_batres_tbl_9100[] = { ...@@ -182,7 +182,7 @@ static struct batres_vs_temp temp_to_batres_tbl_9100[] = {
}; };
static struct abx500_battery_type bat_type_thermistor[] = { static struct abx500_battery_type bat_type_thermistor[] = {
[BATTERY_UNKNOWN] = { [BATTERY_UNKNOWN] = {
/* First element always represent the UNKNOWN battery */ /* First element always represent the UNKNOWN battery */
.name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
.resis_high = 0, .resis_high = 0,
...@@ -209,8 +209,8 @@ static struct abx500_battery_type bat_type_thermistor[] = { ...@@ -209,8 +209,8 @@ static struct abx500_battery_type bat_type_thermistor[] = {
.v_to_cap_tbl = cap_tbl, .v_to_cap_tbl = cap_tbl,
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
.batres_tbl = temp_to_batres_tbl_thermistor, .batres_tbl = temp_to_batres_tbl_thermistor,
}, },
{ {
.name = POWER_SUPPLY_TECHNOLOGY_LIPO, .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
.resis_high = 53407, .resis_high = 53407,
.resis_low = 12500, .resis_low = 12500,
...@@ -237,8 +237,8 @@ static struct abx500_battery_type bat_type_thermistor[] = { ...@@ -237,8 +237,8 @@ static struct abx500_battery_type bat_type_thermistor[] = {
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
.batres_tbl = temp_to_batres_tbl_thermistor, .batres_tbl = temp_to_batres_tbl_thermistor,
}, },
{ {
.name = POWER_SUPPLY_TECHNOLOGY_LIPO, .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
.resis_high = 200000, .resis_high = 200000,
.resis_low = 82869, .resis_low = 82869,
...@@ -264,11 +264,11 @@ static struct abx500_battery_type bat_type_thermistor[] = { ...@@ -264,11 +264,11 @@ static struct abx500_battery_type bat_type_thermistor[] = {
.v_to_cap_tbl = cap_tbl_B_thermistor, .v_to_cap_tbl = cap_tbl_B_thermistor,
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
.batres_tbl = temp_to_batres_tbl_thermistor, .batres_tbl = temp_to_batres_tbl_thermistor,
}, },
}; };
static struct abx500_battery_type bat_type_ext_thermistor[] = { static struct abx500_battery_type bat_type_ext_thermistor[] = {
[BATTERY_UNKNOWN] = { [BATTERY_UNKNOWN] = {
/* First element always represent the UNKNOWN battery */ /* First element always represent the UNKNOWN battery */
.name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
.resis_high = 0, .resis_high = 0,
...@@ -295,13 +295,13 @@ static struct abx500_battery_type bat_type_ext_thermistor[] = { ...@@ -295,13 +295,13 @@ static struct abx500_battery_type bat_type_ext_thermistor[] = {
.v_to_cap_tbl = cap_tbl, .v_to_cap_tbl = cap_tbl,
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
.batres_tbl = 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 * 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 * its temperature. The temperature in this case is measure with a NTC placed
* near the battery but on the PCB. * near the battery but on the PCB.
*/ */
{ {
.name = POWER_SUPPLY_TECHNOLOGY_LIPO, .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
.resis_high = 76000, .resis_high = 76000,
.resis_low = 53000, .resis_low = 53000,
...@@ -327,8 +327,8 @@ static struct abx500_battery_type bat_type_ext_thermistor[] = { ...@@ -327,8 +327,8 @@ static struct abx500_battery_type bat_type_ext_thermistor[] = {
.v_to_cap_tbl = cap_tbl, .v_to_cap_tbl = cap_tbl,
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
.batres_tbl = temp_to_batres_tbl_thermistor, .batres_tbl = temp_to_batres_tbl_thermistor,
}, },
{ {
.name = POWER_SUPPLY_TECHNOLOGY_LION, .name = POWER_SUPPLY_TECHNOLOGY_LION,
.resis_high = 30000, .resis_high = 30000,
.resis_low = 10000, .resis_low = 10000,
...@@ -354,8 +354,8 @@ static struct abx500_battery_type bat_type_ext_thermistor[] = { ...@@ -354,8 +354,8 @@ static struct abx500_battery_type bat_type_ext_thermistor[] = {
.v_to_cap_tbl = cap_tbl, .v_to_cap_tbl = cap_tbl,
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
.batres_tbl = temp_to_batres_tbl_thermistor, .batres_tbl = temp_to_batres_tbl_thermistor,
}, },
{ {
.name = POWER_SUPPLY_TECHNOLOGY_LION, .name = POWER_SUPPLY_TECHNOLOGY_LION,
.resis_high = 95000, .resis_high = 95000,
.resis_low = 76001, .resis_low = 76001,
...@@ -381,7 +381,7 @@ static struct abx500_battery_type bat_type_ext_thermistor[] = { ...@@ -381,7 +381,7 @@ static struct abx500_battery_type bat_type_ext_thermistor[] = {
.v_to_cap_tbl = cap_tbl, .v_to_cap_tbl = cap_tbl,
.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
.batres_tbl = temp_to_batres_tbl_thermistor, .batres_tbl = temp_to_batres_tbl_thermistor,
}, },
}; };
static const struct abx500_bm_capacity_levels cap_levels = { static const struct abx500_bm_capacity_levels cap_levels = {
...@@ -452,70 +452,55 @@ struct abx500_bm_data ab8500_bm_data = { ...@@ -452,70 +452,55 @@ struct abx500_bm_data ab8500_bm_data = {
.fg_params = &fg, .fg_params = &fg,
}; };
int __devinit int __devinit ab8500_bm_of_probe(struct device *dev,
bmdevs_of_probe(struct device *dev,
struct device_node *np, struct device_node *np,
struct abx500_bm_data **battery) struct abx500_bm_data *bm)
{ {
struct abx500_battery_type *btype; struct batres_vs_temp *tmp_batres_tbl;
struct device_node *np_bat_supply; struct device_node *battery_node;
struct abx500_bm_data *bat;
const char *btech; const char *btech;
char bat_tech[8]; int i;
int i, thermistor;
*battery = &ab8500_bm_data;
/* get phandle to 'battery-info' node */ /* get phandle to 'battery-info' node */
np_bat_supply = of_parse_phandle(np, "battery", 0); battery_node = of_parse_phandle(np, "battery", 0);
if (!np_bat_supply) { if (!battery_node) {
dev_err(dev, "missing property battery\n"); dev_err(dev, "battery node or reference missing\n");
return -EINVAL; return -EINVAL;
} }
if (of_property_read_bool(np_bat_supply,
"thermistor-on-batctrl"))
thermistor = NTC_INTERNAL;
else
thermistor = NTC_EXTERNAL;
bat = *battery; btech = of_get_property(battery_node, "stericsson,battery-type", NULL);
if (thermistor == NTC_EXTERNAL) {
bat->n_btypes = 4;
bat->bat_type = bat_type_ext_thermistor;
bat->adc_therm = ABx500_ADC_THERM_BATTEMP;
}
btech = of_get_property(np_bat_supply,
"stericsson,battery-type", NULL);
if (!btech) { if (!btech) {
dev_warn(dev, "missing property battery-name/type\n"); dev_warn(dev, "missing property battery-name/type\n");
strcpy(bat_tech, "UNKNOWN"); return -EINVAL;
} else {
strcpy(bat_tech, btech);
} }
if (strncmp(bat_tech, "LION", 4) == 0) { if (strncmp(btech, "LION", 4) == 0) {
bat->no_maintenance = true; bm->no_maintenance = true;
bat->chg_unknown_bat = true; bm->chg_unknown_bat = true;
bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600; bm->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600;
bat->bat_type[BATTERY_UNKNOWN].termination_vol = 4150; bm->bat_type[BATTERY_UNKNOWN].termination_vol = 4150;
bat->bat_type[BATTERY_UNKNOWN].recharge_vol = 4130; bm->bat_type[BATTERY_UNKNOWN].recharge_vol = 4130;
bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520; bm->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520;
bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200; bm->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200;
} }
/* select the battery resolution table */
for (i = 0; i < bat->n_btypes; ++i) { if (of_property_read_bool(battery_node, "thermistor-on-batctrl")) {
btype = (bat->bat_type + i); if (strncmp(btech, "LION", 4) == 0)
if (thermistor == NTC_EXTERNAL) { tmp_batres_tbl = temp_to_batres_tbl_9100;
btype->batres_tbl = else
temp_to_batres_tbl_ext_thermistor; tmp_batres_tbl = temp_to_batres_tbl_thermistor;
} else if (strncmp(bat_tech, "LION", 4) == 0) {
btype->batres_tbl =
temp_to_batres_tbl_9100;
} else { } else {
btype->batres_tbl = bm->n_btypes = 4;
temp_to_batres_tbl_thermistor; bm->bat_type = bat_type_ext_thermistor;
} bm->adc_therm = ABx500_ADC_THERM_BATTEMP;
tmp_batres_tbl = temp_to_batres_tbl_ext_thermistor;
} }
of_node_put(np_bat_supply);
/* 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; return 0;
} }
...@@ -78,12 +78,13 @@ struct ab8500_btemp_ranges { ...@@ -78,12 +78,13 @@ struct ab8500_btemp_ranges {
* @parent: Pointer to the struct ab8500 * @parent: Pointer to the struct ab8500
* @gpadc: Pointer to the struct gpadc * @gpadc: Pointer to the struct gpadc
* @fg: Pointer to the struct fg * @fg: Pointer to the struct fg
* @bat: Pointer to the abx500_bm platform data * @bm: Platform specific battery management information
* @btemp_psy: Structure for BTEMP specific battery properties * @btemp_psy: Structure for BTEMP specific battery properties
* @events: Structure for information about events triggered * @events: Structure for information about events triggered
* @btemp_ranges: Battery temperature range structure * @btemp_ranges: Battery temperature range structure
* @btemp_wq: Work queue for measuring the temperature periodically * @btemp_wq: Work queue for measuring the temperature periodically
* @btemp_periodic_work: Work for measuring the temperature periodically * @btemp_periodic_work: Work for measuring the temperature periodically
* @initialized: True if battery id read.
*/ */
struct ab8500_btemp { struct ab8500_btemp {
struct device *dev; struct device *dev;
...@@ -94,12 +95,13 @@ struct ab8500_btemp { ...@@ -94,12 +95,13 @@ struct ab8500_btemp {
struct ab8500 *parent; struct ab8500 *parent;
struct ab8500_gpadc *gpadc; struct ab8500_gpadc *gpadc;
struct ab8500_fg *fg; struct ab8500_fg *fg;
struct abx500_bm_data *bat; struct abx500_bm_data *bm;
struct power_supply btemp_psy; struct power_supply btemp_psy;
struct ab8500_btemp_events events; struct ab8500_btemp_events events;
struct ab8500_btemp_ranges btemp_ranges; struct ab8500_btemp_ranges btemp_ranges;
struct workqueue_struct *btemp_wq; struct workqueue_struct *btemp_wq;
struct delayed_work btemp_periodic_work; struct delayed_work btemp_periodic_work;
bool initialized;
}; };
/* BTEMP power supply properties */ /* BTEMP power supply properties */
...@@ -147,13 +149,13 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di, ...@@ -147,13 +149,13 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
return (450000 * (v_batctrl)) / (1800 - v_batctrl); return (450000 * (v_batctrl)) / (1800 - v_batctrl);
} }
if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL) { if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
/* /*
* If the battery has internal NTC, we use the current * If the battery has internal NTC, we use the current
* source to calculate the resistance, 7uA or 20uA * source to calculate the resistance, 7uA or 20uA
*/ */
rbs = (v_batctrl * 1000 rbs = (v_batctrl * 1000
- di->bat->gnd_lift_resistance * inst_curr) - di->bm->gnd_lift_resistance * inst_curr)
/ di->curr_source; / di->curr_source;
} else { } else {
/* /*
...@@ -209,7 +211,7 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, ...@@ -209,7 +211,7 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
return 0; return 0;
/* Only do this for batteries with internal NTC */ /* Only do this for batteries with internal NTC */
if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA) if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA)
curr = BAT_CTRL_7U_ENA; curr = BAT_CTRL_7U_ENA;
else else
...@@ -241,7 +243,7 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, ...@@ -241,7 +243,7 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
__func__); __func__);
goto disable_curr_source; goto disable_curr_source;
} }
} else if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
dev_dbg(di->dev, "Disable BATCTRL curr source\n"); dev_dbg(di->dev, "Disable BATCTRL curr source\n");
/* Write 0 to the curr bits */ /* Write 0 to the curr bits */
...@@ -457,9 +459,9 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di) ...@@ -457,9 +459,9 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
int rbat, rntc, vntc; int rbat, rntc, vntc;
u8 id; u8 id;
id = di->bat->batt_id; id = di->bm->batt_id;
if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
id != BATTERY_UNKNOWN) { id != BATTERY_UNKNOWN) {
rbat = ab8500_btemp_get_batctrl_res(di); rbat = ab8500_btemp_get_batctrl_res(di);
...@@ -474,8 +476,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di) ...@@ -474,8 +476,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
} }
temp = ab8500_btemp_res_to_temp(di, temp = ab8500_btemp_res_to_temp(di,
di->bat->bat_type[id].r_to_t_tbl, di->bm->bat_type[id].r_to_t_tbl,
di->bat->bat_type[id].n_temp_tbl_elements, rbat); di->bm->bat_type[id].n_temp_tbl_elements, rbat);
} else { } else {
vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL); vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
if (vntc < 0) { if (vntc < 0) {
...@@ -491,8 +493,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di) ...@@ -491,8 +493,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
rntc = 230000 * vntc / (VTVOUT_V - vntc); rntc = 230000 * vntc / (VTVOUT_V - vntc);
temp = ab8500_btemp_res_to_temp(di, temp = ab8500_btemp_res_to_temp(di,
di->bat->bat_type[id].r_to_t_tbl, di->bm->bat_type[id].r_to_t_tbl,
di->bat->bat_type[id].n_temp_tbl_elements, rntc); di->bm->bat_type[id].n_temp_tbl_elements, rntc);
prev = temp; prev = temp;
} }
dev_dbg(di->dev, "Battery temperature is %d\n", temp); dev_dbg(di->dev, "Battery temperature is %d\n", temp);
...@@ -513,7 +515,7 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) ...@@ -513,7 +515,7 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
u8 i; u8 i;
di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
di->bat->batt_id = BATTERY_UNKNOWN; di->bm->batt_id = BATTERY_UNKNOWN;
res = ab8500_btemp_get_batctrl_res(di); res = ab8500_btemp_get_batctrl_res(di);
if (res < 0) { if (res < 0) {
...@@ -522,23 +524,23 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) ...@@ -522,23 +524,23 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
} }
/* BATTERY_UNKNOWN is defined on position 0, skip it! */ /* BATTERY_UNKNOWN is defined on position 0, skip it! */
for (i = BATTERY_UNKNOWN + 1; i < di->bat->n_btypes; i++) { for (i = BATTERY_UNKNOWN + 1; i < di->bm->n_btypes; i++) {
if ((res <= di->bat->bat_type[i].resis_high) && if ((res <= di->bm->bat_type[i].resis_high) &&
(res >= di->bat->bat_type[i].resis_low)) { (res >= di->bm->bat_type[i].resis_low)) {
dev_dbg(di->dev, "Battery detected on %s" dev_dbg(di->dev, "Battery detected on %s"
" low %d < res %d < high: %d" " low %d < res %d < high: %d"
" index: %d\n", " index: %d\n",
di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL ? di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL ?
"BATCTRL" : "BATTEMP", "BATCTRL" : "BATTEMP",
di->bat->bat_type[i].resis_low, res, di->bm->bat_type[i].resis_low, res,
di->bat->bat_type[i].resis_high, i); di->bm->bat_type[i].resis_high, i);
di->bat->batt_id = i; di->bm->batt_id = i;
break; break;
} }
} }
if (di->bat->batt_id == BATTERY_UNKNOWN) { if (di->bm->batt_id == BATTERY_UNKNOWN) {
dev_warn(di->dev, "Battery identified as unknown" dev_warn(di->dev, "Battery identified as unknown"
", resistance %d Ohm\n", res); ", resistance %d Ohm\n", res);
return -ENXIO; return -ENXIO;
...@@ -548,13 +550,13 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) ...@@ -548,13 +550,13 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
* We only have to change current source if the * We only have to change current source if the
* detected type is Type 1, else we use the 7uA source * detected type is Type 1, else we use the 7uA source
*/ */
if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
di->bat->batt_id == 1) { di->bm->batt_id == 1) {
dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA; di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
} }
return di->bat->batt_id; return di->bm->batt_id;
} }
/** /**
...@@ -569,6 +571,13 @@ static void ab8500_btemp_periodic_work(struct work_struct *work) ...@@ -569,6 +571,13 @@ static void ab8500_btemp_periodic_work(struct work_struct *work)
struct ab8500_btemp *di = container_of(work, struct ab8500_btemp *di = container_of(work,
struct ab8500_btemp, btemp_periodic_work.work); struct ab8500_btemp, btemp_periodic_work.work);
if (!di->initialized) {
di->initialized = true;
/* Identify the battery */
if (ab8500_btemp_id(di) < 0)
dev_warn(di->dev, "failed to identify the battery\n");
}
di->bat_temp = ab8500_btemp_measure_temp(di); di->bat_temp = ab8500_btemp_measure_temp(di);
if (di->bat_temp != di->prev_bat_temp) { if (di->bat_temp != di->prev_bat_temp) {
...@@ -577,9 +586,9 @@ static void ab8500_btemp_periodic_work(struct work_struct *work) ...@@ -577,9 +586,9 @@ static void ab8500_btemp_periodic_work(struct work_struct *work)
} }
if (di->events.ac_conn || di->events.usb_conn) if (di->events.ac_conn || di->events.usb_conn)
interval = di->bat->temp_interval_chg; interval = di->bm->temp_interval_chg;
else else
interval = di->bat->temp_interval_nochg; interval = di->bm->temp_interval_nochg;
/* Schedule a new measurement */ /* Schedule a new measurement */
queue_delayed_work(di->btemp_wq, queue_delayed_work(di->btemp_wq,
...@@ -806,7 +815,7 @@ static int ab8500_btemp_get_property(struct power_supply *psy, ...@@ -806,7 +815,7 @@ static int ab8500_btemp_get_property(struct power_supply *psy,
val->intval = 1; val->intval = 1;
break; break;
case POWER_SUPPLY_PROP_TECHNOLOGY: case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = di->bat->bat_type[di->bat->batt_id].name; val->intval = di->bm->bat_type[di->bm->batt_id].name;
break; break;
case POWER_SUPPLY_PROP_TEMP: case POWER_SUPPLY_PROP_TEMP:
val->intval = ab8500_btemp_get_temp(di); val->intval = ab8500_btemp_get_temp(di);
...@@ -967,6 +976,7 @@ static char *supply_interface[] = { ...@@ -967,6 +976,7 @@ static char *supply_interface[] = {
static int ab8500_btemp_probe(struct platform_device *pdev) static int ab8500_btemp_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct abx500_bm_data *plat = pdev->dev.platform_data;
struct ab8500_btemp *di; struct ab8500_btemp *di;
int irq, i, ret = 0; int irq, i, ret = 0;
u8 val; u8 val;
...@@ -976,21 +986,19 @@ static int ab8500_btemp_probe(struct platform_device *pdev) ...@@ -976,21 +986,19 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__); dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
return -ENOMEM; return -ENOMEM;
} }
di->bat = pdev->mfd_cell->platform_data;
if (!di->bat) { if (!plat) {
dev_err(&pdev->dev, "no battery management data supplied\n");
return -EINVAL;
}
di->bm = plat;
if (np) { if (np) {
ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev, "failed to get battery information\n");
"failed to get battery information\n");
return ret; return ret;
} }
} else {
dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n");
return -EINVAL;
}
} else {
dev_info(&pdev->dev, "falling back to legacy platform data\n");
} }
/* get parent data */ /* get parent data */
...@@ -998,6 +1006,8 @@ static int ab8500_btemp_probe(struct platform_device *pdev) ...@@ -998,6 +1006,8 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
di->parent = dev_get_drvdata(pdev->dev.parent); di->parent = dev_get_drvdata(pdev->dev.parent);
di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
di->initialized = false;
/* BTEMP supply */ /* BTEMP supply */
di->btemp_psy.name = "ab8500_btemp"; di->btemp_psy.name = "ab8500_btemp";
di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
...@@ -1022,10 +1032,6 @@ static int ab8500_btemp_probe(struct platform_device *pdev) ...@@ -1022,10 +1032,6 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
INIT_DEFERRABLE_WORK(&di->btemp_periodic_work, INIT_DEFERRABLE_WORK(&di->btemp_periodic_work,
ab8500_btemp_periodic_work); ab8500_btemp_periodic_work);
/* Identify the battery */
if (ab8500_btemp_id(di) < 0)
dev_warn(di->dev, "failed to identify the battery\n");
/* Set BTEMP thermal limits. Low and Med are fixed */ /* Set BTEMP thermal limits. Low and Med are fixed */
di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT; di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT; di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;
......
...@@ -79,6 +79,9 @@ ...@@ -79,6 +79,9 @@
/* Lowest charger voltage is 3.39V -> 0x4E */ /* Lowest charger voltage is 3.39V -> 0x4E */
#define LOW_VOLT_REG 0x4E #define LOW_VOLT_REG 0x4E
/* Step up/down delay in us */
#define STEP_UDELAY 1000
/* UsbLineStatus register - usb types */ /* UsbLineStatus register - usb types */
enum ab8500_charger_link_status { enum ab8500_charger_link_status {
USB_STAT_NOT_CONFIGURED, USB_STAT_NOT_CONFIGURED,
...@@ -186,7 +189,7 @@ struct ab8500_charger_usb_state { ...@@ -186,7 +189,7 @@ struct ab8500_charger_usb_state {
* @autopower_cfg platform specific power config support for "pwron after pwrloss" * @autopower_cfg platform specific power config support for "pwron after pwrloss"
* @parent: Pointer to the struct ab8500 * @parent: Pointer to the struct ab8500
* @gpadc: Pointer to the struct gpadc * @gpadc: Pointer to the struct gpadc
* @bat: Pointer to the abx500_bm platform data * @bm: Platform specific battery management information
* @flags: Structure for information about events triggered * @flags: Structure for information about events triggered
* @usb_state: Structure for usb stack information * @usb_state: Structure for usb stack information
* @ac_chg: AC charger power supply * @ac_chg: AC charger power supply
...@@ -223,7 +226,7 @@ struct ab8500_charger { ...@@ -223,7 +226,7 @@ struct ab8500_charger {
bool autopower_cfg; bool autopower_cfg;
struct ab8500 *parent; struct ab8500 *parent;
struct ab8500_gpadc *gpadc; struct ab8500_gpadc *gpadc;
struct abx500_bm_data *bat; struct abx500_bm_data *bm;
struct ab8500_charger_event_flags flags; struct ab8500_charger_event_flags flags;
struct ab8500_charger_usb_state usb_state; struct ab8500_charger_usb_state usb_state;
struct ux500_charger ac_chg; struct ux500_charger ac_chg;
...@@ -935,6 +938,88 @@ static int ab8500_charger_get_usb_cur(struct ab8500_charger *di) ...@@ -935,6 +938,88 @@ static int ab8500_charger_get_usb_cur(struct ab8500_charger *di)
return 0; return 0;
} }
/**
* ab8500_charger_set_current() - set charger current
* @di: pointer to the ab8500_charger structure
* @ich: charger current, in mA
* @reg: select what charger register to set
*
* Set charger current.
* There is no state machine in the AB to step up/down the charger
* current to avoid dips and spikes on MAIN, VBUS and VBAT when
* charging is started. Instead we need to implement
* this charger current step-up/down here.
* Returns error code in case of failure else 0(on success)
*/
static int ab8500_charger_set_current(struct ab8500_charger *di,
int ich, int reg)
{
int ret, i;
int curr_index, prev_curr_index, shift_value;
u8 reg_value;
switch (reg) {
case AB8500_MCH_IPT_CURLVL_REG:
shift_value = MAIN_CH_INPUT_CURR_SHIFT;
curr_index = ab8500_current_to_regval(ich);
break;
case AB8500_USBCH_IPT_CRNTLVL_REG:
shift_value = VBUS_IN_CURR_LIM_SHIFT;
curr_index = ab8500_vbus_in_curr_to_regval(ich);
break;
case AB8500_CH_OPT_CRNTLVL_REG:
shift_value = 0;
curr_index = ab8500_current_to_regval(ich);
break;
default:
dev_err(di->dev, "%s current register not valid\n", __func__);
return -ENXIO;
}
if (curr_index < 0) {
dev_err(di->dev, "requested current limit out-of-range\n");
return -ENXIO;
}
ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
reg, &reg_value);
if (ret < 0) {
dev_err(di->dev, "%s read failed\n", __func__);
return ret;
}
prev_curr_index = (reg_value >> shift_value);
/* only update current if it's been changed */
if (prev_curr_index == curr_index)
return 0;
dev_dbg(di->dev, "%s set charger current: %d mA for reg: 0x%02x\n",
__func__, ich, reg);
if (prev_curr_index > curr_index) {
for (i = prev_curr_index - 1; i >= curr_index; i--) {
ret = abx500_set_register_interruptible(di->dev,
AB8500_CHARGER, reg, (u8) i << shift_value);
if (ret) {
dev_err(di->dev, "%s write failed\n", __func__);
return ret;
}
usleep_range(STEP_UDELAY, STEP_UDELAY * 2);
}
} else {
for (i = prev_curr_index + 1; i <= curr_index; i++) {
ret = abx500_set_register_interruptible(di->dev,
AB8500_CHARGER, reg, (u8) i << shift_value);
if (ret) {
dev_err(di->dev, "%s write failed\n", __func__);
return ret;
}
usleep_range(STEP_UDELAY, STEP_UDELAY * 2);
}
}
return ret;
}
/** /**
* ab8500_charger_set_vbus_in_curr() - set VBUS input current limit * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit
* @di: pointer to the ab8500_charger structure * @di: pointer to the ab8500_charger structure
...@@ -946,12 +1031,10 @@ static int ab8500_charger_get_usb_cur(struct ab8500_charger *di) ...@@ -946,12 +1031,10 @@ static int ab8500_charger_get_usb_cur(struct ab8500_charger *di)
static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di,
int ich_in) int ich_in)
{ {
int ret;
int input_curr_index;
int min_value; int min_value;
/* We should always use to lowest current limit */ /* We should always use to lowest current limit */
min_value = min(di->bat->chg_params->usb_curr_max, ich_in); min_value = min(di->bm->chg_params->usb_curr_max, ich_in);
switch (min_value) { switch (min_value) {
case 100: case 100:
...@@ -966,19 +1049,38 @@ static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, ...@@ -966,19 +1049,38 @@ static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di,
break; break;
} }
input_curr_index = ab8500_vbus_in_curr_to_regval(min_value); return ab8500_charger_set_current(di, min_value,
if (input_curr_index < 0) { AB8500_USBCH_IPT_CRNTLVL_REG);
dev_err(di->dev, "VBUS input current limit too high\n"); }
return -ENXIO;
}
ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, /**
AB8500_USBCH_IPT_CRNTLVL_REG, * ab8500_charger_set_main_in_curr() - set main charger input current
input_curr_index << VBUS_IN_CURR_LIM_SHIFT); * @di: pointer to the ab8500_charger structure
if (ret) * @ich_in: input charger current, in mA
dev_err(di->dev, "%s write failed\n", __func__); *
* Set main charger input current.
* Returns error code in case of failure else 0(on success)
*/
static int ab8500_charger_set_main_in_curr(struct ab8500_charger *di,
int ich_in)
{
return ab8500_charger_set_current(di, ich_in,
AB8500_MCH_IPT_CURLVL_REG);
}
return ret; /**
* ab8500_charger_set_output_curr() - set charger output current
* @di: pointer to the ab8500_charger structure
* @ich_out: output charger current, in mA
*
* Set charger output current.
* Returns error code in case of failure else 0(on success)
*/
static int ab8500_charger_set_output_curr(struct ab8500_charger *di,
int ich_out)
{
return ab8500_charger_set_current(di, ich_out,
AB8500_CH_OPT_CRNTLVL_REG);
} }
/** /**
...@@ -1074,7 +1176,7 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, ...@@ -1074,7 +1176,7 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger,
volt_index = ab8500_voltage_to_regval(vset); volt_index = ab8500_voltage_to_regval(vset);
curr_index = ab8500_current_to_regval(iset); curr_index = ab8500_current_to_regval(iset);
input_curr_index = ab8500_current_to_regval( input_curr_index = ab8500_current_to_regval(
di->bat->chg_params->ac_curr_max); di->bm->chg_params->ac_curr_max);
if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) { if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) {
dev_err(di->dev, dev_err(di->dev,
"Charger voltage or current too high, " "Charger voltage or current too high, "
...@@ -1090,23 +1192,24 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, ...@@ -1090,23 +1192,24 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger,
return ret; return ret;
} }
/* MainChInputCurr: current that can be drawn from the charger*/ /* MainChInputCurr: current that can be drawn from the charger*/
ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, ret = ab8500_charger_set_main_in_curr(di,
AB8500_MCH_IPT_CURLVL_REG, di->bm->chg_params->ac_curr_max);
input_curr_index << MAIN_CH_INPUT_CURR_SHIFT);
if (ret) { if (ret) {
dev_err(di->dev, "%s write failed\n", __func__); dev_err(di->dev, "%s Failed to set MainChInputCurr\n",
__func__);
return ret; return ret;
} }
/* ChOutputCurentLevel: protected output current */ /* ChOutputCurentLevel: protected output current */
ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, ret = ab8500_charger_set_output_curr(di, iset);
AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index);
if (ret) { if (ret) {
dev_err(di->dev, "%s write failed\n", __func__); dev_err(di->dev, "%s "
"Failed to set ChOutputCurentLevel\n",
__func__);
return ret; return ret;
} }
/* Check if VBAT overshoot control should be enabled */ /* Check if VBAT overshoot control should be enabled */
if (!di->bat->enable_overshoot) if (!di->bm->enable_overshoot)
overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N; overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N;
/* Enable Main Charger */ /* Enable Main Charger */
...@@ -1158,12 +1261,11 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, ...@@ -1158,12 +1261,11 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger,
return ret; return ret;
} }
ret = abx500_set_register_interruptible(di->dev, ret = ab8500_charger_set_output_curr(di, 0);
AB8500_CHARGER,
AB8500_CH_OPT_CRNTLVL_REG, CH_OP_CUR_LVL_0P1);
if (ret) { if (ret) {
dev_err(di->dev, dev_err(di->dev, "%s "
"%s write failed\n", __func__); "Failed to set ChOutputCurentLevel\n",
__func__);
return ret; return ret;
} }
} else { } else {
...@@ -1266,14 +1368,15 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, ...@@ -1266,14 +1368,15 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
return ret; return ret;
} }
/* ChOutputCurentLevel: protected output current */ /* ChOutputCurentLevel: protected output current */
ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, ret = ab8500_charger_set_output_curr(di, ich_out);
AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index);
if (ret) { if (ret) {
dev_err(di->dev, "%s write failed\n", __func__); dev_err(di->dev, "%s "
"Failed to set ChOutputCurentLevel\n",
__func__);
return ret; return ret;
} }
/* Check if VBAT overshoot control should be enabled */ /* Check if VBAT overshoot control should be enabled */
if (!di->bat->enable_overshoot) if (!di->bm->enable_overshoot)
overshoot = USB_CHG_NO_OVERSHOOT_ENA_N; overshoot = USB_CHG_NO_OVERSHOOT_ENA_N;
/* Enable USB Charger */ /* Enable USB Charger */
...@@ -1366,7 +1469,6 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger, ...@@ -1366,7 +1469,6 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
int ich_out) int ich_out)
{ {
int ret; int ret;
int curr_index;
struct ab8500_charger *di; struct ab8500_charger *di;
if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
...@@ -1376,18 +1478,11 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger, ...@@ -1376,18 +1478,11 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
else else
return -ENXIO; return -ENXIO;
curr_index = ab8500_current_to_regval(ich_out); ret = ab8500_charger_set_output_curr(di, ich_out);
if (curr_index < 0) {
dev_err(di->dev,
"Charger current too high, "
"charging not started\n");
return -ENXIO;
}
ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index);
if (ret) { if (ret) {
dev_err(di->dev, "%s write failed\n", __func__); dev_err(di->dev, "%s "
"Failed to set ChOutputCurentLevel\n",
__func__);
return ret; return ret;
} }
...@@ -2359,8 +2454,8 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) ...@@ -2359,8 +2454,8 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
ret = abx500_set_register_interruptible(di->dev, ret = abx500_set_register_interruptible(di->dev,
AB8500_RTC, AB8500_RTC,
AB8500_RTC_BACKUP_CHG_REG, AB8500_RTC_BACKUP_CHG_REG,
di->bat->bkup_bat_v | di->bm->bkup_bat_v |
di->bat->bkup_bat_i); di->bm->bkup_bat_i);
if (ret) { if (ret) {
dev_err(di->dev, "failed to setup backup battery charging\n"); dev_err(di->dev, "failed to setup backup battery charging\n");
goto out; goto out;
...@@ -2541,6 +2636,7 @@ static char *supply_interface[] = { ...@@ -2541,6 +2636,7 @@ static char *supply_interface[] = {
static int ab8500_charger_probe(struct platform_device *pdev) static int ab8500_charger_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct abx500_bm_data *plat = pdev->dev.platform_data;
struct ab8500_charger *di; struct ab8500_charger *di;
int irq, i, charger_status, ret = 0; int irq, i, charger_status, ret = 0;
...@@ -2549,24 +2645,22 @@ static int ab8500_charger_probe(struct platform_device *pdev) ...@@ -2549,24 +2645,22 @@ static int ab8500_charger_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__);
return -ENOMEM; return -ENOMEM;
} }
di->bat = pdev->mfd_cell->platform_data;
if (!di->bat) { if (!plat) {
dev_err(&pdev->dev, "no battery management data supplied\n");
return -EINVAL;
}
di->bm = plat;
if (np) { if (np) {
ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev, "failed to get battery information\n");
"failed to get battery information\n");
return ret; return ret;
} }
di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
} else { } else
dev_err(&pdev->dev, "missing dt node for ab8500_charger\n");
return -EINVAL;
}
} else {
dev_info(&pdev->dev, "falling back to legacy platform data\n");
di->autopower_cfg = false; di->autopower_cfg = false;
}
/* get parent data */ /* get parent data */
di->dev = &pdev->dev; di->dev = &pdev->dev;
......
...@@ -173,7 +173,7 @@ struct inst_curr_result_list { ...@@ -173,7 +173,7 @@ struct inst_curr_result_list {
* @avg_cap: Average capacity filter * @avg_cap: Average capacity filter
* @parent: Pointer to the struct ab8500 * @parent: Pointer to the struct ab8500
* @gpadc: Pointer to the struct gpadc * @gpadc: Pointer to the struct gpadc
* @bat: Pointer to the abx500_bm platform data * @bm: Platform specific battery management information
* @fg_psy: Structure that holds the FG specific battery properties * @fg_psy: Structure that holds the FG specific battery properties
* @fg_wq: Work queue for running the FG algorithm * @fg_wq: Work queue for running the FG algorithm
* @fg_periodic_work: Work to run the FG algorithm periodically * @fg_periodic_work: Work to run the FG algorithm periodically
...@@ -212,7 +212,7 @@ struct ab8500_fg { ...@@ -212,7 +212,7 @@ struct ab8500_fg {
struct ab8500_fg_avg_cap avg_cap; struct ab8500_fg_avg_cap avg_cap;
struct ab8500 *parent; struct ab8500 *parent;
struct ab8500_gpadc *gpadc; struct ab8500_gpadc *gpadc;
struct abx500_bm_data *bat; struct abx500_bm_data *bm;
struct power_supply fg_psy; struct power_supply fg_psy;
struct workqueue_struct *fg_wq; struct workqueue_struct *fg_wq;
struct delayed_work fg_periodic_work; struct delayed_work fg_periodic_work;
...@@ -355,7 +355,7 @@ static int ab8500_fg_is_low_curr(struct ab8500_fg *di, int curr) ...@@ -355,7 +355,7 @@ static int ab8500_fg_is_low_curr(struct ab8500_fg *di, int curr)
/* /*
* We want to know if we're in low current mode * We want to know if we're in low current mode
*/ */
if (curr > -di->bat->fg_params->high_curr_threshold) if (curr > -di->bm->fg_params->high_curr_threshold)
return true; return true;
else else
return false; return false;
...@@ -484,8 +484,9 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable) ...@@ -484,8 +484,9 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable)
di->flags.fg_enabled = true; di->flags.fg_enabled = true;
} else { } else {
/* Clear any pending read requests */ /* Clear any pending read requests */
ret = abx500_set_register_interruptible(di->dev, ret = abx500_mask_and_set_register_interruptible(di->dev,
AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, 0); AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
(RESET_ACCU | READ_REQ), 0);
if (ret) if (ret)
goto cc_err; goto cc_err;
...@@ -647,7 +648,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) ...@@ -647,7 +648,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
* 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm
*/ */
val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) / val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) /
(1000 * di->bat->fg_res); (1000 * di->bm->fg_res);
if (di->turn_off_fg) { if (di->turn_off_fg) {
dev_dbg(di->dev, "%s Disable FG\n", __func__); dev_dbg(di->dev, "%s Disable FG\n", __func__);
...@@ -750,7 +751,7 @@ static void ab8500_fg_acc_cur_work(struct work_struct *work) ...@@ -750,7 +751,7 @@ static void ab8500_fg_acc_cur_work(struct work_struct *work)
* 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm
*/ */
di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10) / di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10) /
(100 * di->bat->fg_res); (100 * di->bm->fg_res);
/* /*
* Convert to unit value in mA * Convert to unit value in mA
...@@ -762,7 +763,7 @@ static void ab8500_fg_acc_cur_work(struct work_struct *work) ...@@ -762,7 +763,7 @@ static void ab8500_fg_acc_cur_work(struct work_struct *work)
* 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm
*/ */
di->avg_curr = (val * QLSB_NANO_AMP_HOURS_X10 * 36) / di->avg_curr = (val * QLSB_NANO_AMP_HOURS_X10 * 36) /
(1000 * di->bat->fg_res * (di->fg_samples / 4)); (1000 * di->bm->fg_res * (di->fg_samples / 4));
di->flags.conv_done = true; di->flags.conv_done = true;
...@@ -814,8 +815,8 @@ static int ab8500_fg_volt_to_capacity(struct ab8500_fg *di, int voltage) ...@@ -814,8 +815,8 @@ static int ab8500_fg_volt_to_capacity(struct ab8500_fg *di, int voltage)
struct abx500_v_to_cap *tbl; struct abx500_v_to_cap *tbl;
int cap = 0; int cap = 0;
tbl = di->bat->bat_type[di->bat->batt_id].v_to_cap_tbl, tbl = di->bm->bat_type[di->bm->batt_id].v_to_cap_tbl,
tbl_size = di->bat->bat_type[di->bat->batt_id].n_v_cap_tbl_elements; tbl_size = di->bm->bat_type[di->bm->batt_id].n_v_cap_tbl_elements;
for (i = 0; i < tbl_size; ++i) { for (i = 0; i < tbl_size; ++i) {
if (voltage > tbl[i].voltage) if (voltage > tbl[i].voltage)
...@@ -866,8 +867,8 @@ static int ab8500_fg_battery_resistance(struct ab8500_fg *di) ...@@ -866,8 +867,8 @@ static int ab8500_fg_battery_resistance(struct ab8500_fg *di)
struct batres_vs_temp *tbl; struct batres_vs_temp *tbl;
int resist = 0; int resist = 0;
tbl = di->bat->bat_type[di->bat->batt_id].batres_tbl; tbl = di->bm->bat_type[di->bm->batt_id].batres_tbl;
tbl_size = di->bat->bat_type[di->bat->batt_id].n_batres_tbl_elements; tbl_size = di->bm->bat_type[di->bm->batt_id].n_batres_tbl_elements;
for (i = 0; i < tbl_size; ++i) { for (i = 0; i < tbl_size; ++i) {
if (di->bat_temp / 10 > tbl[i].temp) if (di->bat_temp / 10 > tbl[i].temp)
...@@ -888,11 +889,11 @@ static int ab8500_fg_battery_resistance(struct ab8500_fg *di) ...@@ -888,11 +889,11 @@ static int ab8500_fg_battery_resistance(struct ab8500_fg *di)
dev_dbg(di->dev, "%s Temp: %d battery internal resistance: %d" dev_dbg(di->dev, "%s Temp: %d battery internal resistance: %d"
" fg resistance %d, total: %d (mOhm)\n", " fg resistance %d, total: %d (mOhm)\n",
__func__, di->bat_temp, resist, di->bat->fg_res / 10, __func__, di->bat_temp, resist, di->bm->fg_res / 10,
(di->bat->fg_res / 10) + resist); (di->bm->fg_res / 10) + resist);
/* fg_res variable is in 0.1mOhm */ /* fg_res variable is in 0.1mOhm */
resist += di->bat->fg_res / 10; resist += di->bm->fg_res / 10;
return resist; return resist;
} }
...@@ -1110,14 +1111,14 @@ static int ab8500_fg_capacity_level(struct ab8500_fg *di) ...@@ -1110,14 +1111,14 @@ static int ab8500_fg_capacity_level(struct ab8500_fg *di)
percent = di->bat_cap.permille / 10; percent = di->bat_cap.permille / 10;
if (percent <= di->bat->cap_levels->critical || if (percent <= di->bm->cap_levels->critical ||
di->flags.low_bat) di->flags.low_bat)
ret = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; ret = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
else if (percent <= di->bat->cap_levels->low) else if (percent <= di->bm->cap_levels->low)
ret = POWER_SUPPLY_CAPACITY_LEVEL_LOW; ret = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
else if (percent <= di->bat->cap_levels->normal) else if (percent <= di->bm->cap_levels->normal)
ret = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; ret = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
else if (percent <= di->bat->cap_levels->high) else if (percent <= di->bm->cap_levels->high)
ret = POWER_SUPPLY_CAPACITY_LEVEL_HIGH; ret = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
else else
ret = POWER_SUPPLY_CAPACITY_LEVEL_FULL; ret = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
...@@ -1182,7 +1183,7 @@ static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init) ...@@ -1182,7 +1183,7 @@ static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init)
di->bat_cap.prev_percent != di->bat_cap.prev_percent !=
(di->bat_cap.permille) / 10 && (di->bat_cap.permille) / 10 &&
(di->bat_cap.permille / 10) < (di->bat_cap.permille / 10) <
di->bat->fg_params->maint_thres) { di->bm->fg_params->maint_thres) {
dev_dbg(di->dev, dev_dbg(di->dev,
"battery reported full " "battery reported full "
"but capacity dropping: %d\n", "but capacity dropping: %d\n",
...@@ -1284,7 +1285,7 @@ static void ab8500_fg_algorithm_charging(struct ab8500_fg *di) ...@@ -1284,7 +1285,7 @@ static void ab8500_fg_algorithm_charging(struct ab8500_fg *di)
switch (di->charge_state) { switch (di->charge_state) {
case AB8500_FG_CHARGE_INIT: case AB8500_FG_CHARGE_INIT:
di->fg_samples = SEC_TO_SAMPLE( di->fg_samples = SEC_TO_SAMPLE(
di->bat->fg_params->accu_charging); di->bm->fg_params->accu_charging);
ab8500_fg_coulomb_counter(di, true); ab8500_fg_coulomb_counter(di, true);
ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_READOUT); ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_READOUT);
...@@ -1346,8 +1347,8 @@ static bool check_sysfs_capacity(struct ab8500_fg *di) ...@@ -1346,8 +1347,8 @@ static bool check_sysfs_capacity(struct ab8500_fg *di)
cap_permille = ab8500_fg_convert_mah_to_permille(di, cap_permille = ab8500_fg_convert_mah_to_permille(di,
di->bat_cap.user_mah); di->bat_cap.user_mah);
lower = di->bat_cap.permille - di->bat->fg_params->user_cap_limit * 10; lower = di->bat_cap.permille - di->bm->fg_params->user_cap_limit * 10;
upper = di->bat_cap.permille + di->bat->fg_params->user_cap_limit * 10; upper = di->bat_cap.permille + di->bm->fg_params->user_cap_limit * 10;
if (lower < 0) if (lower < 0)
lower = 0; lower = 0;
...@@ -1387,7 +1388,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) ...@@ -1387,7 +1388,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
case AB8500_FG_DISCHARGE_INIT: case AB8500_FG_DISCHARGE_INIT:
/* We use the FG IRQ to work on */ /* We use the FG IRQ to work on */
di->init_cnt = 0; di->init_cnt = 0;
di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer); di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer);
ab8500_fg_coulomb_counter(di, true); ab8500_fg_coulomb_counter(di, true);
ab8500_fg_discharge_state_to(di, ab8500_fg_discharge_state_to(di,
AB8500_FG_DISCHARGE_INITMEASURING); AB8500_FG_DISCHARGE_INITMEASURING);
...@@ -1400,18 +1401,17 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) ...@@ -1400,18 +1401,17 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
* samples to get an initial capacity. * samples to get an initial capacity.
* Then go to READOUT * Then go to READOUT
*/ */
sleep_time = di->bat->fg_params->init_timer; sleep_time = di->bm->fg_params->init_timer;
/* Discard the first [x] seconds */ /* Discard the first [x] seconds */
if (di->init_cnt > if (di->init_cnt > di->bm->fg_params->init_discard_time) {
di->bat->fg_params->init_discard_time) {
ab8500_fg_calc_cap_discharge_voltage(di, true); ab8500_fg_calc_cap_discharge_voltage(di, true);
ab8500_fg_check_capacity_limits(di, true); ab8500_fg_check_capacity_limits(di, true);
} }
di->init_cnt += sleep_time; di->init_cnt += sleep_time;
if (di->init_cnt > di->bat->fg_params->init_total_time) if (di->init_cnt > di->bm->fg_params->init_total_time)
ab8500_fg_discharge_state_to(di, ab8500_fg_discharge_state_to(di,
AB8500_FG_DISCHARGE_READOUT_INIT); AB8500_FG_DISCHARGE_READOUT_INIT);
...@@ -1426,7 +1426,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) ...@@ -1426,7 +1426,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
/* Intentional fallthrough */ /* Intentional fallthrough */
case AB8500_FG_DISCHARGE_RECOVERY: case AB8500_FG_DISCHARGE_RECOVERY:
sleep_time = di->bat->fg_params->recovery_sleep_timer; sleep_time = di->bm->fg_params->recovery_sleep_timer;
/* /*
* We should check the power consumption * We should check the power consumption
...@@ -1438,9 +1438,9 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) ...@@ -1438,9 +1438,9 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
if (ab8500_fg_is_low_curr(di, di->inst_curr)) { if (ab8500_fg_is_low_curr(di, di->inst_curr)) {
if (di->recovery_cnt > if (di->recovery_cnt >
di->bat->fg_params->recovery_total_time) { di->bm->fg_params->recovery_total_time) {
di->fg_samples = SEC_TO_SAMPLE( di->fg_samples = SEC_TO_SAMPLE(
di->bat->fg_params->accu_high_curr); di->bm->fg_params->accu_high_curr);
ab8500_fg_coulomb_counter(di, true); ab8500_fg_coulomb_counter(di, true);
ab8500_fg_discharge_state_to(di, ab8500_fg_discharge_state_to(di,
AB8500_FG_DISCHARGE_READOUT); AB8500_FG_DISCHARGE_READOUT);
...@@ -1453,7 +1453,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) ...@@ -1453,7 +1453,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
di->recovery_cnt += sleep_time; di->recovery_cnt += sleep_time;
} else { } else {
di->fg_samples = SEC_TO_SAMPLE( di->fg_samples = SEC_TO_SAMPLE(
di->bat->fg_params->accu_high_curr); di->bm->fg_params->accu_high_curr);
ab8500_fg_coulomb_counter(di, true); ab8500_fg_coulomb_counter(di, true);
ab8500_fg_discharge_state_to(di, ab8500_fg_discharge_state_to(di,
AB8500_FG_DISCHARGE_READOUT); AB8500_FG_DISCHARGE_READOUT);
...@@ -1462,7 +1462,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) ...@@ -1462,7 +1462,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
case AB8500_FG_DISCHARGE_READOUT_INIT: case AB8500_FG_DISCHARGE_READOUT_INIT:
di->fg_samples = SEC_TO_SAMPLE( di->fg_samples = SEC_TO_SAMPLE(
di->bat->fg_params->accu_high_curr); di->bm->fg_params->accu_high_curr);
ab8500_fg_coulomb_counter(di, true); ab8500_fg_coulomb_counter(di, true);
ab8500_fg_discharge_state_to(di, ab8500_fg_discharge_state_to(di,
AB8500_FG_DISCHARGE_READOUT); AB8500_FG_DISCHARGE_READOUT);
...@@ -1509,9 +1509,9 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) ...@@ -1509,9 +1509,9 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
} }
di->high_curr_cnt += di->high_curr_cnt +=
di->bat->fg_params->accu_high_curr; di->bm->fg_params->accu_high_curr;
if (di->high_curr_cnt > if (di->high_curr_cnt >
di->bat->fg_params->high_curr_time) di->bm->fg_params->high_curr_time)
di->recovery_needed = true; di->recovery_needed = true;
ab8500_fg_calc_cap_discharge_fg(di); ab8500_fg_calc_cap_discharge_fg(di);
...@@ -1528,7 +1528,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) ...@@ -1528,7 +1528,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
ab8500_fg_calc_cap_discharge_voltage(di, true); ab8500_fg_calc_cap_discharge_voltage(di, true);
di->fg_samples = SEC_TO_SAMPLE( di->fg_samples = SEC_TO_SAMPLE(
di->bat->fg_params->accu_high_curr); di->bm->fg_params->accu_high_curr);
ab8500_fg_coulomb_counter(di, true); ab8500_fg_coulomb_counter(di, true);
ab8500_fg_discharge_state_to(di, ab8500_fg_discharge_state_to(di,
AB8500_FG_DISCHARGE_READOUT); AB8500_FG_DISCHARGE_READOUT);
...@@ -1721,7 +1721,7 @@ static void ab8500_fg_low_bat_work(struct work_struct *work) ...@@ -1721,7 +1721,7 @@ static void ab8500_fg_low_bat_work(struct work_struct *work)
vbat = ab8500_fg_bat_voltage(di); vbat = ab8500_fg_bat_voltage(di);
/* Check if LOW_BAT still fulfilled */ /* Check if LOW_BAT still fulfilled */
if (vbat < di->bat->fg_params->lowbat_threshold) { if (vbat < di->bm->fg_params->lowbat_threshold) {
di->flags.low_bat = true; di->flags.low_bat = true;
dev_warn(di->dev, "Battery voltage still LOW\n"); dev_warn(di->dev, "Battery voltage still LOW\n");
...@@ -1779,8 +1779,8 @@ static int ab8500_fg_battok_init_hw_register(struct ab8500_fg *di) ...@@ -1779,8 +1779,8 @@ static int ab8500_fg_battok_init_hw_register(struct ab8500_fg *di)
int ret; int ret;
int new_val; int new_val;
sel0 = di->bat->fg_params->battok_falling_th_sel0; sel0 = di->bm->fg_params->battok_falling_th_sel0;
sel1 = di->bat->fg_params->battok_raising_th_sel1; sel1 = di->bm->fg_params->battok_raising_th_sel1;
cbp_sel0 = ab8500_fg_battok_calc(di, sel0); cbp_sel0 = ab8500_fg_battok_calc(di, sel0);
cbp_sel1 = ab8500_fg_battok_calc(di, sel1); cbp_sel1 = ab8500_fg_battok_calc(di, sel1);
...@@ -1963,7 +1963,7 @@ static int ab8500_fg_get_property(struct power_supply *psy, ...@@ -1963,7 +1963,7 @@ static int ab8500_fg_get_property(struct power_supply *psy,
di->bat_cap.max_mah); di->bat_cap.max_mah);
break; break;
case POWER_SUPPLY_PROP_ENERGY_NOW: case POWER_SUPPLY_PROP_ENERGY_NOW:
if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
di->flags.batt_id_received) di->flags.batt_id_received)
val->intval = ab8500_fg_convert_mah_to_uwh(di, val->intval = ab8500_fg_convert_mah_to_uwh(di,
di->bat_cap.max_mah); di->bat_cap.max_mah);
...@@ -1978,21 +1978,21 @@ static int ab8500_fg_get_property(struct power_supply *psy, ...@@ -1978,21 +1978,21 @@ static int ab8500_fg_get_property(struct power_supply *psy,
val->intval = di->bat_cap.max_mah; val->intval = di->bat_cap.max_mah;
break; break;
case POWER_SUPPLY_PROP_CHARGE_NOW: case POWER_SUPPLY_PROP_CHARGE_NOW:
if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
di->flags.batt_id_received) di->flags.batt_id_received)
val->intval = di->bat_cap.max_mah; val->intval = di->bat_cap.max_mah;
else else
val->intval = di->bat_cap.prev_mah; val->intval = di->bat_cap.prev_mah;
break; break;
case POWER_SUPPLY_PROP_CAPACITY: case POWER_SUPPLY_PROP_CAPACITY:
if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
di->flags.batt_id_received) di->flags.batt_id_received)
val->intval = 100; val->intval = 100;
else else
val->intval = di->bat_cap.prev_percent; val->intval = di->bat_cap.prev_percent;
break; break;
case POWER_SUPPLY_PROP_CAPACITY_LEVEL: case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
di->flags.batt_id_received) di->flags.batt_id_received)
val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
else else
...@@ -2078,7 +2078,7 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data) ...@@ -2078,7 +2078,7 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
if (!di->flags.batt_id_received) { if (!di->flags.batt_id_received) {
const struct abx500_battery_type *b; const struct abx500_battery_type *b;
b = &(di->bat->bat_type[di->bat->batt_id]); b = &(di->bm->bat_type[di->bm->batt_id]);
di->flags.batt_id_received = true; di->flags.batt_id_received = true;
...@@ -2155,7 +2155,7 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg *di) ...@@ -2155,7 +2155,7 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg *di)
AB8500_SYS_CTRL2_BLOCK, AB8500_SYS_CTRL2_BLOCK,
AB8500_LOW_BAT_REG, AB8500_LOW_BAT_REG,
ab8500_volt_to_regval( ab8500_volt_to_regval(
di->bat->fg_params->lowbat_threshold) << 1 | di->bm->fg_params->lowbat_threshold) << 1 |
LOW_BAT_ENABLE); LOW_BAT_ENABLE);
if (ret) { if (ret) {
dev_err(di->dev, "%s write failed\n", __func__); dev_err(di->dev, "%s write failed\n", __func__);
...@@ -2448,6 +2448,7 @@ static char *supply_interface[] = { ...@@ -2448,6 +2448,7 @@ static char *supply_interface[] = {
static int ab8500_fg_probe(struct platform_device *pdev) static int ab8500_fg_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct abx500_bm_data *plat = pdev->dev.platform_data;
struct ab8500_fg *di; struct ab8500_fg *di;
int i, irq; int i, irq;
int ret = 0; int ret = 0;
...@@ -2457,21 +2458,19 @@ static int ab8500_fg_probe(struct platform_device *pdev) ...@@ -2457,21 +2458,19 @@ static int ab8500_fg_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__); dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__);
return -ENOMEM; return -ENOMEM;
} }
di->bat = pdev->mfd_cell->platform_data;
if (!di->bat) { if (!plat) {
dev_err(&pdev->dev, "no battery management data supplied\n");
return -EINVAL;
}
di->bm = plat;
if (np) { if (np) {
ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev, "failed to get battery information\n");
"failed to get battery information\n");
return ret; return ret;
} }
} else {
dev_err(&pdev->dev, "missing dt node for ab8500_fg\n");
return -EINVAL;
}
} else {
dev_info(&pdev->dev, "falling back to legacy platform data\n");
} }
mutex_init(&di->cc_lock); mutex_init(&di->cc_lock);
...@@ -2491,11 +2490,11 @@ static int ab8500_fg_probe(struct platform_device *pdev) ...@@ -2491,11 +2490,11 @@ static int ab8500_fg_probe(struct platform_device *pdev)
di->fg_psy.external_power_changed = ab8500_fg_external_power_changed; di->fg_psy.external_power_changed = ab8500_fg_external_power_changed;
di->bat_cap.max_mah_design = MILLI_TO_MICRO * di->bat_cap.max_mah_design = MILLI_TO_MICRO *
di->bat->bat_type[di->bat->batt_id].charge_full_design; di->bm->bat_type[di->bm->batt_id].charge_full_design;
di->bat_cap.max_mah = di->bat_cap.max_mah_design; di->bat_cap.max_mah = di->bat_cap.max_mah_design;
di->vbat_nom = di->bat->bat_type[di->bat->batt_id].nominal_voltage; di->vbat_nom = di->bm->bat_type[di->bm->batt_id].nominal_voltage;
di->init_capacity = true; di->init_capacity = true;
...@@ -2549,7 +2548,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) ...@@ -2549,7 +2548,7 @@ static int ab8500_fg_probe(struct platform_device *pdev)
goto free_inst_curr_wq; goto free_inst_curr_wq;
} }
di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer); di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer);
ab8500_fg_coulomb_counter(di, true); ab8500_fg_coulomb_counter(di, true);
/* Initialize completion used to notify completion of inst current */ /* Initialize completion used to notify completion of inst current */
......
...@@ -207,7 +207,7 @@ enum maxim_ret { ...@@ -207,7 +207,7 @@ enum maxim_ret {
* @chg_info: information about connected charger types * @chg_info: information about connected charger types
* @batt_data: data of the battery * @batt_data: data of the battery
* @susp_status: current charger suspension status * @susp_status: current charger suspension status
* @bat: pointer to the abx500_bm platform data * @bm: Platform specific battery management information
* @chargalg_psy: structure that holds the battery properties exposed by * @chargalg_psy: structure that holds the battery properties exposed by
* the charging algorithm * the charging algorithm
* @events: structure for information about events triggered * @events: structure for information about events triggered
...@@ -232,7 +232,7 @@ struct abx500_chargalg { ...@@ -232,7 +232,7 @@ struct abx500_chargalg {
struct abx500_chargalg_charger_info chg_info; struct abx500_chargalg_charger_info chg_info;
struct abx500_chargalg_battery_data batt_data; struct abx500_chargalg_battery_data batt_data;
struct abx500_chargalg_suspension_status susp_status; struct abx500_chargalg_suspension_status susp_status;
struct abx500_bm_data *bat; struct abx500_bm_data *bm;
struct power_supply chargalg_psy; struct power_supply chargalg_psy;
struct ux500_charger *ac_chg; struct ux500_charger *ac_chg;
struct ux500_charger *usb_chg; struct ux500_charger *usb_chg;
...@@ -367,13 +367,13 @@ static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di) ...@@ -367,13 +367,13 @@ static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di)
case AC_CHG: case AC_CHG:
timer_expiration = timer_expiration =
round_jiffies(jiffies + round_jiffies(jiffies +
(di->bat->main_safety_tmr_h * 3600 * HZ)); (di->bm->main_safety_tmr_h * 3600 * HZ));
break; break;
case USB_CHG: case USB_CHG:
timer_expiration = timer_expiration =
round_jiffies(jiffies + round_jiffies(jiffies +
(di->bat->usb_safety_tmr_h * 3600 * HZ)); (di->bm->usb_safety_tmr_h * 3600 * HZ));
break; break;
default: default:
...@@ -638,32 +638,32 @@ static void abx500_chargalg_start_charging(struct abx500_chargalg *di, ...@@ -638,32 +638,32 @@ static void abx500_chargalg_start_charging(struct abx500_chargalg *di,
*/ */
static void abx500_chargalg_check_temp(struct abx500_chargalg *di) static void abx500_chargalg_check_temp(struct abx500_chargalg *di)
{ {
if (di->batt_data.temp > (di->bat->temp_low + di->t_hyst_norm) && if (di->batt_data.temp > (di->bm->temp_low + di->t_hyst_norm) &&
di->batt_data.temp < (di->bat->temp_high - di->t_hyst_norm)) { di->batt_data.temp < (di->bm->temp_high - di->t_hyst_norm)) {
/* Temp OK! */ /* Temp OK! */
di->events.btemp_underover = false; di->events.btemp_underover = false;
di->events.btemp_lowhigh = false; di->events.btemp_lowhigh = false;
di->t_hyst_norm = 0; di->t_hyst_norm = 0;
di->t_hyst_lowhigh = 0; di->t_hyst_lowhigh = 0;
} else { } else {
if (((di->batt_data.temp >= di->bat->temp_high) && if (((di->batt_data.temp >= di->bm->temp_high) &&
(di->batt_data.temp < (di->batt_data.temp <
(di->bat->temp_over - di->t_hyst_lowhigh))) || (di->bm->temp_over - di->t_hyst_lowhigh))) ||
((di->batt_data.temp > ((di->batt_data.temp >
(di->bat->temp_under + di->t_hyst_lowhigh)) && (di->bm->temp_under + di->t_hyst_lowhigh)) &&
(di->batt_data.temp <= di->bat->temp_low))) { (di->batt_data.temp <= di->bm->temp_low))) {
/* TEMP minor!!!!! */ /* TEMP minor!!!!! */
di->events.btemp_underover = false; di->events.btemp_underover = false;
di->events.btemp_lowhigh = true; di->events.btemp_lowhigh = true;
di->t_hyst_norm = di->bat->temp_hysteresis; di->t_hyst_norm = di->bm->temp_hysteresis;
di->t_hyst_lowhigh = 0; di->t_hyst_lowhigh = 0;
} else if (di->batt_data.temp <= di->bat->temp_under || } else if (di->batt_data.temp <= di->bm->temp_under ||
di->batt_data.temp >= di->bat->temp_over) { di->batt_data.temp >= di->bm->temp_over) {
/* TEMP major!!!!! */ /* TEMP major!!!!! */
di->events.btemp_underover = true; di->events.btemp_underover = true;
di->events.btemp_lowhigh = false; di->events.btemp_lowhigh = false;
di->t_hyst_norm = 0; di->t_hyst_norm = 0;
di->t_hyst_lowhigh = di->bat->temp_hysteresis; di->t_hyst_lowhigh = di->bm->temp_hysteresis;
} else { } else {
/* Within hysteresis */ /* Within hysteresis */
dev_dbg(di->dev, "Within hysteresis limit temp: %d " dev_dbg(di->dev, "Within hysteresis limit temp: %d "
...@@ -682,12 +682,12 @@ static void abx500_chargalg_check_temp(struct abx500_chargalg *di) ...@@ -682,12 +682,12 @@ static void abx500_chargalg_check_temp(struct abx500_chargalg *di)
*/ */
static void abx500_chargalg_check_charger_voltage(struct abx500_chargalg *di) static void abx500_chargalg_check_charger_voltage(struct abx500_chargalg *di)
{ {
if (di->chg_info.usb_volt > di->bat->chg_params->usb_volt_max) if (di->chg_info.usb_volt > di->bm->chg_params->usb_volt_max)
di->chg_info.usb_chg_ok = false; di->chg_info.usb_chg_ok = false;
else else
di->chg_info.usb_chg_ok = true; di->chg_info.usb_chg_ok = true;
if (di->chg_info.ac_volt > di->bat->chg_params->ac_volt_max) if (di->chg_info.ac_volt > di->bm->chg_params->ac_volt_max)
di->chg_info.ac_chg_ok = false; di->chg_info.ac_chg_ok = false;
else else
di->chg_info.ac_chg_ok = true; di->chg_info.ac_chg_ok = true;
...@@ -707,10 +707,10 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di) ...@@ -707,10 +707,10 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di)
if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING && if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
di->charge_state == STATE_NORMAL && di->charge_state == STATE_NORMAL &&
!di->maintenance_chg && (di->batt_data.volt >= !di->maintenance_chg && (di->batt_data.volt >=
di->bat->bat_type[di->bat->batt_id].termination_vol || di->bm->bat_type[di->bm->batt_id].termination_vol ||
di->events.usb_cv_active || di->events.ac_cv_active) && di->events.usb_cv_active || di->events.ac_cv_active) &&
di->batt_data.avg_curr < di->batt_data.avg_curr <
di->bat->bat_type[di->bat->batt_id].termination_curr && di->bm->bat_type[di->bm->batt_id].termination_curr &&
di->batt_data.avg_curr > 0) { di->batt_data.avg_curr > 0) {
if (++di->eoc_cnt >= EOC_COND_CNT) { if (++di->eoc_cnt >= EOC_COND_CNT) {
di->eoc_cnt = 0; di->eoc_cnt = 0;
...@@ -733,12 +733,12 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di) ...@@ -733,12 +733,12 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di)
static void init_maxim_chg_curr(struct abx500_chargalg *di) static void init_maxim_chg_curr(struct abx500_chargalg *di)
{ {
di->ccm.original_iset = di->ccm.original_iset =
di->bat->bat_type[di->bat->batt_id].normal_cur_lvl; di->bm->bat_type[di->bm->batt_id].normal_cur_lvl;
di->ccm.current_iset = di->ccm.current_iset =
di->bat->bat_type[di->bat->batt_id].normal_cur_lvl; di->bm->bat_type[di->bm->batt_id].normal_cur_lvl;
di->ccm.test_delta_i = di->bat->maxi->charger_curr_step; di->ccm.test_delta_i = di->bm->maxi->charger_curr_step;
di->ccm.max_current = di->bat->maxi->chg_curr; di->ccm.max_current = di->bm->maxi->chg_curr;
di->ccm.condition_cnt = di->bat->maxi->wait_cycles; di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
di->ccm.level = 0; di->ccm.level = 0;
} }
...@@ -755,7 +755,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) ...@@ -755,7 +755,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
{ {
int delta_i; int delta_i;
if (!di->bat->maxi->ena_maxi) if (!di->bm->maxi->ena_maxi)
return MAXIM_RET_NOACTION; return MAXIM_RET_NOACTION;
delta_i = di->ccm.original_iset - di->batt_data.inst_curr; delta_i = di->ccm.original_iset - di->batt_data.inst_curr;
...@@ -766,7 +766,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) ...@@ -766,7 +766,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
if (di->ccm.wait_cnt == 0) { if (di->ccm.wait_cnt == 0) {
dev_dbg(di->dev, "lowering current\n"); dev_dbg(di->dev, "lowering current\n");
di->ccm.wait_cnt++; di->ccm.wait_cnt++;
di->ccm.condition_cnt = di->bat->maxi->wait_cycles; di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
di->ccm.max_current = di->ccm.max_current =
di->ccm.current_iset - di->ccm.test_delta_i; di->ccm.current_iset - di->ccm.test_delta_i;
di->ccm.current_iset = di->ccm.max_current; di->ccm.current_iset = di->ccm.max_current;
...@@ -791,7 +791,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) ...@@ -791,7 +791,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
if (di->ccm.current_iset == di->ccm.original_iset) if (di->ccm.current_iset == di->ccm.original_iset)
return MAXIM_RET_NOACTION; return MAXIM_RET_NOACTION;
di->ccm.condition_cnt = di->bat->maxi->wait_cycles; di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
di->ccm.current_iset = di->ccm.original_iset; di->ccm.current_iset = di->ccm.original_iset;
di->ccm.level = 0; di->ccm.level = 0;
...@@ -803,7 +803,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) ...@@ -803,7 +803,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
di->ccm.max_current) { di->ccm.max_current) {
if (di->ccm.condition_cnt-- == 0) { if (di->ccm.condition_cnt-- == 0) {
/* Increse the iset with cco.test_delta_i */ /* Increse the iset with cco.test_delta_i */
di->ccm.condition_cnt = di->bat->maxi->wait_cycles; di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
di->ccm.current_iset += di->ccm.test_delta_i; di->ccm.current_iset += di->ccm.test_delta_i;
di->ccm.level++; di->ccm.level++;
dev_dbg(di->dev, " Maximization needed, increase" dev_dbg(di->dev, " Maximization needed, increase"
...@@ -818,7 +818,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) ...@@ -818,7 +818,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
return MAXIM_RET_NOACTION; return MAXIM_RET_NOACTION;
} }
} else { } else {
di->ccm.condition_cnt = di->bat->maxi->wait_cycles; di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
return MAXIM_RET_NOACTION; return MAXIM_RET_NOACTION;
} }
} }
...@@ -838,7 +838,7 @@ static void handle_maxim_chg_curr(struct abx500_chargalg *di) ...@@ -838,7 +838,7 @@ static void handle_maxim_chg_curr(struct abx500_chargalg *di)
break; break;
case MAXIM_RET_IBAT_TOO_HIGH: case MAXIM_RET_IBAT_TOO_HIGH:
result = abx500_chargalg_update_chg_curr(di, result = abx500_chargalg_update_chg_curr(di,
di->bat->bat_type[di->bat->batt_id].normal_cur_lvl); di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
if (result) if (result)
dev_err(di->dev, "failed to set chg curr\n"); dev_err(di->dev, "failed to set chg curr\n");
break; break;
...@@ -1210,7 +1210,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) ...@@ -1210,7 +1210,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
* this way * this way
*/ */
if (!charger_status || if (!charger_status ||
(di->events.batt_unknown && !di->bat->chg_unknown_bat)) { (di->events.batt_unknown && !di->bm->chg_unknown_bat)) {
if (di->charge_state != STATE_HANDHELD) { if (di->charge_state != STATE_HANDHELD) {
di->events.safety_timer_expired = false; di->events.safety_timer_expired = false;
abx500_chargalg_state_to(di, STATE_HANDHELD_INIT); abx500_chargalg_state_to(di, STATE_HANDHELD_INIT);
...@@ -1394,8 +1394,8 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) ...@@ -1394,8 +1394,8 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
case STATE_NORMAL_INIT: case STATE_NORMAL_INIT:
abx500_chargalg_start_charging(di, abx500_chargalg_start_charging(di,
di->bat->bat_type[di->bat->batt_id].normal_vol_lvl, di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
di->bat->bat_type[di->bat->batt_id].normal_cur_lvl); di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
abx500_chargalg_state_to(di, STATE_NORMAL); abx500_chargalg_state_to(di, STATE_NORMAL);
abx500_chargalg_start_safety_timer(di); abx500_chargalg_start_safety_timer(di);
abx500_chargalg_stop_maintenance_timer(di); abx500_chargalg_stop_maintenance_timer(di);
...@@ -1411,7 +1411,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) ...@@ -1411,7 +1411,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
handle_maxim_chg_curr(di); handle_maxim_chg_curr(di);
if (di->charge_status == POWER_SUPPLY_STATUS_FULL && if (di->charge_status == POWER_SUPPLY_STATUS_FULL &&
di->maintenance_chg) { di->maintenance_chg) {
if (di->bat->no_maintenance) if (di->bm->no_maintenance)
abx500_chargalg_state_to(di, abx500_chargalg_state_to(di,
STATE_WAIT_FOR_RECHARGE_INIT); STATE_WAIT_FOR_RECHARGE_INIT);
else else
...@@ -1429,7 +1429,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) ...@@ -1429,7 +1429,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
case STATE_WAIT_FOR_RECHARGE: case STATE_WAIT_FOR_RECHARGE:
if (di->batt_data.volt <= if (di->batt_data.volt <=
di->bat->bat_type[di->bat->batt_id].recharge_vol) { di->bm->bat_type[di->bm->batt_id].recharge_vol) {
if (di->rch_cnt-- == 0) if (di->rch_cnt-- == 0)
abx500_chargalg_state_to(di, STATE_NORMAL_INIT); abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
} else } else
...@@ -1439,13 +1439,13 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) ...@@ -1439,13 +1439,13 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
case STATE_MAINTENANCE_A_INIT: case STATE_MAINTENANCE_A_INIT:
abx500_chargalg_stop_safety_timer(di); abx500_chargalg_stop_safety_timer(di);
abx500_chargalg_start_maintenance_timer(di, abx500_chargalg_start_maintenance_timer(di,
di->bat->bat_type[ di->bm->bat_type[
di->bat->batt_id].maint_a_chg_timer_h); di->bm->batt_id].maint_a_chg_timer_h);
abx500_chargalg_start_charging(di, abx500_chargalg_start_charging(di,
di->bat->bat_type[ di->bm->bat_type[
di->bat->batt_id].maint_a_vol_lvl, di->bm->batt_id].maint_a_vol_lvl,
di->bat->bat_type[ di->bm->bat_type[
di->bat->batt_id].maint_a_cur_lvl); di->bm->batt_id].maint_a_cur_lvl);
abx500_chargalg_state_to(di, STATE_MAINTENANCE_A); abx500_chargalg_state_to(di, STATE_MAINTENANCE_A);
power_supply_changed(&di->chargalg_psy); power_supply_changed(&di->chargalg_psy);
/* Intentional fallthrough*/ /* Intentional fallthrough*/
...@@ -1459,13 +1459,13 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) ...@@ -1459,13 +1459,13 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
case STATE_MAINTENANCE_B_INIT: case STATE_MAINTENANCE_B_INIT:
abx500_chargalg_start_maintenance_timer(di, abx500_chargalg_start_maintenance_timer(di,
di->bat->bat_type[ di->bm->bat_type[
di->bat->batt_id].maint_b_chg_timer_h); di->bm->batt_id].maint_b_chg_timer_h);
abx500_chargalg_start_charging(di, abx500_chargalg_start_charging(di,
di->bat->bat_type[ di->bm->bat_type[
di->bat->batt_id].maint_b_vol_lvl, di->bm->batt_id].maint_b_vol_lvl,
di->bat->bat_type[ di->bm->bat_type[
di->bat->batt_id].maint_b_cur_lvl); di->bm->batt_id].maint_b_cur_lvl);
abx500_chargalg_state_to(di, STATE_MAINTENANCE_B); abx500_chargalg_state_to(di, STATE_MAINTENANCE_B);
power_supply_changed(&di->chargalg_psy); power_supply_changed(&di->chargalg_psy);
/* Intentional fallthrough*/ /* Intentional fallthrough*/
...@@ -1479,10 +1479,10 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) ...@@ -1479,10 +1479,10 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
case STATE_TEMP_LOWHIGH_INIT: case STATE_TEMP_LOWHIGH_INIT:
abx500_chargalg_start_charging(di, abx500_chargalg_start_charging(di,
di->bat->bat_type[ di->bm->bat_type[
di->bat->batt_id].low_high_vol_lvl, di->bm->batt_id].low_high_vol_lvl,
di->bat->bat_type[ di->bm->bat_type[
di->bat->batt_id].low_high_cur_lvl); di->bm->batt_id].low_high_cur_lvl);
abx500_chargalg_stop_maintenance_timer(di); abx500_chargalg_stop_maintenance_timer(di);
di->charge_status = POWER_SUPPLY_STATUS_CHARGING; di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH); abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH);
...@@ -1543,11 +1543,11 @@ static void abx500_chargalg_periodic_work(struct work_struct *work) ...@@ -1543,11 +1543,11 @@ static void abx500_chargalg_periodic_work(struct work_struct *work)
if (di->chg_info.conn_chg) if (di->chg_info.conn_chg)
queue_delayed_work(di->chargalg_wq, queue_delayed_work(di->chargalg_wq,
&di->chargalg_periodic_work, &di->chargalg_periodic_work,
di->bat->interval_charging * HZ); di->bm->interval_charging * HZ);
else else
queue_delayed_work(di->chargalg_wq, queue_delayed_work(di->chargalg_wq,
&di->chargalg_periodic_work, &di->chargalg_periodic_work,
di->bat->interval_not_charging * HZ); di->bm->interval_not_charging * HZ);
} }
/** /**
...@@ -1614,7 +1614,7 @@ static int abx500_chargalg_get_property(struct power_supply *psy, ...@@ -1614,7 +1614,7 @@ static int abx500_chargalg_get_property(struct power_supply *psy,
if (di->events.batt_ovv) { if (di->events.batt_ovv) {
val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
} else if (di->events.btemp_underover) { } else if (di->events.btemp_underover) {
if (di->batt_data.temp <= di->bat->temp_under) if (di->batt_data.temp <= di->bm->temp_under)
val->intval = POWER_SUPPLY_HEALTH_COLD; val->intval = POWER_SUPPLY_HEALTH_COLD;
else else
val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
...@@ -1806,6 +1806,7 @@ static char *supply_interface[] = { ...@@ -1806,6 +1806,7 @@ static char *supply_interface[] = {
static int abx500_chargalg_probe(struct platform_device *pdev) static int abx500_chargalg_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct abx500_bm_data *plat = pdev->dev.platform_data;
struct abx500_chargalg *di; struct abx500_chargalg *di;
int ret = 0; int ret = 0;
...@@ -1814,21 +1815,19 @@ static int abx500_chargalg_probe(struct platform_device *pdev) ...@@ -1814,21 +1815,19 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__); dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__);
return -ENOMEM; return -ENOMEM;
} }
di->bat = pdev->mfd_cell->platform_data;
if (!di->bat) { if (!plat) {
dev_err(&pdev->dev, "no battery management data supplied\n");
return -EINVAL;
}
di->bm = plat;
if (np) { if (np) {
ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev, "failed to get battery information\n");
"failed to get battery information\n");
return ret; return ret;
} }
} else {
dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n");
return -EINVAL;
}
} else {
dev_info(&pdev->dev, "falling back to legacy platform data\n");
} }
/* get device struct */ /* get device struct */
......
...@@ -279,9 +279,9 @@ enum { ...@@ -279,9 +279,9 @@ enum {
NTC_INTERNAL, NTC_INTERNAL,
}; };
int bmdevs_of_probe(struct device *dev, int ab8500_bm_of_probe(struct device *dev,
struct device_node *np, struct device_node *np,
struct abx500_bm_data **battery); struct abx500_bm_data *bm);
int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg, int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
u8 value); u8 value);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment