summaryrefslogtreecommitdiff
path: root/drivers/power/supply/cpcap-battery.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-05-16 04:50:40 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-16 04:50:40 +0300
commit8649efb2f8750dcabff018a27784bab4ecb9f88f (patch)
tree4351aa7377c2042be5963d0f8b5600a1eb221a59 /drivers/power/supply/cpcap-battery.c
parent5fd09ba68297c967f5ba6bea9c3b444d34f80ee5 (diff)
parentbaf5964ecfe19a0109fe2e497e72840ce0f488e6 (diff)
downloadlinux-8649efb2f8750dcabff018a27784bab4ecb9f88f.tar.xz
Merge tag 'for-v5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply
Pull power supply and reset updates from Sebastian Reichel: "Core: - Add over-current health state - Add standard, adaptive and custom charge types - Add new properties for start/end charge threshold New Drivers / Hardware: - UCS1002 Programmable USB Port Power Controller - Ingenic JZ47xx Battery Fuel Gauge - AXP20x USB Power: Add AXP813 support - AT91 poweroff: Add SAM9X60 support - OLPC battery: Add XO-1.5 and XO-1.75 support Misc Changes: - syscon-reboot: support mask property - AXP288 fuel gauge: Blacklist ACEPC T8/T11. Looks like some vendor thought it's a good idea to build a desktop system with a fuel gauge, that slowly "discharges"... - cpcap-battery: Fix calculation errors - misc fixes" * tag 'for-v5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (54 commits) power: supply: olpc_battery: force the le/be casts power: supply: ucs1002: Fix build error without CONFIG_REGULATOR power: supply: ucs1002: Fix wrong return value checking power: supply: Add driver for Microchip UCS1002 dt-bindings: power: supply: Add bindings for Microchip UCS1002 power: supply: core: Add POWER_SUPPLY_HEALTH_OVERCURRENT constant power: supply: core: fix clang -Wunsequenced power: supply: core: Add missing documentation for CHARGE_CONTROL_* properties power: supply: core: Add CHARGE_CONTROL_{START_THRESHOLD,END_THRESHOLD} properties power: supply: core: Add Standard, Adaptive, and Custom charge types power: supply: axp288_fuel_gauge: Add ACEPC T8 and T11 mini PCs to the blacklist power: supply: bq27xxx_battery: Notify also about status changes power: supply: olpc_battery: Have the framework register sysfs files for us power: supply: olpc_battery: Add OLPC XO 1.75 support power: supply: olpc_battery: Avoid using platform_info power: supply: olpc_battery: Use devm_power_supply_register() power: supply: olpc_battery: Move priv data to a struct power: supply: olpc_battery: Use DT to get battery version x86/platform/olpc: Use a correct version when making up a battery node x86/platform/olpc: Trivial code move in DT fixup ...
Diffstat (limited to 'drivers/power/supply/cpcap-battery.c')
-rw-r--r--drivers/power/supply/cpcap-battery.c44
1 files changed, 22 insertions, 22 deletions
diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c
index 6887870ba32c..61d6447d1966 100644
--- a/drivers/power/supply/cpcap-battery.c
+++ b/drivers/power/supply/cpcap-battery.c
@@ -82,9 +82,9 @@ struct cpcap_battery_config {
};
struct cpcap_coulomb_counter_data {
- s32 sample; /* 24-bits */
+ s32 sample; /* 24 or 32 bits */
s32 accumulator;
- s16 offset; /* 10-bits */
+ s16 offset; /* 9 bits */
};
enum cpcap_battery_state {
@@ -213,7 +213,7 @@ static int cpcap_battery_get_current(struct cpcap_battery_ddata *ddata)
* TI or ST coulomb counter in the PMIC.
*/
static int cpcap_battery_cc_raw_div(struct cpcap_battery_ddata *ddata,
- u32 sample, s32 accumulator,
+ s32 sample, s32 accumulator,
s16 offset, u32 divider)
{
s64 acc;
@@ -224,9 +224,6 @@ static int cpcap_battery_cc_raw_div(struct cpcap_battery_ddata *ddata,
if (!divider)
return 0;
- sample &= 0xffffff; /* 24-bits, unsigned */
- offset &= 0x7ff; /* 10-bits, signed */
-
switch (ddata->vendor) {
case CPCAP_VENDOR_ST:
cc_lsb = 95374; /* μAms per LSB */
@@ -259,7 +256,7 @@ static int cpcap_battery_cc_raw_div(struct cpcap_battery_ddata *ddata,
/* 3600000μAms = 1μAh */
static int cpcap_battery_cc_to_uah(struct cpcap_battery_ddata *ddata,
- u32 sample, s32 accumulator,
+ s32 sample, s32 accumulator,
s16 offset)
{
return cpcap_battery_cc_raw_div(ddata, sample,
@@ -268,7 +265,7 @@ static int cpcap_battery_cc_to_uah(struct cpcap_battery_ddata *ddata,
}
static int cpcap_battery_cc_to_ua(struct cpcap_battery_ddata *ddata,
- u32 sample, s32 accumulator,
+ s32 sample, s32 accumulator,
s16 offset)
{
return cpcap_battery_cc_raw_div(ddata, sample,
@@ -312,17 +309,19 @@ cpcap_battery_read_accumulated(struct cpcap_battery_ddata *ddata,
/* Sample value CPCAP_REG_CCS1 & 2 */
ccd->sample = (buf[1] & 0x0fff) << 16;
ccd->sample |= buf[0];
+ if (ddata->vendor == CPCAP_VENDOR_TI)
+ ccd->sample = sign_extend32(24, ccd->sample);
/* Accumulator value CPCAP_REG_CCA1 & 2 */
ccd->accumulator = ((s16)buf[3]) << 16;
ccd->accumulator |= buf[2];
- /* Offset value CPCAP_REG_CCO */
- ccd->offset = buf[5];
-
- /* Adjust offset based on mode value CPCAP_REG_CCM? */
- if (buf[4] >= 0x200)
- ccd->offset |= 0xfc00;
+ /*
+ * Coulomb counter calibration offset is CPCAP_REG_CCM,
+ * REG_CCO seems unused
+ */
+ ccd->offset = buf[4];
+ ccd->offset = sign_extend32(ccd->offset, 9);
return cpcap_battery_cc_to_uah(ddata,
ccd->sample,
@@ -477,11 +476,11 @@ static int cpcap_battery_get_property(struct power_supply *psy,
val->intval = ddata->config.info.voltage_min_design;
break;
case POWER_SUPPLY_PROP_CURRENT_AVG:
- if (cached) {
+ sample = latest->cc.sample - previous->cc.sample;
+ if (!sample) {
val->intval = cpcap_battery_cc_get_avg_current(ddata);
break;
}
- sample = latest->cc.sample - previous->cc.sample;
accumulator = latest->cc.accumulator - previous->cc.accumulator;
val->intval = cpcap_battery_cc_to_ua(ddata, sample,
accumulator,
@@ -498,13 +497,13 @@ static int cpcap_battery_get_property(struct power_supply *psy,
val->intval = div64_s64(tmp, 100);
break;
case POWER_SUPPLY_PROP_POWER_AVG:
- if (cached) {
+ sample = latest->cc.sample - previous->cc.sample;
+ if (!sample) {
tmp = cpcap_battery_cc_get_avg_current(ddata);
tmp *= (latest->voltage / 10000);
val->intval = div64_s64(tmp, 100);
break;
}
- sample = latest->cc.sample - previous->cc.sample;
accumulator = latest->cc.accumulator - previous->cc.accumulator;
tmp = cpcap_battery_cc_to_ua(ddata, sample, accumulator,
latest->cc.offset);
@@ -562,11 +561,11 @@ static irqreturn_t cpcap_battery_irq_thread(int irq, void *data)
switch (d->action) {
case CPCAP_BATTERY_IRQ_ACTION_BATTERY_LOW:
- if (latest->counter_uah >= 0)
+ if (latest->current_ua >= 0)
dev_warn(ddata->dev, "Battery low at 3.3V!\n");
break;
case CPCAP_BATTERY_IRQ_ACTION_POWEROFF:
- if (latest->counter_uah >= 0) {
+ if (latest->current_ua >= 0) {
dev_emerg(ddata->dev,
"Battery empty at 3.1V, powering off\n");
orderly_poweroff(true);
@@ -670,8 +669,9 @@ static int cpcap_battery_init_iio(struct cpcap_battery_ddata *ddata)
return 0;
out_err:
- dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
- error);
+ if (error != -EPROBE_DEFER)
+ dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
+ error);
return error;
}