power_supply: add CHARGE_COUNTER property and olpc_battery support for it
This adds PROP_CHARGE_COUNTER to the power supply class (documenting it
as well). The OLPC battery driver uses this for spitting out its ACR
values (in uAh). We have some rounding errors (the data sheet claims
416.7, the math actually works out to 416.666667, so we're forced to
choose between overflows or precision loss. I chose precision loss,
and stuck w/ data sheet values), but I don't think anyone will care
that much.
Signed-off-by: Andres Salomon <dilinger@debian.org>
Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
diff --git a/Documentation/power/power_supply_class.txt b/Documentation/power/power_supply_class.txt
index a8686e5..c6cd495 100644
--- a/Documentation/power/power_supply_class.txt
+++ b/Documentation/power/power_supply_class.txt
@@ -101,6 +101,10 @@
charge when battery considered full/empty at given conditions (temperature,
age)". I.e. these attributes represents real thresholds, not design values.
+CHARGE_COUNTER - the current charge counter (in µAh). This could easily
+be negative; there is no empty or full value. It is only useful for
+relative, time-based measurements.
+
ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
CAPACITY - capacity in percents.
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index c8b596a..9dd1589 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -19,7 +19,7 @@
#define EC_BAT_VOLTAGE 0x10 /* uint16_t, *9.76/32, mV */
#define EC_BAT_CURRENT 0x11 /* int16_t, *15.625/120, mA */
-#define EC_BAT_ACR 0x12
+#define EC_BAT_ACR 0x12 /* int16_t, *416.7, µAh */
#define EC_BAT_TEMP 0x13 /* uint16_t, *100/256, °C */
#define EC_AMB_TEMP 0x14 /* uint16_t, *100/256, °C */
#define EC_BAT_STATUS 0x15 /* uint8_t, bitmask */
@@ -289,6 +289,14 @@
ec_word = be16_to_cpu(ec_word);
val->intval = ec_word * 100 / 256;
break;
+ case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+ ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 4167 / 10;
+ break;
case POWER_SUPPLY_PROP_SERIAL_NUMBER:
ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8);
if (ret)
@@ -317,6 +325,7 @@
POWER_SUPPLY_PROP_TEMP_AMBIENT,
POWER_SUPPLY_PROP_MANUFACTURER,
POWER_SUPPLY_PROP_SERIAL_NUMBER,
+ POWER_SUPPLY_PROP_CHARGE_COUNTER,
};
/* EEPROM reading goes completely around the power_supply API, sadly */
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index c444d6b..82e1246 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -99,6 +99,7 @@
POWER_SUPPLY_ATTR(charge_empty),
POWER_SUPPLY_ATTR(charge_now),
POWER_SUPPLY_ATTR(charge_avg),
+ POWER_SUPPLY_ATTR(charge_counter),
POWER_SUPPLY_ATTR(energy_full_design),
POWER_SUPPLY_ATTR(energy_empty_design),
POWER_SUPPLY_ATTR(energy_full),
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 68ed19c..ea96ead 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -78,6 +78,7 @@
POWER_SUPPLY_PROP_CHARGE_EMPTY,
POWER_SUPPLY_PROP_CHARGE_NOW,
POWER_SUPPLY_PROP_CHARGE_AVG,
+ POWER_SUPPLY_PROP_CHARGE_COUNTER,
POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
POWER_SUPPLY_PROP_ENERGY_FULL,