summaryrefslogtreecommitdiff
path: root/drivers/power/ab8500_btemp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 22:15:24 (GMT)
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 22:15:24 (GMT)
commit151173e8ce9b95bbbbd7eedb9035cfaffbdb7cb2 (patch)
treebca02f40bdd054fa2e30f4923e1513d40873c4d9 /drivers/power/ab8500_btemp.c
parent30945669593df14692e933c557d00c4bb2727857 (diff)
parent6b170807cd5cac8dc6353f47a88ccb14bbf76c4f (diff)
downloadlinux-151173e8ce9b95bbbbd7eedb9035cfaffbdb7cb2.tar.xz
Merge tag 'for-v3.10' of git://git.infradead.org/battery-2.6
Pull battery updates from Anton Vorontsov: "Highlights: - OpenFirmware/DeviceTree support for the Power Supply core: the core now automatically populates supplied_from hierarchy from the device tree. With these patches chargers and batteries can now lookup each other without the board files support shim. Rhyland Klein at NVIDIA did the work - New ST-Ericsson ABX500 hwmon driver. The driver is heavily using the AB85xx core and depends on some recent changes to it, so that is why the driver comes through the battery tree. It has an appropriate ack from the hwmon maintainer (i.e. Guenter Roeck). Martin Persson at ST-Ericsson and Hongbo Zhang at Linaro authored the driver - Final bits to sync AB85xx ST-Ericsson changes into mainline. The changes touch mfd parts, but these were acked by the appropriate MFD maintainer (ie Samuel Ortiz). Lee Jones at Linaro did most of the work and lead the submission process. Minor changes, but still worth mentioning: - Battery temperature reporting fix for Nokia N900 phones - Versatile Express poweroff driver moved into drivers/power/reset/ - Tree-wide: use devm_kzalloc() where appropriate - Tree-wide: dev_pm_ops cleanups/fixes" * tag 'for-v3.10' of git://git.infradead.org/battery-2.6: (112 commits) pm2301-charger: Fix suspend/resume charger-manager: Use kmemdup instead of kzalloc + memcpy power_supply: Populate supplied_from hierarchy from the device tree power_supply: Add core support for supplied_from power_supply: Define Binding for power-supplies rx51_battery: Fix reporting temperature hwmon: Add ST-Ericsson ABX500 hwmon driver ab8500_bmdata: Export abx500_res_to_temp tables for hwmon ab8500_{bmdata,fg}: Add const attributes to some data arrays ab8500_bmdata: Eliminate CamelCase warning of some variables ab8500_btemp: Make ab8500_btemp_get* interfaces public goldfish_battery: Use resource_size() lp8788-charger: Use PAGE_SIZE for the sysfs read operation max8925_power: Use devm_kzalloc() da9030_battery: Use devm_kzalloc() da9052-battery: Use devm_kzalloc() ds2760_battery: Use devm_kzalloc() ds2780_battery: Use devm_kzalloc() gpio-charger: Use devm_kzalloc() isp1704_charger: Use devm_kzalloc() ...
Diffstat (limited to 'drivers/power/ab8500_btemp.c')
-rw-r--r--drivers/power/ab8500_btemp.c80
1 files changed, 63 insertions, 17 deletions
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 0768906..d412d34 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -42,6 +42,9 @@
#define BTEMP_BATCTRL_CURR_SRC_16UA 16
#define BTEMP_BATCTRL_CURR_SRC_18UA 18
+#define BTEMP_BATCTRL_CURR_SRC_60UA 60
+#define BTEMP_BATCTRL_CURR_SRC_120UA 120
+
#define to_ab8500_btemp_device_info(x) container_of((x), \
struct ab8500_btemp, btemp_psy);
@@ -76,8 +79,8 @@ struct ab8500_btemp_ranges {
* @dev: Pointer to the structure device
* @node: List of AB8500 BTEMPs, hence prepared for reentrance
* @curr_source: What current source we use, in uA
- * @bat_temp: Battery temperature in degree Celcius
- * @prev_bat_temp Last dispatched battery temperature
+ * @bat_temp: Dispatched battery temperature in degree Celcius
+ * @prev_bat_temp Last measured battery temperature in degree Celcius
* @parent: Pointer to the struct ab8500
* @gpadc: Pointer to the struct gpadc
* @fg: Pointer to the struct fg
@@ -128,6 +131,7 @@ struct ab8500_btemp *ab8500_btemp_get(void)
return btemp;
}
+EXPORT_SYMBOL(ab8500_btemp_get);
/**
* ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance
@@ -155,7 +159,7 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
/*
* If the battery has internal NTC, we use the current
- * source to calculate the resistance, 7uA or 20uA
+ * source to calculate the resistance.
*/
rbs = (v_batctrl * 1000
- di->bm->gnd_lift_resistance * inst_curr)
@@ -216,7 +220,12 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
/* Only do this for batteries with internal NTC */
if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
- if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
+ if (is_ab8540(di->parent)) {
+ if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_60UA)
+ curr = BAT_CTRL_60U_ENA;
+ else
+ curr = BAT_CTRL_120U_ENA;
+ } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA)
curr = BAT_CTRL_16U_ENA;
else
@@ -257,7 +266,14 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
} else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
dev_dbg(di->dev, "Disable BATCTRL curr source\n");
- if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
+ if (is_ab8540(di->parent)) {
+ /* Write 0 to the curr bits */
+ ret = abx500_mask_and_set_register_interruptible(
+ di->dev,
+ AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
+ BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
+ ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
+ } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
/* Write 0 to the curr bits */
ret = abx500_mask_and_set_register_interruptible(
di->dev,
@@ -314,7 +330,13 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
* if we got an error above
*/
disable_curr_source:
- if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
+ if (is_ab8540(di->parent)) {
+ /* Write 0 to the curr bits */
+ ret = abx500_mask_and_set_register_interruptible(di->dev,
+ AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
+ BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
+ ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
+ } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
/* Write 0 to the curr bits */
ret = abx500_mask_and_set_register_interruptible(di->dev,
AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
@@ -541,7 +563,9 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
{
int res;
u8 i;
- if (is_ab9540(di->parent) || is_ab8505(di->parent))
+ if (is_ab8540(di->parent))
+ di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
+ else if (is_ab9540(di->parent) || is_ab8505(di->parent))
di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
else
di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
@@ -579,12 +603,17 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
/*
* 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.
*/
if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
- di->bm->batt_id == 1) {
- if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
- dev_dbg(di->dev, "Set BATCTRL current source to 16uA\n");
+ di->bm->batt_id == 1) {
+ if (is_ab8540(di->parent)) {
+ dev_dbg(di->dev,
+ "Set BATCTRL current source to 60uA\n");
+ di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
+ } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
+ dev_dbg(di->dev,
+ "Set BATCTRL current source to 16uA\n");
di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
} else {
dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
@@ -604,22 +633,37 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
static void ab8500_btemp_periodic_work(struct work_struct *work)
{
int interval;
+ int bat_temp;
struct ab8500_btemp *di = container_of(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);
-
- if (di->bat_temp != di->prev_bat_temp) {
- di->prev_bat_temp = di->bat_temp;
+ bat_temp = ab8500_btemp_measure_temp(di);
+ /*
+ * Filter battery temperature.
+ * Allow direct updates on temperature only if two samples result in
+ * same temperature. Else only allow 1 degree change from previous
+ * reported value in the direction of the new measurement.
+ */
+ if ((bat_temp == di->prev_bat_temp) || !di->initialized) {
+ if ((di->bat_temp != di->prev_bat_temp) || !di->initialized) {
+ di->initialized = true;
+ di->bat_temp = bat_temp;
+ power_supply_changed(&di->btemp_psy);
+ }
+ } else if (bat_temp < di->prev_bat_temp) {
+ di->bat_temp--;
+ power_supply_changed(&di->btemp_psy);
+ } else if (bat_temp > di->prev_bat_temp) {
+ di->bat_temp++;
power_supply_changed(&di->btemp_psy);
}
+ di->prev_bat_temp = bat_temp;
if (di->events.ac_conn || di->events.usb_conn)
interval = di->bm->temp_interval_chg;
@@ -772,7 +816,7 @@ static void ab8500_btemp_periodic(struct ab8500_btemp *di,
*
* Returns battery temperature
*/
-static int ab8500_btemp_get_temp(struct ab8500_btemp *di)
+int ab8500_btemp_get_temp(struct ab8500_btemp *di)
{
int temp = 0;
@@ -808,6 +852,7 @@ static int ab8500_btemp_get_temp(struct ab8500_btemp *di)
}
return temp;
}
+EXPORT_SYMBOL(ab8500_btemp_get_temp);
/**
* ab8500_btemp_get_batctrl_temp() - get the temperature
@@ -819,6 +864,7 @@ int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp)
{
return btemp->bat_temp * 1000;
}
+EXPORT_SYMBOL(ab8500_btemp_get_batctrl_temp);
/**
* ab8500_btemp_get_property() - get the btemp properties