* [PATCH v10 0/8] devicetree battery support and client bq27xxx_battery
@ 2017-03-15 19:26 Liam Breck
2017-03-15 19:26 ` [PATCH v10 2/8] devicetree: property-units: Add uWh and uAh units Liam Breck
` (6 more replies)
0 siblings, 7 replies; 35+ messages in thread
From: Liam Breck @ 2017-03-15 19:26 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: Andrew F. Davis, linux-pm, Matt Ranostay
Overview:
* new devicetree battery node specifies static battery data
* fuel gauge and charger nodes shall use monitored-battery=<&battery_node>
* new power_supply_get_battery_info() reads battery data from devicetree
* new struct power_supply_battery_info provides battery data to drivers
* drivers surface battery data in sysfs via related power_supply_prop_* fields
* bq27xxx driver calls the above and writes battery data to RAM/NVM for params
essential to correct operation: energy-full-design-microwatt-hours,
charge-full-design-microamp-hours, voltage-min-design-microvolt
Changes in v10:
bq27xxx_battery:
* pass actual chip ID into _setup()
* add di->unseal_key & di->dm_regs; drop static arrays
* support bq27425, 441, 621
Changes in v9:
bq27xxx_battery:
* fix set_cfgupdate()
* support bq27500, 545, 421; defer others
* drop print_dm_blocks() patch
* minor polishing
Documentation/devicetree/.../battery.txt:
* describe rationale for enum power_supply_property names
Changes in v8:
bq27xxx_battery:
* wait on flag after set_cfgupdate & soft_reset
* drop print_config(), report status in update_dm_block()
* clarify error messages
* cleanup from Andrew's feedback; minor polishing
Changes in v7:
bq27xxx_battery:
* support chips where terminate_voltage & design_* live in separate blocks
* draft support for 421, 441, 621 chips
* new patch to log chip memory fields
* report bus I/O errors; return error code in bq27xxx_battery_i2c
* verify checksum in read_dm_block()
* use set_cfgupdate only if chip provides it, soft_reset on I/O error
* block_data_control=0 only in write_dm_block()
* note toxic code from TI bqtool in write_dm_block()
* lots of functionally neutral polishing
Documentation/devicetree/.../battery.txt:
* mention power_supply_get_battery_info()
Changes in v6:
* Documentation/devictree/... fixes
* bq27xxx_battery: clarify names
* bq27xxx_battery: verify that selected registers are supported
* bq27xxx_battery: allocate NVM buffer on stack
* bq27xxx_battery_i2c: fix return code of bulk_read
Changes in v5:
* incorporate feedback into Documentation/devicetree/.../battery.txt
* use power_supply_prop_* names in devicetree and power_supply_battery_info
* default fields to -EINVAL in power_supply_battery_info
* power_supply_get_battery_info() always looks for "monitored-battery"
* power_supply_get_battery_info() emits a warning if !psy->of_node
* squash patches for power_supply_battery_info
* bq27xxx_battery: check power_supply_battery_info values
* bq27xxx_battery: note missing power_supply_prop_* features
* bq27xxx_battery: new patch for access methods
Changes in v4:
* add "fixed-battery" compatible field to be be more consistant with devicetree
Changes in v3:
* split i2c changes into respective patches
* add documentation for battery information for fuel gauge
* rebased documentation patches on change on the list
* abstracted the battery configuration for the state machine
to an generic struct and platform data access function
Changes in v2:
* add documentation for uWh and uAh property units
* change devicetree entries to match new property units
Liam (5):
devicetree: power: Add battery.txt
devicetree: power: bq27xxx: Add monitored-battery documentation
power: power_supply: Add power_supply_battery_info and API
power: bq27xxx_battery: Keep track of specific chip id
power: bq27xxx_battery: Add power_supply_battery_info support
Matt Ranostay (3):
devicetree: property-units: Add uWh and uAh units
power: bq27xxx_battery: Define access methods to write chip registers
power: bq27xxx_battery_i2c: Add I2C bulk read/write functions
.../devicetree/bindings/power/supply/battery.txt | 45 ++
.../devicetree/bindings/power/supply/bq27xxx.txt | 11 +-
.../devicetree/bindings/property-units.txt | 2 +
drivers/power/supply/bq27xxx_battery.c | 477 ++++++++++++++++++++-
drivers/power/supply/bq27xxx_battery_i2c.c | 98 ++++-
drivers/power/supply/power_supply_core.c | 40 ++
include/linux/power/bq27xxx_battery.h | 30 +-
include/linux/power_supply.h | 18 +
8 files changed, 702 insertions(+), 19 deletions(-)
create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
--
2.9.3
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH v10 1/8] devicetree: power: Add battery.txt
[not found] ` <20170315192653.26799-1-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
@ 2017-03-15 19:26 ` Liam Breck
2017-03-15 22:04 ` Sebastian Reichel
2017-03-15 19:26 ` [PATCH v10 3/8] devicetree: power: bq27xxx: Add monitored-battery documentation Liam Breck
1 sibling, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-15 19:26 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Andrew F. Davis, linux-pm-u79uwXL29TY76Z2rM5mHXA, Matt Ranostay,
Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA, Liam Breck
From: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
Documentation of static battery characteristics that can be defined
for batteries which cannot self-identify. This information is required
by fuel-gauge and charger chips for proper handling of the battery.
Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
Signed-off-by: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
---
.../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
new file mode 100644
index 0000000..0278617
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/battery.txt
@@ -0,0 +1,45 @@
+Battery Characteristics
+
+Required Properties:
+ - compatible: Must be "fixed-battery"
+
+Optional Properties:
+ - voltage-min-design-microvolt: drained battery voltage
+ - energy-full-design-microwatt-hours: battery design energy
+ - charge-full-design-microamp-hours: battery design capacity
+
+Because drivers surface properties in sysfs using names derived
+from enum power_supply_property, e.g.
+/sys/class/power_supply/<device>/charge_full_design, our
+battery properties must be named for the corresponding elements in
+enum power_supply_property, defined in include/linux/power_supply.h.
+
+Batteries must be referenced by chargers and/or fuel-gauges
+using a phandle. The phandle's property should be named
+"monitored-battery".
+
+Driver code should call power_supply_get_battery_info() to obtain
+battery properties via monitored-battery. For details see:
+ drivers/power/supply/power_supply_core.c
+ drivers/power/supply/bq27xxx_battery.c
+
+Example:
+
+ bat: battery {
+ compatible = "fixed-battery";
+ voltage-min-design-microvolt = <3200000>;
+ energy-full-design-microwatt-hours = <5290000>;
+ charge-full-design-microamp-hours = <1430000>;
+ };
+
+ charger: charger@11 {
+ ....
+ monitored-battery = <&bat>;
+ ...
+ };
+
+ fuel_gauge: fuel-gauge@22 {
+ ....
+ monitored-battery = <&bat>;
+ ...
+ };
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v10 2/8] devicetree: property-units: Add uWh and uAh units
2017-03-15 19:26 [PATCH v10 0/8] devicetree battery support and client bq27xxx_battery Liam Breck
@ 2017-03-15 19:26 ` Liam Breck
[not found] ` <20170315192653.26799-1-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
` (5 subsequent siblings)
6 siblings, 0 replies; 35+ messages in thread
From: Liam Breck @ 2017-03-15 19:26 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Rob Herring,
Mark Rutland, devicetree, linux-kernel, Liam Breck
From: Matt Ranostay <matt@ranostay.consulting>
Add entries for microwatt-hours and microamp-hours.
Cc: Rob Herring <robh@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
Signed-off-by: Liam Breck <kernel@networkimprov.net>
Acked-by: Sebastian Reichel <sre@kernel.org>
Acked-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/property-units.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/property-units.txt b/Documentation/devicetree/bindings/property-units.txt
index 12278d7..0849618 100644
--- a/Documentation/devicetree/bindings/property-units.txt
+++ b/Documentation/devicetree/bindings/property-units.txt
@@ -25,8 +25,10 @@ Distance
Electricity
----------------------------------------
-microamp : micro amps
+-microamp-hours : micro amp-hours
-ohms : Ohms
-micro-ohms : micro Ohms
+-microwatt-hours: micro Watt-hours
-microvolt : micro volts
Temperature
--
2.9.3
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v10 3/8] devicetree: power: bq27xxx: Add monitored-battery documentation
[not found] ` <20170315192653.26799-1-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
2017-03-15 19:26 ` [PATCH v10 1/8] devicetree: power: Add battery.txt Liam Breck
@ 2017-03-15 19:26 ` Liam Breck
[not found] ` <20170315192653.26799-4-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
1 sibling, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-15 19:26 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Andrew F. Davis, linux-pm-u79uwXL29TY76Z2rM5mHXA, Matt Ranostay,
Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA, Liam Breck
From: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
Document monitored-battery = <&battery_node>
Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
Signed-off-by: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Documentation/devicetree/bindings/power/supply/bq27xxx.txt | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/power/supply/bq27xxx.txt b/Documentation/devicetree/bindings/power/supply/bq27xxx.txt
index b0c95ef..cf83371 100644
--- a/Documentation/devicetree/bindings/power/supply/bq27xxx.txt
+++ b/Documentation/devicetree/bindings/power/supply/bq27xxx.txt
@@ -28,9 +28,18 @@ Required properties:
* "ti,bq27621" - BQ27621
- reg: integer, i2c address of the device.
+Optional properties:
+- monitored-battery: phandle of battery information devicetree node
+
+ See Documentation/devicetree/bindings/power/supply/battery.txt
+ If either of the referenced battery's *-full-design-*-hours properties are set,
+ then both must be.
+
Example:
-bq27510g3 {
+bq27510g3 : fuel-gauge@55 {
compatible = "ti,bq27510g3";
reg = <0x55>;
+
+ monitored-battery = <&bat>;
};
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v10 4/8] power: power_supply: Add power_supply_battery_info and API
2017-03-15 19:26 [PATCH v10 0/8] devicetree battery support and client bq27xxx_battery Liam Breck
2017-03-15 19:26 ` [PATCH v10 2/8] devicetree: property-units: Add uWh and uAh units Liam Breck
[not found] ` <20170315192653.26799-1-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
@ 2017-03-15 19:26 ` Liam Breck
2017-03-15 22:07 ` Sebastian Reichel
2017-03-15 19:26 ` [PATCH v10 5/8] power: bq27xxx_battery: Define access methods to write chip registers Liam Breck
` (3 subsequent siblings)
6 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-15 19:26 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Liam Breck
From: Liam Breck <kernel@networkimprov.net>
power_supply_get_battery_info() reads battery data from devicetree.
struct power_supply_battery_info provides battery data to drivers.
Drivers may surface battery data in sysfs via corresponding
POWER_SUPPLY_PROP_* fields.
Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
Signed-off-by: Liam Breck <kernel@networkimprov.net>
---
drivers/power/supply/power_supply_core.c | 40 ++++++++++++++++++++++++++++++++
include/linux/power_supply.h | 18 ++++++++++++++
2 files changed, 58 insertions(+)
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index a74d8ca..c121931 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -17,6 +17,7 @@
#include <linux/device.h>
#include <linux/notifier.h>
#include <linux/err.h>
+#include <linux/of.h>
#include <linux/power_supply.h>
#include <linux/thermal.h>
#include "power_supply.h"
@@ -487,6 +488,45 @@ struct power_supply *devm_power_supply_get_by_phandle(struct device *dev,
EXPORT_SYMBOL_GPL(devm_power_supply_get_by_phandle);
#endif /* CONFIG_OF */
+int power_supply_get_battery_info(struct power_supply *psy,
+ struct power_supply_battery_info *info)
+{
+ struct device_node *battery_np;
+ const char *value;
+ int err;
+
+ info->energy_full_design_uwh = -EINVAL;
+ info->charge_full_design_uah = -EINVAL;
+ info->voltage_min_design_uv = -EINVAL;
+
+ if (!psy->of_node) {
+ dev_warn(&psy->dev, "%s currently only supports devicetree\n",
+ __func__);
+ return -ENXIO;
+ }
+
+ battery_np = of_parse_phandle(psy->of_node, "monitored-battery", 0);
+ if (!battery_np)
+ return -ENODEV;
+
+ err = of_property_read_string(battery_np, "compatible", &value);
+ if (err)
+ return err;
+
+ if (strcmp("fixed-battery", value))
+ return -ENODEV;
+
+ of_property_read_u32(battery_np, "energy-full-design-microwatt-hours",
+ &info->energy_full_design_uwh);
+ of_property_read_u32(battery_np, "charge-full-design-microamp-hours",
+ &info->charge_full_design_uah);
+ of_property_read_u32(battery_np, "voltage-min-design-microvolt",
+ &info->voltage_min_design_uv);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(power_supply_get_battery_info);
+
int power_supply_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 3965503..e84f1d3 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -288,6 +288,21 @@ struct power_supply_info {
int use_for_apm;
};
+/*
+ * This is the recommended struct to manage static battery parameters,
+ * populated by power_supply_get_battery_info(). Most platform drivers should
+ * use these for consistency.
+ * Its field names must correspond to elements in enum power_supply_property.
+ * The default field value is -EINVAL.
+ * Power supply class itself doesn't use this.
+ */
+
+struct power_supply_battery_info {
+ int energy_full_design_uwh; /* microWatt-hours */
+ int charge_full_design_uah; /* microAmp-hours */
+ int voltage_min_design_uv; /* microVolts */
+};
+
extern struct atomic_notifier_head power_supply_notifier;
extern int power_supply_reg_notifier(struct notifier_block *nb);
extern void power_supply_unreg_notifier(struct notifier_block *nb);
@@ -306,6 +321,9 @@ static inline struct power_supply *
devm_power_supply_get_by_phandle(struct device *dev, const char *property)
{ return NULL; }
#endif /* CONFIG_OF */
+
+extern int power_supply_get_battery_info(struct power_supply *psy,
+ struct power_supply_battery_info *info);
extern void power_supply_changed(struct power_supply *psy);
extern int power_supply_am_i_supplied(struct power_supply *psy);
extern int power_supply_set_battery_charged(struct power_supply *psy);
--
2.9.3
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v10 5/8] power: bq27xxx_battery: Define access methods to write chip registers
2017-03-15 19:26 [PATCH v10 0/8] devicetree battery support and client bq27xxx_battery Liam Breck
` (2 preceding siblings ...)
2017-03-15 19:26 ` [PATCH v10 4/8] power: power_supply: Add power_supply_battery_info and API Liam Breck
@ 2017-03-15 19:26 ` Liam Breck
2017-03-15 19:26 ` [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id Liam Breck
` (2 subsequent siblings)
6 siblings, 0 replies; 35+ messages in thread
From: Liam Breck @ 2017-03-15 19:26 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Liam Breck
From: Matt Ranostay <matt@ranostay.consulting>
write(), read_bulk(), write_bulk() support setting chip registers,
e.g. with data obtained from power_supply_battery_info.
Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
Signed-off-by: Liam Breck <kernel@networkimprov.net>
---
include/linux/power/bq27xxx_battery.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
index bed9557..92df553 100644
--- a/include/linux/power/bq27xxx_battery.h
+++ b/include/linux/power/bq27xxx_battery.h
@@ -32,6 +32,9 @@ struct bq27xxx_platform_data {
struct bq27xxx_device_info;
struct bq27xxx_access_methods {
int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single);
+ int (*write)(struct bq27xxx_device_info *di, u8 reg, int value, bool single);
+ int (*read_bulk)(struct bq27xxx_device_info *di, u8 reg, u8 *data, int len);
+ int (*write_bulk)(struct bq27xxx_device_info *di, u8 reg, u8 *data, int len);
};
struct bq27xxx_reg_cache {
--
2.9.3
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
2017-03-15 19:26 [PATCH v10 0/8] devicetree battery support and client bq27xxx_battery Liam Breck
` (3 preceding siblings ...)
2017-03-15 19:26 ` [PATCH v10 5/8] power: bq27xxx_battery: Define access methods to write chip registers Liam Breck
@ 2017-03-15 19:26 ` Liam Breck
2017-03-16 14:44 ` Andrew F. Davis
2017-03-15 19:26 ` [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support Liam Breck
2017-03-15 19:26 ` [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions Liam Breck
6 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-15 19:26 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Liam Breck
From: Liam Breck <kernel@networkimprov.net>
Pass actual chip ID into _setup(), which translates it to a group ID,
to allow support for all chips by the power_supply_battery_info code.
There are no functional changes to the driver.
Signed-off-by: Liam Breck <kernel@networkimprov.net>
---
drivers/power/supply/bq27xxx_battery.c | 19 +++++++++++++++++++
drivers/power/supply/bq27xxx_battery_i2c.c | 16 ++++++++--------
include/linux/power/bq27xxx_battery.h | 25 ++++++++++++++++++-------
3 files changed, 45 insertions(+), 15 deletions(-)
diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
index 7272d1e..d613d3d 100644
--- a/drivers/power/supply/bq27xxx_battery.c
+++ b/drivers/power/supply/bq27xxx_battery.c
@@ -1020,6 +1020,25 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
struct power_supply_desc *psy_desc;
struct power_supply_config psy_cfg = { .drv_data = di, };
+ switch(di->chip) {
+ case BQ27000:
+ case BQ27010:
+ case BQ27500:
+ case BQ27510:
+ case BQ27530:
+ case BQ27541:
+ case BQ27545:
+ case BQ27421: break;
+ case BQ27520: di->chip = BQ27510; break;
+ case BQ27531: di->chip = BQ27530; break;
+ case BQ27542: di->chip = BQ27541; break;
+ case BQ27546: di->chip = BQ27541; break;
+ case BQ27742: di->chip = BQ27541; break;
+ case BQ27425: di->chip = BQ27421; break;
+ case BQ27441: di->chip = BQ27421; break;
+ case BQ27621: di->chip = BQ27421; break;
+ }
+
INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
mutex_init(&di->lock);
di->regs = bq27xxx_regs[di->chip];
diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
index 5c5c3a6..13def59 100644
--- a/drivers/power/supply/bq27xxx_battery_i2c.c
+++ b/drivers/power/supply/bq27xxx_battery_i2c.c
@@ -150,18 +150,18 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
{ "bq27210", BQ27010 },
{ "bq27500", BQ27500 },
{ "bq27510", BQ27510 },
- { "bq27520", BQ27510 },
+ { "bq27520", BQ27520 },
{ "bq27530", BQ27530 },
- { "bq27531", BQ27530 },
+ { "bq27531", BQ27531 },
{ "bq27541", BQ27541 },
- { "bq27542", BQ27541 },
- { "bq27546", BQ27541 },
- { "bq27742", BQ27541 },
+ { "bq27542", BQ27542 },
+ { "bq27546", BQ27546 },
+ { "bq27742", BQ27742 },
{ "bq27545", BQ27545 },
{ "bq27421", BQ27421 },
- { "bq27425", BQ27421 },
- { "bq27441", BQ27421 },
- { "bq27621", BQ27421 },
+ { "bq27425", BQ27425 },
+ { "bq27441", BQ27441 },
+ { "bq27621", BQ27621 },
{},
};
MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
index 92df553..90db1cf 100644
--- a/include/linux/power/bq27xxx_battery.h
+++ b/include/linux/power/bq27xxx_battery.h
@@ -2,14 +2,25 @@
#define __LINUX_BQ27X00_BATTERY_H__
enum bq27xxx_chip {
+ /* categories; index for bq27xxx_regs[] */
BQ27000 = 1, /* bq27000, bq27200 */
- BQ27010, /* bq27010, bq27210 */
- BQ27500, /* bq27500 */
- BQ27510, /* bq27510, bq27520 */
- BQ27530, /* bq27530, bq27531 */
- BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
- BQ27545, /* bq27545 */
- BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
+ BQ27010 = 2, /* bq27010, bq27210 */
+ BQ27500 = 3, /* bq27500 */
+ BQ27510 = 4, /* bq27510, bq27520 */
+ BQ27530 = 5, /* bq27530, bq27531 */
+ BQ27541 = 6, /* bq27541, bq27542, bq27546, bq27742 */
+ BQ27545 = 7, /* bq27545 */
+ BQ27421 = 8, /* bq27421, bq27425, bq27441, bq27621 */
+
+ /* members of categories; translate these to category in _setup() */
+ BQ27520 = 101,
+ BQ27531 = 102,
+ BQ27542 = 103,
+ BQ27546 = 104,
+ BQ27742 = 105,
+ BQ27425 = 106,
+ BQ27441 = 107,
+ BQ27621 = 108,
};
/**
--
2.9.3
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support
2017-03-15 19:26 [PATCH v10 0/8] devicetree battery support and client bq27xxx_battery Liam Breck
` (4 preceding siblings ...)
2017-03-15 19:26 ` [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id Liam Breck
@ 2017-03-15 19:26 ` Liam Breck
2017-03-16 15:00 ` Andrew F. Davis
2017-03-15 19:26 ` [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions Liam Breck
6 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-15 19:26 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Liam Breck
From: Liam Breck <kernel@networkimprov.net>
Previously there was no way to configure chip registers in the event that the
defaults didn't match the battery in question.
BQ27xxx driver now calls power_supply_get_battery_info, checks the inputs,
and writes battery data to chip RAM or non-volatile memory.
Supports chips BQ27500, 545, 421, 425, 441, 621. Others may be added.
Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
Signed-off-by: Liam Breck <kernel@networkimprov.net>
---
drivers/power/supply/bq27xxx_battery.c | 478 ++++++++++++++++++++++++++++++++-
include/linux/power/bq27xxx_battery.h | 2 +
2 files changed, 468 insertions(+), 12 deletions(-)
diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
index d613d3d..fb062db 100644
--- a/drivers/power/supply/bq27xxx_battery.c
+++ b/drivers/power/supply/bq27xxx_battery.c
@@ -51,7 +51,7 @@
#include <linux/power/bq27xxx_battery.h>
-#define DRIVER_VERSION "1.2.0"
+#define DRIVER_VERSION "1.3.0"
#define BQ27XXX_MANUFACTURER "Texas Instruments"
@@ -59,6 +59,7 @@
#define BQ27XXX_FLAG_DSC BIT(0)
#define BQ27XXX_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
#define BQ27XXX_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
+#define BQ27XXX_FLAG_CFGUP BIT(4)
#define BQ27XXX_FLAG_FC BIT(9)
#define BQ27XXX_FLAG_OTD BIT(14)
#define BQ27XXX_FLAG_OTC BIT(15)
@@ -72,6 +73,11 @@
#define BQ27000_FLAG_FC BIT(5)
#define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
+/* control register params */
+#define BQ27XXX_SEALED 0x20
+#define BQ27XXX_SET_CFGUPDATE 0x13
+#define BQ27XXX_SOFT_RESET 0x42
+
#define BQ27XXX_RS (20) /* Resistor sense mOhm */
#define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */
#define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */
@@ -102,6 +108,11 @@ enum bq27xxx_reg_index {
BQ27XXX_REG_SOC, /* State-of-Charge */
BQ27XXX_REG_DCAP, /* Design Capacity */
BQ27XXX_REG_AP, /* Average Power */
+ BQ27XXX_DM_CTRL, /* BlockDataControl() */
+ BQ27XXX_DM_CLASS, /* DataClass() */
+ BQ27XXX_DM_BLOCK, /* DataBlock() */
+ BQ27XXX_DM_DATA, /* BlockData() */
+ BQ27XXX_DM_CKSUM, /* BlockDataChecksum() */
BQ27XXX_REG_MAX, /* sentinel */
};
@@ -125,6 +136,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_SOC] = 0x0b,
[BQ27XXX_REG_DCAP] = 0x76,
[BQ27XXX_REG_AP] = 0x24,
+ [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_DATA] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR,
},
[BQ27010] = {
[BQ27XXX_REG_CTRL] = 0x00,
@@ -144,6 +160,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_SOC] = 0x0b,
[BQ27XXX_REG_DCAP] = 0x76,
[BQ27XXX_REG_AP] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_DATA] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR,
},
[BQ27500] = {
[BQ27XXX_REG_CTRL] = 0x00,
@@ -163,6 +184,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_SOC] = 0x2c,
[BQ27XXX_REG_DCAP] = 0x3c,
[BQ27XXX_REG_AP] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_CTRL] = 0x61,
+ [BQ27XXX_DM_CLASS] = 0x3e,
+ [BQ27XXX_DM_BLOCK] = 0x3f,
+ [BQ27XXX_DM_DATA] = 0x40,
+ [BQ27XXX_DM_CKSUM] = 0x60,
},
[BQ27510] = {
[BQ27XXX_REG_CTRL] = 0x00,
@@ -182,6 +208,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_SOC] = 0x20,
[BQ27XXX_REG_DCAP] = 0x2e,
[BQ27XXX_REG_AP] = INVALID_REG_ADDR,
+ [BQ27XXX_DM_CTRL] = 0x61,
+ [BQ27XXX_DM_CLASS] = 0x3e,
+ [BQ27XXX_DM_BLOCK] = 0x3f,
+ [BQ27XXX_DM_DATA] = 0x40,
+ [BQ27XXX_DM_CKSUM] = 0x60,
},
[BQ27530] = {
[BQ27XXX_REG_CTRL] = 0x00,
@@ -201,6 +232,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_SOC] = 0x2c,
[BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
[BQ27XXX_REG_AP] = 0x24,
+ [BQ27XXX_DM_CTRL] = 0x61,
+ [BQ27XXX_DM_CLASS] = 0x3e,
+ [BQ27XXX_DM_BLOCK] = 0x3f,
+ [BQ27XXX_DM_DATA] = 0x40,
+ [BQ27XXX_DM_CKSUM] = 0x60,
},
[BQ27541] = {
[BQ27XXX_REG_CTRL] = 0x00,
@@ -220,6 +256,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_SOC] = 0x2c,
[BQ27XXX_REG_DCAP] = 0x3c,
[BQ27XXX_REG_AP] = 0x24,
+ [BQ27XXX_DM_CTRL] = 0x61,
+ [BQ27XXX_DM_CLASS] = 0x3e,
+ [BQ27XXX_DM_BLOCK] = 0x3f,
+ [BQ27XXX_DM_DATA] = 0x40,
+ [BQ27XXX_DM_CKSUM] = 0x60,
},
[BQ27545] = {
[BQ27XXX_REG_CTRL] = 0x00,
@@ -239,6 +280,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_SOC] = 0x2c,
[BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
[BQ27XXX_REG_AP] = 0x24,
+ [BQ27XXX_DM_CTRL] = 0x61,
+ [BQ27XXX_DM_CLASS] = 0x3e,
+ [BQ27XXX_DM_BLOCK] = 0x3f,
+ [BQ27XXX_DM_DATA] = 0x40,
+ [BQ27XXX_DM_CKSUM] = 0x60,
},
[BQ27421] = {
[BQ27XXX_REG_CTRL] = 0x00,
@@ -258,6 +304,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_SOC] = 0x1c,
[BQ27XXX_REG_DCAP] = 0x3c,
[BQ27XXX_REG_AP] = 0x18,
+ [BQ27XXX_DM_CTRL] = 0x61,
+ [BQ27XXX_DM_CLASS] = 0x3e,
+ [BQ27XXX_DM_BLOCK] = 0x3f,
+ [BQ27XXX_DM_DATA] = 0x40,
+ [BQ27XXX_DM_CKSUM] = 0x60,
},
};
@@ -432,6 +483,82 @@ static struct {
static DEFINE_MUTEX(bq27xxx_list_lock);
static LIST_HEAD(bq27xxx_battery_devices);
+#define BQ27XXX_DM_SZ 32
+
+#define BQ27XXX_MSLEEP(i) usleep_range((i)*1000, (i)*1000+500)
+
+struct bq27xxx_dm_reg {
+ u8 subclass_id;
+ u8 offset;
+ u8 bytes;
+ u16 min, max;
+};
+
+struct bq27xxx_dm_buf {
+ u8 class;
+ u8 block;
+ u8 a[BQ27XXX_DM_SZ];
+ bool full, updt;
+};
+
+#define BQ27XXX_DM_BUF(di, i) { \
+ .class = (di)->dm_regs[i].subclass_id, \
+ .block = (di)->dm_regs[i].offset / BQ27XXX_DM_SZ, \
+}
+
+static inline u16* bq27xxx_dm_reg_ptr(struct bq27xxx_dm_buf *buf,
+ struct bq27xxx_dm_reg *reg)
+{
+ if (buf->class == reg->subclass_id
+ && buf->block == reg->offset / BQ27XXX_DM_SZ)
+ return (u16*) (buf->a + reg->offset % BQ27XXX_DM_SZ);
+
+ return NULL;
+}
+
+enum bq27xxx_dm_reg_id {
+ BQ27XXX_DM_DESIGN_CAPACITY = 0,
+ BQ27XXX_DM_DESIGN_ENERGY,
+ BQ27XXX_DM_TERMINATE_VOLTAGE,
+};
+
+static const char* bq27xxx_dm_reg_name[] = {
+ [BQ27XXX_DM_DESIGN_CAPACITY] = "design-capacity",
+ [BQ27XXX_DM_DESIGN_ENERGY] = "design-energy",
+ [BQ27XXX_DM_TERMINATE_VOLTAGE] = "terminate-voltage",
+};
+
+static struct bq27xxx_dm_reg bq27500_dm_regs[] = {
+ [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 10, 2, 0, 65535 },
+ [BQ27XXX_DM_DESIGN_ENERGY] = { }, /* missing on chip */
+ [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 48, 2, 1000, 32767 },
+};
+
+static struct bq27xxx_dm_reg bq27545_dm_regs[] = {
+ [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 23, 2, 0, 32767 },
+ [BQ27XXX_DM_DESIGN_ENERGY] = { 48, 25, 2, 0, 32767 },
+ [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 67, 2, 2800, 3700 },
+};
+
+static struct bq27xxx_dm_reg bq27421_dm_regs[] = {
+ [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 8000 },
+ [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 },
+ [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 16, 2, 2500, 3700 },
+};
+
+static struct bq27xxx_dm_reg bq27425_dm_regs[] = {
+ [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 12, 2, 0, 32767 },
+ [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 14, 2, 0, 32767 },
+ [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 18, 2, 2800, 3700 },
+};
+
+static struct bq27xxx_dm_reg bq27621_dm_regs[] = {
+ [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 3, 2, 0, 8000 },
+ [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 5, 2, 0, 32767 },
+ [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 9, 2, 2500, 3700 },
+};
+
+
static int poll_interval_param_set(const char *val, const struct kernel_param *kp)
{
struct bq27xxx_device_info *di;
@@ -476,6 +603,317 @@ static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index,
return di->bus.read(di, di->regs[reg_index], single);
}
+static int bq27xxx_battery_set_seal_state(struct bq27xxx_device_info *di,
+ bool state)
+{
+ int ret;
+
+ if (state) {
+ ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], BQ27XXX_SEALED, false);
+ if (ret < 0)
+ goto out;
+ } else {
+ ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], (u16)(di->unseal_key >> 16), false);
+ if (ret < 0)
+ goto out;
+
+ ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], (u16)di->unseal_key, false);
+ if (ret < 0)
+ goto out;
+ }
+ return 0;
+
+out:
+ dev_err(di->dev, "bus error on %s: %d\n", state ? "seal" : "unseal", ret);
+ return ret;
+}
+
+static u8 bq27xxx_battery_checksum_dm_block(struct bq27xxx_dm_buf *buf)
+{
+ u16 sum = 0;
+ int i;
+
+ for (i = 0; i < BQ27XXX_DM_SZ; i++)
+ sum += buf->a[i];
+ sum &= 0xff;
+
+ return 0xff - sum;
+}
+
+static int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di,
+ struct bq27xxx_dm_buf *buf)
+{
+ int ret;
+
+ ret = di->bus.write(di, di->regs[BQ27XXX_DM_CLASS], buf->class, true);
+ if (ret < 0)
+ goto out;
+
+ ret = di->bus.write(di, di->regs[BQ27XXX_DM_BLOCK], buf->block, true);
+ if (ret < 0)
+ goto out;
+
+ BQ27XXX_MSLEEP(1);
+
+ ret = di->bus.read_bulk(di, di->regs[BQ27XXX_DM_DATA], buf->a, BQ27XXX_DM_SZ);
+ if (ret < 0)
+ goto out;
+
+ ret = di->bus.read(di, di->regs[BQ27XXX_DM_CKSUM], true);
+ if (ret < 0)
+ goto out;
+
+ if ((u8)ret != bq27xxx_battery_checksum_dm_block(buf)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ buf->full = true;
+ buf->updt = false;
+ return 0;
+
+out:
+ dev_err(di->dev, "bus error reading chip memory: %d\n", ret);
+ return ret;
+}
+
+static void bq27xxx_battery_update_dm_block(struct bq27xxx_device_info *di,
+ struct bq27xxx_dm_buf *buf,
+ enum bq27xxx_dm_reg_id reg_id,
+ unsigned int val)
+{
+ struct bq27xxx_dm_reg *reg = &di->dm_regs[reg_id];
+ const char* str = bq27xxx_dm_reg_name[reg_id];
+ u16 *prev = bq27xxx_dm_reg_ptr(buf, reg);
+
+ if (prev == NULL) {
+ dev_warn(di->dev, "buffer does not match %s dm spec\n", str);
+ return;
+ }
+
+ if (reg->bytes != 2) {
+ dev_warn(di->dev, "%s dm spec has unsupported byte size\n", str);
+ return;
+ }
+
+ if (!buf->full)
+ return;
+
+ if (be16_to_cpup(prev) == val) {
+ dev_info(di->dev, "%s has %u\n", str, val);
+ return;
+ }
+
+ dev_info(di->dev, "update %s to %u\n", str, val);
+
+ *prev = cpu_to_be16(val);
+ buf->updt = true;
+}
+
+static int bq27xxx_battery_set_cfgupdate(struct bq27xxx_device_info *di,
+ bool state)
+{
+ int ret, try=100;
+
+ ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL],
+ state ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET,
+ false);
+ if (ret < 0)
+ goto out;
+
+ do {
+ BQ27XXX_MSLEEP(25);
+ ret = di->bus.read(di, di->regs[BQ27XXX_REG_FLAGS], false);
+ if (ret < 0)
+ goto out;
+ } while (!(ret & BQ27XXX_FLAG_CFGUP) == state && --try);
+
+ if (!try) {
+ dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", state);
+ return -EINVAL;
+ }
+
+ if (100-try > 3)
+ dev_warn(di->dev, "cfgupdate %d, retries %d\n", state, 100-try);
+
+ return 0;
+
+out:
+ dev_err(di->dev, "bus error on %s: %d\n", state ? "set_cfgupdate" : "soft_reset", ret);
+ return ret;
+}
+
+static int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di,
+ struct bq27xxx_dm_buf *buf)
+{
+ bool cfgup = di->chip == BQ27421; /* assume group supports cfgupdate */
+ int ret;
+
+ if (!buf->updt)
+ return 0;
+
+ if (cfgup) {
+ ret = bq27xxx_battery_set_cfgupdate(di, true);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = di->bus.write(di, di->regs[BQ27XXX_DM_CTRL], 0, true);
+ if (ret < 0)
+ goto out;
+
+ ret = di->bus.write(di, di->regs[BQ27XXX_DM_CLASS], buf->class, true);
+ if (ret < 0)
+ goto out;
+
+ ret = di->bus.write(di, di->regs[BQ27XXX_DM_BLOCK], buf->block, true);
+ if (ret < 0)
+ goto out;
+
+ BQ27XXX_MSLEEP(1);
+
+ ret = di->bus.write_bulk(di, di->regs[BQ27XXX_DM_DATA], buf->a, BQ27XXX_DM_SZ);
+ if (ret < 0)
+ goto out;
+
+ ret = di->bus.write(di, di->regs[BQ27XXX_DM_CKSUM],
+ bq27xxx_battery_checksum_dm_block(buf), true);
+ if (ret < 0)
+ goto out;
+
+ /* THE FOLLOWING SEQUENCE IS TOXIC. DO NOT USE!
+ * If the 'time' delay is insufficient, NVM corruption results on
+ * the '425 chip (and perhaps others), which could damage the chip.
+ * It was suggested in this TI tool:
+ * http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328
+ *
+ * 1. MSLEEP(time) after above write(BQ27XXX_DM_CKSUM, ...)
+ * 2. write(BQ27XXX_DM_BLOCK, buf->block)
+ * 3. sum = read(BQ27XXX_DM_CKSUM)
+ * 4. if (sum != bq27xxx_battery_checksum_dm_block(buf))
+ * report error
+ */
+
+ if (cfgup) {
+ BQ27XXX_MSLEEP(1);
+ ret = bq27xxx_battery_set_cfgupdate(di, false);
+ if (ret < 0)
+ return ret;
+ } else {
+ /* flash DM updates in <100ms, but reset time isn't documented */
+ BQ27XXX_MSLEEP(400);
+ }
+
+ buf->updt = false;
+ return 0;
+
+out:
+ if (cfgup)
+ bq27xxx_battery_set_cfgupdate(di, false);
+
+ dev_err(di->dev, "bus error writing chip memory: %d\n", ret);
+ return ret;
+}
+
+static void bq27xxx_battery_set_config(struct bq27xxx_device_info *di,
+ struct power_supply_battery_info *info)
+{
+ struct bq27xxx_dm_buf bd = BQ27XXX_DM_BUF(di, BQ27XXX_DM_DESIGN_CAPACITY);
+ struct bq27xxx_dm_buf bt = BQ27XXX_DM_BUF(di, BQ27XXX_DM_TERMINATE_VOLTAGE);
+
+ if (info->charge_full_design_uah != -EINVAL
+ && info->energy_full_design_uwh != -EINVAL) {
+ bq27xxx_battery_read_dm_block(di, &bd);
+ /* assume design energy & capacity are in same block */
+ bq27xxx_battery_update_dm_block(di, &bd,
+ BQ27XXX_DM_DESIGN_CAPACITY,
+ info->charge_full_design_uah / 1000);
+ bq27xxx_battery_update_dm_block(di, &bd,
+ BQ27XXX_DM_DESIGN_ENERGY,
+ info->energy_full_design_uwh / 1000);
+ }
+
+ if (info->voltage_min_design_uv != -EINVAL) {
+ bool same = bd.class == bt.class && bd.block == bt.block;
+ if (!same)
+ bq27xxx_battery_read_dm_block(di, &bt);
+ bq27xxx_battery_update_dm_block(di, same ? &bd : &bt,
+ BQ27XXX_DM_TERMINATE_VOLTAGE,
+ info->voltage_min_design_uv / 1000);
+ }
+
+ bq27xxx_battery_write_dm_block(di, &bd);
+ bq27xxx_battery_write_dm_block(di, &bt);
+}
+
+void bq27xxx_battery_settings(struct bq27xxx_device_info *di)
+{
+ struct power_supply_battery_info info = {};
+ unsigned int min, max;
+
+ /* functions don't exist for writing data so abort */
+ if (!di->bus.write || !di->bus.write_bulk)
+ return;
+
+ /* no settings to be set for this chipset so abort */
+ if (!di->dm_regs)
+ return;
+
+ if (bq27xxx_battery_set_seal_state(di, false) < 0)
+ return;
+
+ if (power_supply_get_battery_info(di->bat, &info) < 0)
+ goto out;
+
+ if (info.energy_full_design_uwh != info.charge_full_design_uah) {
+ if (info.energy_full_design_uwh == -EINVAL)
+ dev_warn(di->dev,
+ "missing battery:energy-full-design-microwatt-hours\n");
+ else if (info.charge_full_design_uah == -EINVAL)
+ dev_warn(di->dev,
+ "missing battery:charge-full-design-microamp-hours\n");
+ }
+
+ /* assume min == 0 */
+ max = di->dm_regs[BQ27XXX_DM_DESIGN_ENERGY].max;
+ if (info.energy_full_design_uwh > max * 1000) {
+ dev_err(di->dev,
+ "invalid battery:energy-full-design-microwatt-hours %d\n",
+ info.energy_full_design_uwh);
+ info.energy_full_design_uwh = -EINVAL;
+ }
+
+ /* assume min == 0 */
+ max = di->dm_regs[BQ27XXX_DM_DESIGN_CAPACITY].max;
+ if (info.charge_full_design_uah > max * 1000) {
+ dev_err(di->dev,
+ "invalid battery:charge-full-design-microamp-hours %d\n",
+ info.charge_full_design_uah);
+ info.charge_full_design_uah = -EINVAL;
+ }
+
+ min = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].min;
+ max = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].max;
+ if ((info.voltage_min_design_uv < min * 1000
+ || info.voltage_min_design_uv > max * 1000)
+ && info.voltage_min_design_uv != -EINVAL) {
+ dev_err(di->dev,
+ "invalid battery:voltage-min-design-microvolt %d\n",
+ info.voltage_min_design_uv);
+ info.voltage_min_design_uv = -EINVAL;
+ }
+
+ if ((info.energy_full_design_uwh == -EINVAL
+ || info.charge_full_design_uah == -EINVAL)
+ && info.voltage_min_design_uv == -EINVAL)
+ goto out;
+
+ bq27xxx_battery_set_config(di, &info);
+
+out:
+ bq27xxx_battery_set_seal_state(di, true);
+}
+
/*
* Return the battery State-of-Charge
* Or < 0 if something fails.
@@ -985,6 +1423,13 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
ret = bq27xxx_simple_value(di->charge_design_full, val);
break;
+ /*
+ * TODO: Implement these to make registers set from
+ * power_supply_battery_info visible in sysfs.
+ */
+ case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ return -EINVAL;
case POWER_SUPPLY_PROP_CYCLE_COUNT:
ret = bq27xxx_simple_value(di->cache.cycle_count, val);
break;
@@ -1015,28 +1460,36 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
schedule_delayed_work(&di->work, 0);
}
+#define BQ27XXX_INIT(c,d,k) \
+ di->chip = (c); \
+ di->dm_regs = (d); \
+ di->unseal_key = (k)
+
int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
{
struct power_supply_desc *psy_desc;
- struct power_supply_config psy_cfg = { .drv_data = di, };
+ struct power_supply_config psy_cfg = {
+ .of_node = di->dev->of_node,
+ .drv_data = di,
+ };
switch(di->chip) {
case BQ27000:
- case BQ27010:
- case BQ27500:
- case BQ27510:
- case BQ27530:
- case BQ27541:
- case BQ27545:
- case BQ27421: break;
+ case BQ27010: break;
+ case BQ27500: BQ27XXX_INIT(BQ27500, bq27500_dm_regs, 0x04143672); break;
+ case BQ27510: break;
+ case BQ27530: break;
+ case BQ27541: break;
+ case BQ27545: BQ27XXX_INIT(BQ27545, bq27545_dm_regs, 0x04143672); break;
+ case BQ27421: BQ27XXX_INIT(BQ27421, bq27421_dm_regs, 0x80008000); break;
case BQ27520: di->chip = BQ27510; break;
case BQ27531: di->chip = BQ27530; break;
case BQ27542: di->chip = BQ27541; break;
case BQ27546: di->chip = BQ27541; break;
case BQ27742: di->chip = BQ27541; break;
- case BQ27425: di->chip = BQ27421; break;
- case BQ27441: di->chip = BQ27421; break;
- case BQ27621: di->chip = BQ27421; break;
+ case BQ27425: BQ27XXX_INIT(BQ27421, bq27425_dm_regs, 0x04143672); break;
+ case BQ27441: BQ27XXX_INIT(BQ27421, bq27421_dm_regs, 0x80008000); break;
+ case BQ27621: BQ27XXX_INIT(BQ27421, bq27621_dm_regs, 0x80008000); break;
}
INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
@@ -1062,6 +1515,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
+ bq27xxx_battery_settings(di);
bq27xxx_battery_update(di);
mutex_lock(&bq27xxx_list_lock);
diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
index 90db1cf..dbf1ab9 100644
--- a/include/linux/power/bq27xxx_battery.h
+++ b/include/linux/power/bq27xxx_battery.h
@@ -67,6 +67,8 @@ struct bq27xxx_device_info {
int id;
enum bq27xxx_chip chip;
const char *name;
+ struct bq27xxx_dm_reg *dm_regs;
+ u32 unseal_key;
struct bq27xxx_access_methods bus;
struct bq27xxx_reg_cache cache;
int charge_design_full;
--
2.9.3
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions
2017-03-15 19:26 [PATCH v10 0/8] devicetree battery support and client bq27xxx_battery Liam Breck
` (5 preceding siblings ...)
2017-03-15 19:26 ` [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support Liam Breck
@ 2017-03-15 19:26 ` Liam Breck
2017-03-15 22:14 ` Sebastian Reichel
6 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-15 19:26 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Liam Breck
From: Matt Ranostay <matt@ranostay.consulting>
write(), read_bulk(), write_bulk() are required by bq27xxx_battery
power_supply_battery_info code.
Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
Signed-off-by: Liam Breck <kernel@networkimprov.net>
---
drivers/power/supply/bq27xxx_battery_i2c.c | 82 +++++++++++++++++++++++++++++-
1 file changed, 81 insertions(+), 1 deletion(-)
diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
index 13def59..abdc266 100644
--- a/drivers/power/supply/bq27xxx_battery_i2c.c
+++ b/drivers/power/supply/bq27xxx_battery_i2c.c
@@ -38,7 +38,7 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
{
struct i2c_client *client = to_i2c_client(di->dev);
struct i2c_msg msg[2];
- unsigned char data[2];
+ u8 data[2];
int ret;
if (!client->adapter)
@@ -68,6 +68,82 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
return ret;
}
+static int bq27xxx_battery_i2c_write(struct bq27xxx_device_info *di, u8 reg,
+ int value, bool single)
+{
+ struct i2c_client *client = to_i2c_client(di->dev);
+ struct i2c_msg msg;
+ u8 data[4];
+ int ret;
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ data[0] = reg;
+ if (single) {
+ data[1] = (u8) value;
+ msg.len = 2;
+ } else {
+ put_unaligned_le16(value, &data[1]);
+ msg.len = 3;
+ }
+
+ msg.buf = data;
+ msg.addr = client->addr;
+ msg.flags = 0;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret < 0)
+ return ret;
+ if (ret != 1)
+ return -EINVAL;
+ return 0;
+}
+
+static int bq27xxx_battery_i2c_bulk_read(struct bq27xxx_device_info *di, u8 reg,
+ u8 *data, int len)
+{
+ struct i2c_client *client = to_i2c_client(di->dev);
+ int ret;
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ ret = i2c_smbus_read_i2c_block_data(client, reg, len, data);
+ if (ret < 0)
+ return ret;
+ if (ret != len)
+ return -EINVAL;
+ return 0;
+}
+
+static int bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info *di,
+ u8 reg, u8 *data, int len)
+{
+ struct i2c_client *client = to_i2c_client(di->dev);
+ struct i2c_msg msg;
+ u8 buf[33];
+ int ret;
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ buf[0] = reg;
+ memcpy(&buf[1], data, len);
+
+ msg.buf = buf;
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = len + 1;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret < 0)
+ return ret;
+ if (ret != 1)
+ return -EINVAL;
+ return 0;
+}
+
static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -95,7 +171,11 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
di->dev = &client->dev;
di->chip = id->driver_data;
di->name = name;
+
di->bus.read = bq27xxx_battery_i2c_read;
+ di->bus.write = bq27xxx_battery_i2c_write;
+ di->bus.read_bulk = bq27xxx_battery_i2c_bulk_read;
+ di->bus.write_bulk = bq27xxx_battery_i2c_bulk_write;
ret = bq27xxx_battery_setup(di);
if (ret)
--
2.9.3
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
2017-03-15 19:26 ` [PATCH v10 1/8] devicetree: power: Add battery.txt Liam Breck
@ 2017-03-15 22:04 ` Sebastian Reichel
2017-03-15 22:18 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Sebastian Reichel @ 2017-03-15 22:04 UTC (permalink / raw)
To: Liam Breck
Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Rob Herring,
devicetree, Liam Breck
[-- Attachment #1: Type: text/plain, Size: 3066 bytes --]
Hi Liam & Matt,
Sorry for my absence in the discussion. I skipped the previous
iterations for now and start with this version.
On Wed, Mar 15, 2017 at 12:26:46PM -0700, Liam Breck wrote:
> From: Liam Breck <kernel@networkimprov.net>
>
> Documentation of static battery characteristics that can be defined
> for batteries which cannot self-identify. This information is required
> by fuel-gauge and charger chips for proper handling of the battery.
>
> Cc: Rob Herring <robh@kernel.org>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
> Signed-off-by: Liam Breck <kernel@networkimprov.net>
> ---
> .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++
> 1 file changed, 45 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
>
> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
> new file mode 100644
> index 0000000..0278617
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
> @@ -0,0 +1,45 @@
> +Battery Characteristics
Maybe add something like
This device provides static battery information, that is usually
available in the EEPROM of a smart battery. It's supposed to be
used for batteries, which do not have their own EEPROM (or if its
unusable).
> +Required Properties:
> + - compatible: Must be "fixed-battery"
> +
> +Optional Properties:
> + - voltage-min-design-microvolt: drained battery voltage
> + - energy-full-design-microwatt-hours: battery design energy
> + - charge-full-design-microamp-hours: battery design capacity
Looks fine to me.
> +Because drivers surface properties in sysfs using names derived
> +from enum power_supply_property, e.g.
> +/sys/class/power_supply/<device>/charge_full_design, our
> +battery properties must be named for the corresponding elements in
> +enum power_supply_property, defined in include/linux/power_supply.h.
This is Linux/implementation specific and does not belong
into a DT binding document.
> +Batteries must be referenced by chargers and/or fuel-gauges
> +using a phandle. The phandle's property should be named
> +"monitored-battery".
This looks fine.
> +Driver code should call power_supply_get_battery_info() to obtain
> +battery properties via monitored-battery. For details see:
> + drivers/power/supply/power_supply_core.c
> + drivers/power/supply/bq27xxx_battery.c
This is also Linux/implementation specific and should be dropped.
> +Example:
> +
> + bat: battery {
> + compatible = "fixed-battery";
> + voltage-min-design-microvolt = <3200000>;
> + energy-full-design-microwatt-hours = <5290000>;
> + charge-full-design-microamp-hours = <1430000>;
> + };
> +
> + charger: charger@11 {
> + ....
> + monitored-battery = <&bat>;
> + ...
> + };
> +
> + fuel_gauge: fuel-gauge@22 {
> + ....
> + monitored-battery = <&bat>;
> + ...
> + };
> --
> 2.9.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 3/8] devicetree: power: bq27xxx: Add monitored-battery documentation
[not found] ` <20170315192653.26799-4-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
@ 2017-03-15 22:06 ` Sebastian Reichel
0 siblings, 0 replies; 35+ messages in thread
From: Sebastian Reichel @ 2017-03-15 22:06 UTC (permalink / raw)
To: Liam Breck
Cc: Andrew F. Davis, linux-pm-u79uwXL29TY76Z2rM5mHXA, Matt Ranostay,
Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA, Liam Breck
[-- Attachment #1: Type: text/plain, Size: 1717 bytes --]
On Wed, Mar 15, 2017 at 12:26:48PM -0700, Liam Breck wrote:
> From: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
>
> Document monitored-battery = <&battery_node>
>
> Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
> Signed-off-by: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: Sebastian Reichel <sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
-- Sebastian
> ---
> Documentation/devicetree/bindings/power/supply/bq27xxx.txt | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/power/supply/bq27xxx.txt b/Documentation/devicetree/bindings/power/supply/bq27xxx.txt
> index b0c95ef..cf83371 100644
> --- a/Documentation/devicetree/bindings/power/supply/bq27xxx.txt
> +++ b/Documentation/devicetree/bindings/power/supply/bq27xxx.txt
> @@ -28,9 +28,18 @@ Required properties:
> * "ti,bq27621" - BQ27621
> - reg: integer, i2c address of the device.
>
> +Optional properties:
> +- monitored-battery: phandle of battery information devicetree node
> +
> + See Documentation/devicetree/bindings/power/supply/battery.txt
> + If either of the referenced battery's *-full-design-*-hours properties are set,
> + then both must be.
> +
> Example:
>
> -bq27510g3 {
> +bq27510g3 : fuel-gauge@55 {
> compatible = "ti,bq27510g3";
> reg = <0x55>;
> +
> + monitored-battery = <&bat>;
> };
> --
> 2.9.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 4/8] power: power_supply: Add power_supply_battery_info and API
2017-03-15 19:26 ` [PATCH v10 4/8] power: power_supply: Add power_supply_battery_info and API Liam Breck
@ 2017-03-15 22:07 ` Sebastian Reichel
0 siblings, 0 replies; 35+ messages in thread
From: Sebastian Reichel @ 2017-03-15 22:07 UTC (permalink / raw)
To: Liam Breck; +Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Liam Breck
[-- Attachment #1: Type: text/plain, Size: 4368 bytes --]
Hi,
On Wed, Mar 15, 2017 at 12:26:49PM -0700, Liam Breck wrote:
> From: Liam Breck <kernel@networkimprov.net>
>
> power_supply_get_battery_info() reads battery data from devicetree.
> struct power_supply_battery_info provides battery data to drivers.
> Drivers may surface battery data in sysfs via corresponding
> POWER_SUPPLY_PROP_* fields.
>
> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
> Signed-off-by: Liam Breck <kernel@networkimprov.net>
Acked-By: Sebastian Reichel <sre@kernel.org>
-- Sebastian
> ---
> drivers/power/supply/power_supply_core.c | 40 ++++++++++++++++++++++++++++++++
> include/linux/power_supply.h | 18 ++++++++++++++
> 2 files changed, 58 insertions(+)
>
> diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
> index a74d8ca..c121931 100644
> --- a/drivers/power/supply/power_supply_core.c
> +++ b/drivers/power/supply/power_supply_core.c
> @@ -17,6 +17,7 @@
> #include <linux/device.h>
> #include <linux/notifier.h>
> #include <linux/err.h>
> +#include <linux/of.h>
> #include <linux/power_supply.h>
> #include <linux/thermal.h>
> #include "power_supply.h"
> @@ -487,6 +488,45 @@ struct power_supply *devm_power_supply_get_by_phandle(struct device *dev,
> EXPORT_SYMBOL_GPL(devm_power_supply_get_by_phandle);
> #endif /* CONFIG_OF */
>
> +int power_supply_get_battery_info(struct power_supply *psy,
> + struct power_supply_battery_info *info)
> +{
> + struct device_node *battery_np;
> + const char *value;
> + int err;
> +
> + info->energy_full_design_uwh = -EINVAL;
> + info->charge_full_design_uah = -EINVAL;
> + info->voltage_min_design_uv = -EINVAL;
> +
> + if (!psy->of_node) {
> + dev_warn(&psy->dev, "%s currently only supports devicetree\n",
> + __func__);
> + return -ENXIO;
> + }
> +
> + battery_np = of_parse_phandle(psy->of_node, "monitored-battery", 0);
> + if (!battery_np)
> + return -ENODEV;
> +
> + err = of_property_read_string(battery_np, "compatible", &value);
> + if (err)
> + return err;
> +
> + if (strcmp("fixed-battery", value))
> + return -ENODEV;
> +
> + of_property_read_u32(battery_np, "energy-full-design-microwatt-hours",
> + &info->energy_full_design_uwh);
> + of_property_read_u32(battery_np, "charge-full-design-microamp-hours",
> + &info->charge_full_design_uah);
> + of_property_read_u32(battery_np, "voltage-min-design-microvolt",
> + &info->voltage_min_design_uv);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(power_supply_get_battery_info);
> +
> int power_supply_get_property(struct power_supply *psy,
> enum power_supply_property psp,
> union power_supply_propval *val)
> diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
> index 3965503..e84f1d3 100644
> --- a/include/linux/power_supply.h
> +++ b/include/linux/power_supply.h
> @@ -288,6 +288,21 @@ struct power_supply_info {
> int use_for_apm;
> };
>
> +/*
> + * This is the recommended struct to manage static battery parameters,
> + * populated by power_supply_get_battery_info(). Most platform drivers should
> + * use these for consistency.
> + * Its field names must correspond to elements in enum power_supply_property.
> + * The default field value is -EINVAL.
> + * Power supply class itself doesn't use this.
> + */
> +
> +struct power_supply_battery_info {
> + int energy_full_design_uwh; /* microWatt-hours */
> + int charge_full_design_uah; /* microAmp-hours */
> + int voltage_min_design_uv; /* microVolts */
> +};
> +
> extern struct atomic_notifier_head power_supply_notifier;
> extern int power_supply_reg_notifier(struct notifier_block *nb);
> extern void power_supply_unreg_notifier(struct notifier_block *nb);
> @@ -306,6 +321,9 @@ static inline struct power_supply *
> devm_power_supply_get_by_phandle(struct device *dev, const char *property)
> { return NULL; }
> #endif /* CONFIG_OF */
> +
> +extern int power_supply_get_battery_info(struct power_supply *psy,
> + struct power_supply_battery_info *info);
> extern void power_supply_changed(struct power_supply *psy);
> extern int power_supply_am_i_supplied(struct power_supply *psy);
> extern int power_supply_set_battery_charged(struct power_supply *psy);
> --
> 2.9.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions
2017-03-15 19:26 ` [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions Liam Breck
@ 2017-03-15 22:14 ` Sebastian Reichel
2017-03-15 22:34 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Sebastian Reichel @ 2017-03-15 22:14 UTC (permalink / raw)
To: Liam Breck; +Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Liam Breck
[-- Attachment #1: Type: text/plain, Size: 3567 bytes --]
Hi,
On Wed, Mar 15, 2017 at 12:26:53PM -0700, Liam Breck wrote:
> From: Matt Ranostay <matt@ranostay.consulting>
>
> write(), read_bulk(), write_bulk() are required by bq27xxx_battery
> power_supply_battery_info code.
>
> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
> Signed-off-by: Liam Breck <kernel@networkimprov.net>
This is required by the previous patch, so your order is not bisect
safe. Please just merge it with Patch 5.
-- Sebastian
> drivers/power/supply/bq27xxx_battery_i2c.c | 82 +++++++++++++++++++++++++++++-
> 1 file changed, 81 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
> index 13def59..abdc266 100644
> --- a/drivers/power/supply/bq27xxx_battery_i2c.c
> +++ b/drivers/power/supply/bq27xxx_battery_i2c.c
> @@ -38,7 +38,7 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
> {
> struct i2c_client *client = to_i2c_client(di->dev);
> struct i2c_msg msg[2];
> - unsigned char data[2];
> + u8 data[2];
> int ret;
>
> if (!client->adapter)
> @@ -68,6 +68,82 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
> return ret;
> }
>
> +static int bq27xxx_battery_i2c_write(struct bq27xxx_device_info *di, u8 reg,
> + int value, bool single)
> +{
> + struct i2c_client *client = to_i2c_client(di->dev);
> + struct i2c_msg msg;
> + u8 data[4];
> + int ret;
> +
> + if (!client->adapter)
> + return -ENODEV;
> +
> + data[0] = reg;
> + if (single) {
> + data[1] = (u8) value;
> + msg.len = 2;
> + } else {
> + put_unaligned_le16(value, &data[1]);
> + msg.len = 3;
> + }
> +
> + msg.buf = data;
> + msg.addr = client->addr;
> + msg.flags = 0;
> +
> + ret = i2c_transfer(client->adapter, &msg, 1);
> + if (ret < 0)
> + return ret;
> + if (ret != 1)
> + return -EINVAL;
> + return 0;
> +}
> +
> +static int bq27xxx_battery_i2c_bulk_read(struct bq27xxx_device_info *di, u8 reg,
> + u8 *data, int len)
> +{
> + struct i2c_client *client = to_i2c_client(di->dev);
> + int ret;
> +
> + if (!client->adapter)
> + return -ENODEV;
> +
> + ret = i2c_smbus_read_i2c_block_data(client, reg, len, data);
> + if (ret < 0)
> + return ret;
> + if (ret != len)
> + return -EINVAL;
> + return 0;
> +}
> +
> +static int bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info *di,
> + u8 reg, u8 *data, int len)
> +{
> + struct i2c_client *client = to_i2c_client(di->dev);
> + struct i2c_msg msg;
> + u8 buf[33];
> + int ret;
> +
> + if (!client->adapter)
> + return -ENODEV;
> +
> + buf[0] = reg;
> + memcpy(&buf[1], data, len);
> +
> + msg.buf = buf;
> + msg.addr = client->addr;
> + msg.flags = 0;
> + msg.len = len + 1;
> +
> + ret = i2c_transfer(client->adapter, &msg, 1);
> + if (ret < 0)
> + return ret;
> + if (ret != 1)
> + return -EINVAL;
> + return 0;
> +}
> +
> static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> @@ -95,7 +171,11 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
> di->dev = &client->dev;
> di->chip = id->driver_data;
> di->name = name;
> +
> di->bus.read = bq27xxx_battery_i2c_read;
> + di->bus.write = bq27xxx_battery_i2c_write;
> + di->bus.read_bulk = bq27xxx_battery_i2c_bulk_read;
> + di->bus.write_bulk = bq27xxx_battery_i2c_bulk_write;
>
> ret = bq27xxx_battery_setup(di);
> if (ret)
> --
> 2.9.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
2017-03-15 22:04 ` Sebastian Reichel
@ 2017-03-15 22:18 ` Liam Breck
2017-03-15 22:57 ` Sebastian Reichel
0 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-15 22:18 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Andrew F. Davis, linux-pm-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA, Liam Breck
Hey Sebastian, welcome back :-)
I've taken over work on this patchset from Matt.
On Wed, Mar 15, 2017 at 3:04 PM, Sebastian Reichel <sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> Hi Liam & Matt,
>
> Sorry for my absence in the discussion. I skipped the previous
> iterations for now and start with this version.
>
> On Wed, Mar 15, 2017 at 12:26:46PM -0700, Liam Breck wrote:
>> From: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
>>
>> Documentation of static battery characteristics that can be defined
>> for batteries which cannot self-identify. This information is required
>> by fuel-gauge and charger chips for proper handling of the battery.
>>
>> Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
>> Signed-off-by: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
>> ---
>> .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++
>> 1 file changed, 45 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
>>
>> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
>> new file mode 100644
>> index 0000000..0278617
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
>> @@ -0,0 +1,45 @@
>> +Battery Characteristics
>
> Maybe add something like
>
> This device provides static battery information, that is usually
> available in the EEPROM of a smart battery. It's supposed to be
> used for batteries, which do not have their own EEPROM (or if its
> unusable).
OK.
>> +Required Properties:
>> + - compatible: Must be "fixed-battery"
Rob questioned the term "fixed". Shall we consider other terms --
simple-battery, plain-battery...?
>> +Optional Properties:
>> + - voltage-min-design-microvolt: drained battery voltage
>> + - energy-full-design-microwatt-hours: battery design energy
>> + - charge-full-design-microamp-hours: battery design capacity
>
> Looks fine to me.
>
>> +Because drivers surface properties in sysfs using names derived
>> +from enum power_supply_property, e.g.
>> +/sys/class/power_supply/<device>/charge_full_design, our
>> +battery properties must be named for the corresponding elements in
>> +enum power_supply_property, defined in include/linux/power_supply.h.
>
> This is Linux/implementation specific and does not belong
> into a DT binding document.
I just wrote on a thread for an earlier version of this patch:
"Sebastian proposed DT:battery specifically to be consumed by
power_supply_core. Allowing names in DT:battery and
power_supply_property to diverge would cause confusion and wasted
time, for no particular benefit. As there is no rationale to
reconsider the names of these fields for DT:battery, let's write that
into the docs."
>> +Batteries must be referenced by chargers and/or fuel-gauges
>> +using a phandle. The phandle's property should be named
>> +"monitored-battery".
>
> This looks fine.
>
>> +Driver code should call power_supply_get_battery_info() to obtain
>> +battery properties via monitored-battery. For details see:
>> + drivers/power/supply/power_supply_core.c
>> + drivers/power/supply/bq27xxx_battery.c
>
> This is also Linux/implementation specific and should be dropped.
We ought to mention how drivers are expected to consume DT:battery.
>> +Example:
>> +
>> + bat: battery {
>> + compatible = "fixed-battery";
>> + voltage-min-design-microvolt = <3200000>;
>> + energy-full-design-microwatt-hours = <5290000>;
>> + charge-full-design-microamp-hours = <1430000>;
>> + };
>> +
>> + charger: charger@11 {
>> + ....
>> + monitored-battery = <&bat>;
>> + ...
>> + };
>> +
>> + fuel_gauge: fuel-gauge@22 {
>> + ....
>> + monitored-battery = <&bat>;
>> + ...
>> + };
>> --
>> 2.9.3
>>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions
2017-03-15 22:14 ` Sebastian Reichel
@ 2017-03-15 22:34 ` Liam Breck
2017-03-15 23:03 ` Sebastian Reichel
0 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-15 22:34 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Liam Breck
On Wed, Mar 15, 2017 at 3:14 PM, Sebastian Reichel <sre@kernel.org> wrote:
> Hi,
>
> On Wed, Mar 15, 2017 at 12:26:53PM -0700, Liam Breck wrote:
>> From: Matt Ranostay <matt@ranostay.consulting>
>>
>> write(), read_bulk(), write_bulk() are required by bq27xxx_battery
>> power_supply_battery_info code.
>>
>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>
> This is required by the previous patch, so your order is not bisect
> safe. Please just merge it with Patch 5.
It is bisect-safe; bq27xxx_battery only uses the functions if available.
Patch 5 could be merged with 7. But the I2C implementation should be
separate from the header.
>> drivers/power/supply/bq27xxx_battery_i2c.c | 82 +++++++++++++++++++++++++++++-
>> 1 file changed, 81 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
>> index 13def59..abdc266 100644
>> --- a/drivers/power/supply/bq27xxx_battery_i2c.c
>> +++ b/drivers/power/supply/bq27xxx_battery_i2c.c
>> @@ -38,7 +38,7 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
>> {
>> struct i2c_client *client = to_i2c_client(di->dev);
>> struct i2c_msg msg[2];
>> - unsigned char data[2];
>> + u8 data[2];
>> int ret;
>>
>> if (!client->adapter)
>> @@ -68,6 +68,82 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
>> return ret;
>> }
>>
>> +static int bq27xxx_battery_i2c_write(struct bq27xxx_device_info *di, u8 reg,
>> + int value, bool single)
>> +{
>> + struct i2c_client *client = to_i2c_client(di->dev);
>> + struct i2c_msg msg;
>> + u8 data[4];
>> + int ret;
>> +
>> + if (!client->adapter)
>> + return -ENODEV;
>> +
>> + data[0] = reg;
>> + if (single) {
>> + data[1] = (u8) value;
>> + msg.len = 2;
>> + } else {
>> + put_unaligned_le16(value, &data[1]);
>> + msg.len = 3;
>> + }
>> +
>> + msg.buf = data;
>> + msg.addr = client->addr;
>> + msg.flags = 0;
>> +
>> + ret = i2c_transfer(client->adapter, &msg, 1);
>> + if (ret < 0)
>> + return ret;
>> + if (ret != 1)
>> + return -EINVAL;
>> + return 0;
>> +}
>> +
>> +static int bq27xxx_battery_i2c_bulk_read(struct bq27xxx_device_info *di, u8 reg,
>> + u8 *data, int len)
>> +{
>> + struct i2c_client *client = to_i2c_client(di->dev);
>> + int ret;
>> +
>> + if (!client->adapter)
>> + return -ENODEV;
>> +
>> + ret = i2c_smbus_read_i2c_block_data(client, reg, len, data);
>> + if (ret < 0)
>> + return ret;
>> + if (ret != len)
>> + return -EINVAL;
>> + return 0;
>> +}
>> +
>> +static int bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info *di,
>> + u8 reg, u8 *data, int len)
>> +{
>> + struct i2c_client *client = to_i2c_client(di->dev);
>> + struct i2c_msg msg;
>> + u8 buf[33];
>> + int ret;
>> +
>> + if (!client->adapter)
>> + return -ENODEV;
>> +
>> + buf[0] = reg;
>> + memcpy(&buf[1], data, len);
>> +
>> + msg.buf = buf;
>> + msg.addr = client->addr;
>> + msg.flags = 0;
>> + msg.len = len + 1;
>> +
>> + ret = i2c_transfer(client->adapter, &msg, 1);
>> + if (ret < 0)
>> + return ret;
>> + if (ret != 1)
>> + return -EINVAL;
>> + return 0;
>> +}
>> +
>> static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
>> const struct i2c_device_id *id)
>> {
>> @@ -95,7 +171,11 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
>> di->dev = &client->dev;
>> di->chip = id->driver_data;
>> di->name = name;
>> +
>> di->bus.read = bq27xxx_battery_i2c_read;
>> + di->bus.write = bq27xxx_battery_i2c_write;
>> + di->bus.read_bulk = bq27xxx_battery_i2c_bulk_read;
>> + di->bus.write_bulk = bq27xxx_battery_i2c_bulk_write;
>>
>> ret = bq27xxx_battery_setup(di);
>> if (ret)
>> --
>> 2.9.3
>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
2017-03-15 22:18 ` Liam Breck
@ 2017-03-15 22:57 ` Sebastian Reichel
2017-03-16 13:21 ` Andrew F. Davis
0 siblings, 1 reply; 35+ messages in thread
From: Sebastian Reichel @ 2017-03-15 22:57 UTC (permalink / raw)
To: Liam Breck; +Cc: Andrew F. Davis, linux-pm, Rob Herring, devicetree, Liam Breck
[-- Attachment #1: Type: text/plain, Size: 4986 bytes --]
Hi,
On Wed, Mar 15, 2017 at 03:18:17PM -0700, Liam Breck wrote:
> Hey Sebastian, welcome back :-)
>
> I've taken over work on this patchset from Matt.
Ok.
> On Wed, Mar 15, 2017 at 3:04 PM, Sebastian Reichel <sre@kernel.org> wrote:
> > Hi Liam & Matt,
> >
> > Sorry for my absence in the discussion. I skipped the previous
> > iterations for now and start with this version.
> >
> > On Wed, Mar 15, 2017 at 12:26:46PM -0700, Liam Breck wrote:
> >> From: Liam Breck <kernel@networkimprov.net>
> >>
> >> Documentation of static battery characteristics that can be defined
> >> for batteries which cannot self-identify. This information is required
> >> by fuel-gauge and charger chips for proper handling of the battery.
> >>
> >> Cc: Rob Herring <robh@kernel.org>
> >> Cc: devicetree@vger.kernel.org
> >> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
> >> Signed-off-by: Liam Breck <kernel@networkimprov.net>
> >> ---
> >> .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++
> >> 1 file changed, 45 insertions(+)
> >> create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
> >>
> >> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
> >> new file mode 100644
> >> index 0000000..0278617
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
> >> @@ -0,0 +1,45 @@
> >> +Battery Characteristics
> >
> > Maybe add something like
> >
> > This device provides static battery information, that is usually
> > available in the EEPROM of a smart battery. It's supposed to be
> > used for batteries, which do not have their own EEPROM (or if its
> > unusable).
>
> OK.
>
> >> +Required Properties:
> >> + - compatible: Must be "fixed-battery"
>
> Rob questioned the term "fixed". Shall we consider other terms --
> simple-battery, plain-battery...?
I don't like the term either, but it was the best I came up with.
They are known as "dumb" batteries, but that term looks too
colloquial for DT usage. While I think "simple-battery" is not
perfect either, it's better than "fixed-battery", so please switch
to that in the next revision.
> >> +Optional Properties:
> >> + - voltage-min-design-microvolt: drained battery voltage
> >> + - energy-full-design-microwatt-hours: battery design energy
> >> + - charge-full-design-microamp-hours: battery design capacity
> >
> > Looks fine to me.
> >
> >> +Because drivers surface properties in sysfs using names derived
> >> +from enum power_supply_property, e.g.
> >> +/sys/class/power_supply/<device>/charge_full_design, our
> >> +battery properties must be named for the corresponding elements in
> >> +enum power_supply_property, defined in include/linux/power_supply.h.
> >
> > This is Linux/implementation specific and does not belong
> > into a DT binding document.
>
> I just wrote on a thread for an earlier version of this patch:
>
> "Sebastian proposed DT:battery specifically to be consumed by
> power_supply_core. Allowing names in DT:battery and
> power_supply_property to diverge would cause confusion and wasted
> time, for no particular benefit. As there is no rationale to
> reconsider the names of these fields for DT:battery, let's write that
> into the docs."
DT bindings are not "Linux hardware information bindings". Of course
there is no need to diverge without a good reason, but that kind of
Documentation just does not belong into the DT bindings.
> >> +Batteries must be referenced by chargers and/or fuel-gauges
> >> +using a phandle. The phandle's property should be named
> >> +"monitored-battery".
> >
> > This looks fine.
> >
> >> +Driver code should call power_supply_get_battery_info() to obtain
> >> +battery properties via monitored-battery. For details see:
> >> + drivers/power/supply/power_supply_core.c
> >> + drivers/power/supply/bq27xxx_battery.c
> >
> > This is also Linux/implementation specific and should be dropped.
>
> We ought to mention how drivers are expected to consume DT:battery.
That kind of documentation does not belong into
Documentation/devicetree/bindings. We can add something to
Documentation/power/power_supply_class.txt instead.
> >> +Example:
> >> +
> >> + bat: battery {
> >> + compatible = "fixed-battery";
> >> + voltage-min-design-microvolt = <3200000>;
> >> + energy-full-design-microwatt-hours = <5290000>;
> >> + charge-full-design-microamp-hours = <1430000>;
> >> + };
> >> +
> >> + charger: charger@11 {
> >> + ....
> >> + monitored-battery = <&bat>;
> >> + ...
> >> + };
> >> +
> >> + fuel_gauge: fuel-gauge@22 {
> >> + ....
> >> + monitored-battery = <&bat>;
> >> + ...
> >> + };
> >> --
> >> 2.9.3
> >>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions
2017-03-15 22:34 ` Liam Breck
@ 2017-03-15 23:03 ` Sebastian Reichel
0 siblings, 0 replies; 35+ messages in thread
From: Sebastian Reichel @ 2017-03-15 23:03 UTC (permalink / raw)
To: Liam Breck; +Cc: Andrew F. Davis, linux-pm, Matt Ranostay, Liam Breck
[-- Attachment #1: Type: text/plain, Size: 898 bytes --]
Hi,
On Wed, Mar 15, 2017 at 03:34:23PM -0700, Liam Breck wrote:
> On Wed, Mar 15, 2017 at 3:14 PM, Sebastian Reichel <sre@kernel.org> wrote:
> > Hi,
> >
> > On Wed, Mar 15, 2017 at 12:26:53PM -0700, Liam Breck wrote:
> >> From: Matt Ranostay <matt@ranostay.consulting>
> >>
> >> write(), read_bulk(), write_bulk() are required by bq27xxx_battery
> >> power_supply_battery_info code.
> >>
> >> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
> >> Signed-off-by: Liam Breck <kernel@networkimprov.net>
> >
> > This is required by the previous patch, so your order is not bisect
> > safe. Please just merge it with Patch 5.
>
> It is bisect-safe; bq27xxx_battery only uses the functions if available.
ok.
> Patch 5 could be merged with 7. But the I2C implementation should be
> separate from the header.
Please at least move the patches together.
-- Sebastian
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
2017-03-15 22:57 ` Sebastian Reichel
@ 2017-03-16 13:21 ` Andrew F. Davis
2017-03-16 22:58 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Andrew F. Davis @ 2017-03-16 13:21 UTC (permalink / raw)
To: Sebastian Reichel, Liam Breck
Cc: linux-pm-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA, Liam Breck
On 03/15/2017 05:57 PM, Sebastian Reichel wrote:
> Hi,
>
> On Wed, Mar 15, 2017 at 03:18:17PM -0700, Liam Breck wrote:
>> Hey Sebastian, welcome back :-)
>>
>> I've taken over work on this patchset from Matt.
>
> Ok.
>
>> On Wed, Mar 15, 2017 at 3:04 PM, Sebastian Reichel <sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>>> Hi Liam & Matt,
>>>
>>> Sorry for my absence in the discussion. I skipped the previous
>>> iterations for now and start with this version.
>>>
>>> On Wed, Mar 15, 2017 at 12:26:46PM -0700, Liam Breck wrote:
>>>> From: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
>>>>
>>>> Documentation of static battery characteristics that can be defined
>>>> for batteries which cannot self-identify. This information is required
>>>> by fuel-gauge and charger chips for proper handling of the battery.
>>>>
>>>> Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>>>> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>>>> Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
>>>> Signed-off-by: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
>>>> ---
>>>> .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++
>>>> 1 file changed, 45 insertions(+)
>>>> create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>> new file mode 100644
>>>> index 0000000..0278617
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>> @@ -0,0 +1,45 @@
>>>> +Battery Characteristics
>>>
>>> Maybe add something like
>>>
>>> This device provides static battery information, that is usually
>>> available in the EEPROM of a smart battery. It's supposed to be
>>> used for batteries, which do not have their own EEPROM (or if its
>>> unusable).
>>
>> OK.
>>
>>>> +Required Properties:
>>>> + - compatible: Must be "fixed-battery"
>>
>> Rob questioned the term "fixed". Shall we consider other terms --
>> simple-battery, plain-battery...?
>
> I don't like the term either, but it was the best I came up with.
> They are known as "dumb" batteries, but that term looks too
> colloquial for DT usage. While I think "simple-battery" is not
> perfect either, it's better than "fixed-battery", so please switch
> to that in the next revision.
>
I rather like "fixed-battery", it matches the regulator and other power
source DTs better. To answer Rob's question on what a non-fixed battery
would look like we can think of a future battery that can change its
physical properties (chemical or physical perhaps) in response to
software. Although I've not seen such a battery I don't think it's too
far-fetched.
All the properties described here are "fixed", if we say "simple" then a
battery with more properties would be a "complex" battery..
>>>> +Optional Properties:
>>>> + - voltage-min-design-microvolt: drained battery voltage
>>>> + - energy-full-design-microwatt-hours: battery design energy
>>>> + - charge-full-design-microamp-hours: battery design capacity
>>>
>>> Looks fine to me.
>>>
>>>> +Because drivers surface properties in sysfs using names derived
>>>> +from enum power_supply_property, e.g.
>>>> +/sys/class/power_supply/<device>/charge_full_design, our
>>>> +battery properties must be named for the corresponding elements in
>>>> +enum power_supply_property, defined in include/linux/power_supply.h.
>>>
>>> This is Linux/implementation specific and does not belong
>>> into a DT binding document.
>>
>> I just wrote on a thread for an earlier version of this patch:
>>
>> "Sebastian proposed DT:battery specifically to be consumed by
>> power_supply_core. Allowing names in DT:battery and
>> power_supply_property to diverge would cause confusion and wasted
>> time, for no particular benefit. As there is no rationale to
>> reconsider the names of these fields for DT:battery, let's write that
>> into the docs."
>
> DT bindings are not "Linux hardware information bindings". Of course
> there is no need to diverge without a good reason, but that kind of
> Documentation just does not belong into the DT bindings.
>
>>>> +Batteries must be referenced by chargers and/or fuel-gauges
>>>> +using a phandle. The phandle's property should be named
>>>> +"monitored-battery".
>>>
>>> This looks fine.
>>>
>>>> +Driver code should call power_supply_get_battery_info() to obtain
>>>> +battery properties via monitored-battery. For details see:
>>>> + drivers/power/supply/power_supply_core.c
>>>> + drivers/power/supply/bq27xxx_battery.c
>>>
>>> This is also Linux/implementation specific and should be dropped.
>>
>> We ought to mention how drivers are expected to consume DT:battery.
>
> That kind of documentation does not belong into
> Documentation/devicetree/bindings. We can add something to
> Documentation/power/power_supply_class.txt instead.
>
>>>> +Example:
>>>> +
>>>> + bat: battery {
>>>> + compatible = "fixed-battery";
>>>> + voltage-min-design-microvolt = <3200000>;
>>>> + energy-full-design-microwatt-hours = <5290000>;
>>>> + charge-full-design-microamp-hours = <1430000>;
>>>> + };
>>>> +
>>>> + charger: charger@11 {
>>>> + ....
>>>> + monitored-battery = <&bat>;
>>>> + ...
>>>> + };
>>>> +
>>>> + fuel_gauge: fuel-gauge@22 {
>>>> + ....
>>>> + monitored-battery = <&bat>;
>>>> + ...
>>>> + };
>>>> --
>>>> 2.9.3
>>>>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
2017-03-15 19:26 ` [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id Liam Breck
@ 2017-03-16 14:44 ` Andrew F. Davis
2017-03-16 20:12 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Andrew F. Davis @ 2017-03-16 14:44 UTC (permalink / raw)
To: Liam Breck, Sebastian Reichel; +Cc: linux-pm, Matt Ranostay, Liam Breck
On 03/15/2017 02:26 PM, Liam Breck wrote:
> From: Liam Breck <kernel@networkimprov.net>
>
> Pass actual chip ID into _setup(), which translates it to a group ID,
> to allow support for all chips by the power_supply_battery_info code.
> There are no functional changes to the driver.
>
> Signed-off-by: Liam Breck <kernel@networkimprov.net>
> ---
What is this patch based on, it doesn't apply to v4.11-rc1 for me.
> drivers/power/supply/bq27xxx_battery.c | 19 +++++++++++++++++++
> drivers/power/supply/bq27xxx_battery_i2c.c | 16 ++++++++--------
> include/linux/power/bq27xxx_battery.h | 25 ++++++++++++++++++-------
> 3 files changed, 45 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
> index 7272d1e..d613d3d 100644
> --- a/drivers/power/supply/bq27xxx_battery.c
> +++ b/drivers/power/supply/bq27xxx_battery.c
> @@ -1020,6 +1020,25 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
> struct power_supply_desc *psy_desc;
> struct power_supply_config psy_cfg = { .drv_data = di, };
>
> + switch(di->chip) {
> + case BQ27000:
> + case BQ27010:
> + case BQ27500:
> + case BQ27510:
> + case BQ27530:
> + case BQ27541:
> + case BQ27545:
> + case BQ27421: break;
Why even have these cases then?
> + case BQ27520: di->chip = BQ27510; break;
> + case BQ27531: di->chip = BQ27530; break;
> + case BQ27542: di->chip = BQ27541; break;
> + case BQ27546: di->chip = BQ27541; break;
> + case BQ27742: di->chip = BQ27541; break;
> + case BQ27425: di->chip = BQ27421; break;
> + case BQ27441: di->chip = BQ27421; break;
> + case BQ27621: di->chip = BQ27421; break;
Nope, don't like this at all, make a different variable, ->registers or
something to map to the register table. Plus I think changing the
variable you are switching on can cause undefined behavior.
> + }
> +
> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
> mutex_init(&di->lock);
> di->regs = bq27xxx_regs[di->chip];
> diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
> index 5c5c3a6..13def59 100644
> --- a/drivers/power/supply/bq27xxx_battery_i2c.c
> +++ b/drivers/power/supply/bq27xxx_battery_i2c.c
> @@ -150,18 +150,18 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
> { "bq27210", BQ27010 },
> { "bq27500", BQ27500 },
> { "bq27510", BQ27510 },
> - { "bq27520", BQ27510 },
> + { "bq27520", BQ27520 },
> { "bq27530", BQ27530 },
> - { "bq27531", BQ27530 },
> + { "bq27531", BQ27531 },
> { "bq27541", BQ27541 },
> - { "bq27542", BQ27541 },
> - { "bq27546", BQ27541 },
> - { "bq27742", BQ27541 },
> + { "bq27542", BQ27542 },
> + { "bq27546", BQ27546 },
> + { "bq27742", BQ27742 },
> { "bq27545", BQ27545 },
> { "bq27421", BQ27421 },
> - { "bq27425", BQ27421 },
> - { "bq27441", BQ27421 },
> - { "bq27621", BQ27421 },
> + { "bq27425", BQ27425 },
> + { "bq27441", BQ27441 },
> + { "bq27621", BQ27621 },
> {},
> };
> MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
> index 92df553..90db1cf 100644
> --- a/include/linux/power/bq27xxx_battery.h
> +++ b/include/linux/power/bq27xxx_battery.h
> @@ -2,14 +2,25 @@
> #define __LINUX_BQ27X00_BATTERY_H__
>
> enum bq27xxx_chip {
> + /* categories; index for bq27xxx_regs[] */
> BQ27000 = 1, /* bq27000, bq27200 */
> - BQ27010, /* bq27010, bq27210 */
> - BQ27500, /* bq27500 */
> - BQ27510, /* bq27510, bq27520 */
> - BQ27530, /* bq27530, bq27531 */
> - BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
> - BQ27545, /* bq27545 */
> - BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
> + BQ27010 = 2, /* bq27010, bq27210 */
> + BQ27500 = 3, /* bq27500 */
> + BQ27510 = 4, /* bq27510, bq27520 */
> + BQ27530 = 5, /* bq27530, bq27531 */
> + BQ27541 = 6, /* bq27541, bq27542, bq27546, bq27742 */
> + BQ27545 = 7, /* bq27545 */
> + BQ27421 = 8, /* bq27421, bq27425, bq27441, bq27621 */
> +
> + /* members of categories; translate these to category in _setup() */
> + BQ27520 = 101,
> + BQ27531 = 102,
> + BQ27542 = 103,
> + BQ27546 = 104,
> + BQ27742 = 105,
> + BQ27425 = 106,
> + BQ27441 = 107,
> + BQ27621 = 108,
Get rid of this, just add new chip enum names if you need support for
new chips.
> };
>
> /**
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support
2017-03-15 19:26 ` [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support Liam Breck
@ 2017-03-16 15:00 ` Andrew F. Davis
2017-03-16 21:12 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Andrew F. Davis @ 2017-03-16 15:00 UTC (permalink / raw)
To: Liam Breck, Sebastian Reichel; +Cc: linux-pm, Matt Ranostay, Liam Breck
On 03/15/2017 02:26 PM, Liam Breck wrote:
> From: Liam Breck <kernel@networkimprov.net>
>
> Previously there was no way to configure chip registers in the event that the
> defaults didn't match the battery in question.
>
> BQ27xxx driver now calls power_supply_get_battery_info, checks the inputs,
> and writes battery data to chip RAM or non-volatile memory.
>
> Supports chips BQ27500, 545, 421, 425, 441, 621. Others may be added.
>
> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
> Signed-off-by: Liam Breck <kernel@networkimprov.net>
> ---
> drivers/power/supply/bq27xxx_battery.c | 478 ++++++++++++++++++++++++++++++++-
> include/linux/power/bq27xxx_battery.h | 2 +
> 2 files changed, 468 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
> index d613d3d..fb062db 100644
> --- a/drivers/power/supply/bq27xxx_battery.c
> +++ b/drivers/power/supply/bq27xxx_battery.c
> @@ -51,7 +51,7 @@
>
> #include <linux/power/bq27xxx_battery.h>
>
> -#define DRIVER_VERSION "1.2.0"
> +#define DRIVER_VERSION "1.3.0"
>
> #define BQ27XXX_MANUFACTURER "Texas Instruments"
>
> @@ -59,6 +59,7 @@
> #define BQ27XXX_FLAG_DSC BIT(0)
> #define BQ27XXX_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
> #define BQ27XXX_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
> +#define BQ27XXX_FLAG_CFGUP BIT(4)
> #define BQ27XXX_FLAG_FC BIT(9)
> #define BQ27XXX_FLAG_OTD BIT(14)
> #define BQ27XXX_FLAG_OTC BIT(15)
> @@ -72,6 +73,11 @@
> #define BQ27000_FLAG_FC BIT(5)
> #define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
>
> +/* control register params */
> +#define BQ27XXX_SEALED 0x20
> +#define BQ27XXX_SET_CFGUPDATE 0x13
> +#define BQ27XXX_SOFT_RESET 0x42
> +
> #define BQ27XXX_RS (20) /* Resistor sense mOhm */
> #define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */
> #define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */
> @@ -102,6 +108,11 @@ enum bq27xxx_reg_index {
> BQ27XXX_REG_SOC, /* State-of-Charge */
> BQ27XXX_REG_DCAP, /* Design Capacity */
> BQ27XXX_REG_AP, /* Average Power */
> + BQ27XXX_DM_CTRL, /* BlockDataControl() */
> + BQ27XXX_DM_CLASS, /* DataClass() */
> + BQ27XXX_DM_BLOCK, /* DataBlock() */
> + BQ27XXX_DM_DATA, /* BlockData() */
> + BQ27XXX_DM_CKSUM, /* BlockDataChecksum() */
> BQ27XXX_REG_MAX, /* sentinel */
> };
>
> @@ -125,6 +136,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
> [BQ27XXX_REG_SOC] = 0x0b,
> [BQ27XXX_REG_DCAP] = 0x76,
> [BQ27XXX_REG_AP] = 0x24,
> + [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_DATA] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR,
> },
> [BQ27010] = {
> [BQ27XXX_REG_CTRL] = 0x00,
> @@ -144,6 +160,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
> [BQ27XXX_REG_SOC] = 0x0b,
> [BQ27XXX_REG_DCAP] = 0x76,
> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_DATA] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR,
> },
> [BQ27500] = {
> [BQ27XXX_REG_CTRL] = 0x00,
> @@ -163,6 +184,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
> [BQ27XXX_REG_SOC] = 0x2c,
> [BQ27XXX_REG_DCAP] = 0x3c,
> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_CTRL] = 0x61,
> + [BQ27XXX_DM_CLASS] = 0x3e,
> + [BQ27XXX_DM_BLOCK] = 0x3f,
> + [BQ27XXX_DM_DATA] = 0x40,
> + [BQ27XXX_DM_CKSUM] = 0x60,
> },
> [BQ27510] = {
> [BQ27XXX_REG_CTRL] = 0x00,
> @@ -182,6 +208,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
> [BQ27XXX_REG_SOC] = 0x20,
> [BQ27XXX_REG_DCAP] = 0x2e,
> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
> + [BQ27XXX_DM_CTRL] = 0x61,
> + [BQ27XXX_DM_CLASS] = 0x3e,
> + [BQ27XXX_DM_BLOCK] = 0x3f,
> + [BQ27XXX_DM_DATA] = 0x40,
> + [BQ27XXX_DM_CKSUM] = 0x60,
> },
> [BQ27530] = {
> [BQ27XXX_REG_CTRL] = 0x00,
> @@ -201,6 +232,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
> [BQ27XXX_REG_SOC] = 0x2c,
> [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
> [BQ27XXX_REG_AP] = 0x24,
> + [BQ27XXX_DM_CTRL] = 0x61,
> + [BQ27XXX_DM_CLASS] = 0x3e,
> + [BQ27XXX_DM_BLOCK] = 0x3f,
> + [BQ27XXX_DM_DATA] = 0x40,
> + [BQ27XXX_DM_CKSUM] = 0x60,
> },
> [BQ27541] = {
> [BQ27XXX_REG_CTRL] = 0x00,
> @@ -220,6 +256,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
> [BQ27XXX_REG_SOC] = 0x2c,
> [BQ27XXX_REG_DCAP] = 0x3c,
> [BQ27XXX_REG_AP] = 0x24,
> + [BQ27XXX_DM_CTRL] = 0x61,
> + [BQ27XXX_DM_CLASS] = 0x3e,
> + [BQ27XXX_DM_BLOCK] = 0x3f,
> + [BQ27XXX_DM_DATA] = 0x40,
> + [BQ27XXX_DM_CKSUM] = 0x60,
> },
> [BQ27545] = {
> [BQ27XXX_REG_CTRL] = 0x00,
> @@ -239,6 +280,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
> [BQ27XXX_REG_SOC] = 0x2c,
> [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
> [BQ27XXX_REG_AP] = 0x24,
> + [BQ27XXX_DM_CTRL] = 0x61,
> + [BQ27XXX_DM_CLASS] = 0x3e,
> + [BQ27XXX_DM_BLOCK] = 0x3f,
> + [BQ27XXX_DM_DATA] = 0x40,
> + [BQ27XXX_DM_CKSUM] = 0x60,
> },
> [BQ27421] = {
> [BQ27XXX_REG_CTRL] = 0x00,
> @@ -258,6 +304,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
> [BQ27XXX_REG_SOC] = 0x1c,
> [BQ27XXX_REG_DCAP] = 0x3c,
> [BQ27XXX_REG_AP] = 0x18,
> + [BQ27XXX_DM_CTRL] = 0x61,
> + [BQ27XXX_DM_CLASS] = 0x3e,
> + [BQ27XXX_DM_BLOCK] = 0x3f,
> + [BQ27XXX_DM_DATA] = 0x40,
> + [BQ27XXX_DM_CKSUM] = 0x60,
> },
> };
>
> @@ -432,6 +483,82 @@ static struct {
> static DEFINE_MUTEX(bq27xxx_list_lock);
> static LIST_HEAD(bq27xxx_battery_devices);
>
> +#define BQ27XXX_DM_SZ 32
> +
> +#define BQ27XXX_MSLEEP(i) usleep_range((i)*1000, (i)*1000+500)
> +
> +struct bq27xxx_dm_reg {
> + u8 subclass_id;
> + u8 offset;
> + u8 bytes;
> + u16 min, max;
> +};
> +
> +struct bq27xxx_dm_buf {
> + u8 class;
> + u8 block;
> + u8 a[BQ27XXX_DM_SZ];
> + bool full, updt;
> +};
> +
> +#define BQ27XXX_DM_BUF(di, i) { \
> + .class = (di)->dm_regs[i].subclass_id, \
> + .block = (di)->dm_regs[i].offset / BQ27XXX_DM_SZ, \
> +}
> +
> +static inline u16* bq27xxx_dm_reg_ptr(struct bq27xxx_dm_buf *buf,
> + struct bq27xxx_dm_reg *reg)
> +{
> + if (buf->class == reg->subclass_id
> + && buf->block == reg->offset / BQ27XXX_DM_SZ)
> + return (u16*) (buf->a + reg->offset % BQ27XXX_DM_SZ);
> +
> + return NULL;
> +}
> +
> +enum bq27xxx_dm_reg_id {
> + BQ27XXX_DM_DESIGN_CAPACITY = 0,
> + BQ27XXX_DM_DESIGN_ENERGY,
> + BQ27XXX_DM_TERMINATE_VOLTAGE,
> +};
> +
> +static const char* bq27xxx_dm_reg_name[] = {
> + [BQ27XXX_DM_DESIGN_CAPACITY] = "design-capacity",
> + [BQ27XXX_DM_DESIGN_ENERGY] = "design-energy",
> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = "terminate-voltage",
> +};
> +
> +static struct bq27xxx_dm_reg bq27500_dm_regs[] = {
> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 10, 2, 0, 65535 },
> + [BQ27XXX_DM_DESIGN_ENERGY] = { }, /* missing on chip */
> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 48, 2, 1000, 32767 },
> +};
> +
> +static struct bq27xxx_dm_reg bq27545_dm_regs[] = {
> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 23, 2, 0, 32767 },
> + [BQ27XXX_DM_DESIGN_ENERGY] = { 48, 25, 2, 0, 32767 },
> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 67, 2, 2800, 3700 },
> +};
> +
> +static struct bq27xxx_dm_reg bq27421_dm_regs[] = {
> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 8000 },
> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 },
> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 16, 2, 2500, 3700 },
> +};
> +
> +static struct bq27xxx_dm_reg bq27425_dm_regs[] = {
> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 12, 2, 0, 32767 },
> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 14, 2, 0, 32767 },
> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 18, 2, 2800, 3700 },
> +};
> +
> +static struct bq27xxx_dm_reg bq27621_dm_regs[] = {
> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 3, 2, 0, 8000 },
> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 5, 2, 0, 32767 },
> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 9, 2, 2500, 3700 },
> +};
> +
> +
> static int poll_interval_param_set(const char *val, const struct kernel_param *kp)
> {
> struct bq27xxx_device_info *di;
> @@ -476,6 +603,317 @@ static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index,
> return di->bus.read(di, di->regs[reg_index], single);
> }
>
> +static int bq27xxx_battery_set_seal_state(struct bq27xxx_device_info *di,
> + bool state)
> +{
> + int ret;
> +
> + if (state) {
> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], BQ27XXX_SEALED, false);
Look at how reads are done, we have a function bq27xxx_read() that
checks the register and handles the access methods. Do something like
that for write, then replace all these with that, "bus" should only be
accessed in that function.
> + if (ret < 0)
> + goto out;
> + } else {
> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], (u16)(di->unseal_key >> 16), false);
> + if (ret < 0)
> + goto out;
> +
> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], (u16)di->unseal_key, false);
> + if (ret < 0)
> + goto out;
> + }
+space
Has this been run through checkpatch?
> + return 0;
> +
> +out:
> + dev_err(di->dev, "bus error on %s: %d\n", state ? "seal" : "unseal", ret);
> + return ret;
> +}
> +
> +static u8 bq27xxx_battery_checksum_dm_block(struct bq27xxx_dm_buf *buf)
> +{
> + u16 sum = 0;
> + int i;
> +
> + for (i = 0; i < BQ27XXX_DM_SZ; i++)
> + sum += buf->a[i];
> + sum &= 0xff;
> +
> + return 0xff - sum;
> +}
> +
> +static int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di,
> + struct bq27xxx_dm_buf *buf)
> +{
> + int ret;
> +
> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CLASS], buf->class, true);
> + if (ret < 0)
> + goto out;
> +
> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_BLOCK], buf->block, true);
> + if (ret < 0)
> + goto out;
> +
> + BQ27XXX_MSLEEP(1);
> +
> + ret = di->bus.read_bulk(di, di->regs[BQ27XXX_DM_DATA], buf->a, BQ27XXX_DM_SZ);
> + if (ret < 0)
> + goto out;
> +
> + ret = di->bus.read(di, di->regs[BQ27XXX_DM_CKSUM], true);
> + if (ret < 0)
> + goto out;
> +
> + if ((u8)ret != bq27xxx_battery_checksum_dm_block(buf)) {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + buf->full = true;
> + buf->updt = false;
> + return 0;
> +
> +out:
> + dev_err(di->dev, "bus error reading chip memory: %d\n", ret);
Instead of this catch-all, each spot should have an error message that
explains what failed. If they all end up with this generic message we
cannot possibly diagnose issues for people.
> + return ret;
> +}
> +
> +static void bq27xxx_battery_update_dm_block(struct bq27xxx_device_info *di,
> + struct bq27xxx_dm_buf *buf,
> + enum bq27xxx_dm_reg_id reg_id,
> + unsigned int val)
> +{
> + struct bq27xxx_dm_reg *reg = &di->dm_regs[reg_id];
> + const char* str = bq27xxx_dm_reg_name[reg_id];
> + u16 *prev = bq27xxx_dm_reg_ptr(buf, reg);
> +
> + if (prev == NULL) {
> + dev_warn(di->dev, "buffer does not match %s dm spec\n", str);
> + return;
> + }
> +
> + if (reg->bytes != 2) {
> + dev_warn(di->dev, "%s dm spec has unsupported byte size\n", str);
> + return;
> + }
> +
> + if (!buf->full)
> + return;
> +
> + if (be16_to_cpup(prev) == val) {
> + dev_info(di->dev, "%s has %u\n", str, val);
> + return;
> + }
> +
> + dev_info(di->dev, "update %s to %u\n", str, val);
> +
> + *prev = cpu_to_be16(val);
> + buf->updt = true;
> +}
> +
> +static int bq27xxx_battery_set_cfgupdate(struct bq27xxx_device_info *di,
> + bool state)
Why only two states? why bool? you should probably be passing in the
value, if you really want to do this as a state, then the states should
have an enum for each state.
> +{
> + int ret, try=100;
> +
> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL],
> + state ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET,
> + false);
> + if (ret < 0)
> + goto out;
> +
> + do {
> + BQ27XXX_MSLEEP(25);
> + ret = di->bus.read(di, di->regs[BQ27XXX_REG_FLAGS], false);
> + if (ret < 0)
> + goto out;
> + } while (!(ret & BQ27XXX_FLAG_CFGUP) == state && --try);
> +
> + if (!try) {
> + dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", state);
> + return -EINVAL;
> + }
Put this check inside the loop.
> +
> + if (100-try > 3)
Why 3? lets also count up to a set value, 100 is a magic number, if I
change try to =200, I have to change it down here, that is going to be
buggy.
> + dev_warn(di->dev, "cfgupdate %d, retries %d\n", state, 100-try);
> +
> + return 0;
> +
> +out:
> + dev_err(di->dev, "bus error on %s: %d\n", state ? "set_cfgupdate" : "soft_reset", ret);
> + return ret;
> +}
> +
> +static int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di,
> + struct bq27xxx_dm_buf *buf)
> +{
> + bool cfgup = di->chip == BQ27421; /* assume group supports cfgupdate */
> + int ret;
> +
> + if (!buf->updt)
> + return 0;
> +
> + if (cfgup) {
> + ret = bq27xxx_battery_set_cfgupdate(di, true);
> + if (ret < 0)
> + return ret;
> + }
> +
> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CTRL], 0, true);
> + if (ret < 0)
> + goto out;
> +
> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CLASS], buf->class, true);
> + if (ret < 0)
> + goto out;
> +
> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_BLOCK], buf->block, true);
> + if (ret < 0)
> + goto out;
> +
> + BQ27XXX_MSLEEP(1);
> +
> + ret = di->bus.write_bulk(di, di->regs[BQ27XXX_DM_DATA], buf->a, BQ27XXX_DM_SZ);
> + if (ret < 0)
> + goto out;
> +
> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CKSUM],
> + bq27xxx_battery_checksum_dm_block(buf), true);
> + if (ret < 0)
> + goto out;
> +
> + /* THE FOLLOWING SEQUENCE IS TOXIC. DO NOT USE!
> + * If the 'time' delay is insufficient, NVM corruption results on
> + * the '425 chip (and perhaps others), which could damage the chip.
> + * It was suggested in this TI tool:
> + * http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328
> + *
> + * 1. MSLEEP(time) after above write(BQ27XXX_DM_CKSUM, ...)
> + * 2. write(BQ27XXX_DM_BLOCK, buf->block)
> + * 3. sum = read(BQ27XXX_DM_CKSUM)
> + * 4. if (sum != bq27xxx_battery_checksum_dm_block(buf))
> + * report error
> + */
> +
> + if (cfgup) {
> + BQ27XXX_MSLEEP(1);
> + ret = bq27xxx_battery_set_cfgupdate(di, false);
> + if (ret < 0)
> + return ret;
> + } else {
> + /* flash DM updates in <100ms, but reset time isn't documented */
> + BQ27XXX_MSLEEP(400);
> + }
> +
> + buf->updt = false;
> + return 0;
> +
> +out:
> + if (cfgup)
> + bq27xxx_battery_set_cfgupdate(di, false);
> +
> + dev_err(di->dev, "bus error writing chip memory: %d\n", ret);
> + return ret;
> +}
> +
> +static void bq27xxx_battery_set_config(struct bq27xxx_device_info *di,
> + struct power_supply_battery_info *info)
> +{
> + struct bq27xxx_dm_buf bd = BQ27XXX_DM_BUF(di, BQ27XXX_DM_DESIGN_CAPACITY);
> + struct bq27xxx_dm_buf bt = BQ27XXX_DM_BUF(di, BQ27XXX_DM_TERMINATE_VOLTAGE);
> +
> + if (info->charge_full_design_uah != -EINVAL
> + && info->energy_full_design_uwh != -EINVAL) {
> + bq27xxx_battery_read_dm_block(di, &bd);
> + /* assume design energy & capacity are in same block */
> + bq27xxx_battery_update_dm_block(di, &bd,
> + BQ27XXX_DM_DESIGN_CAPACITY,
> + info->charge_full_design_uah / 1000);
> + bq27xxx_battery_update_dm_block(di, &bd,
> + BQ27XXX_DM_DESIGN_ENERGY,
> + info->energy_full_design_uwh / 1000);
> + }
> +
> + if (info->voltage_min_design_uv != -EINVAL) {
> + bool same = bd.class == bt.class && bd.block == bt.block;
> + if (!same)
> + bq27xxx_battery_read_dm_block(di, &bt);
> + bq27xxx_battery_update_dm_block(di, same ? &bd : &bt,
> + BQ27XXX_DM_TERMINATE_VOLTAGE,
> + info->voltage_min_design_uv / 1000);
> + }
> +
> + bq27xxx_battery_write_dm_block(di, &bd);
> + bq27xxx_battery_write_dm_block(di, &bt);
> +}
> +
> +void bq27xxx_battery_settings(struct bq27xxx_device_info *di)
> +{
> + struct power_supply_battery_info info = {};
> + unsigned int min, max;
> +
> + /* functions don't exist for writing data so abort */
> + if (!di->bus.write || !di->bus.write_bulk)
> + return;
> +
> + /* no settings to be set for this chipset so abort */
> + if (!di->dm_regs)
> + return;
> +
> + if (bq27xxx_battery_set_seal_state(di, false) < 0)
> + return;
> +
> + if (power_supply_get_battery_info(di->bat, &info) < 0)
> + goto out;
> +
> + if (info.energy_full_design_uwh != info.charge_full_design_uah) {
> + if (info.energy_full_design_uwh == -EINVAL)
> + dev_warn(di->dev,
> + "missing battery:energy-full-design-microwatt-hours\n");
> + else if (info.charge_full_design_uah == -EINVAL)
> + dev_warn(di->dev,
> + "missing battery:charge-full-design-microamp-hours\n");
> + }
> +
> + /* assume min == 0 */
> + max = di->dm_regs[BQ27XXX_DM_DESIGN_ENERGY].max;
> + if (info.energy_full_design_uwh > max * 1000) {
> + dev_err(di->dev,
> + "invalid battery:energy-full-design-microwatt-hours %d\n",
> + info.energy_full_design_uwh);
> + info.energy_full_design_uwh = -EINVAL;
> + }
> +
> + /* assume min == 0 */
> + max = di->dm_regs[BQ27XXX_DM_DESIGN_CAPACITY].max;
> + if (info.charge_full_design_uah > max * 1000) {
> + dev_err(di->dev,
> + "invalid battery:charge-full-design-microamp-hours %d\n",
> + info.charge_full_design_uah);
> + info.charge_full_design_uah = -EINVAL;
> + }
> +
> + min = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].min;
> + max = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].max;
> + if ((info.voltage_min_design_uv < min * 1000
> + || info.voltage_min_design_uv > max * 1000)
> + && info.voltage_min_design_uv != -EINVAL) {
> + dev_err(di->dev,
> + "invalid battery:voltage-min-design-microvolt %d\n",
> + info.voltage_min_design_uv);
> + info.voltage_min_design_uv = -EINVAL;
> + }
> +
> + if ((info.energy_full_design_uwh == -EINVAL
> + || info.charge_full_design_uah == -EINVAL)
> + && info.voltage_min_design_uv == -EINVAL)
> + goto out;
> +
> + bq27xxx_battery_set_config(di, &info);
> +
> +out:
> + bq27xxx_battery_set_seal_state(di, true);
Don't use goto unless you have to, this is not such a case.
> +}
> +
> /*
> * Return the battery State-of-Charge
> * Or < 0 if something fails.
> @@ -985,6 +1423,13 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
> case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
> ret = bq27xxx_simple_value(di->charge_design_full, val);
> break;
> + /*
> + * TODO: Implement these to make registers set from
> + * power_supply_battery_info visible in sysfs.
> + */
> + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
> + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
> + return -EINVAL;
> case POWER_SUPPLY_PROP_CYCLE_COUNT:
> ret = bq27xxx_simple_value(di->cache.cycle_count, val);
> break;
> @@ -1015,28 +1460,36 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
> schedule_delayed_work(&di->work, 0);
> }
>
> +#define BQ27XXX_INIT(c,d,k) \
> + di->chip = (c); \
> + di->dm_regs = (d); \
> + di->unseal_key = (k)
> +
> int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
> {
> struct power_supply_desc *psy_desc;
> - struct power_supply_config psy_cfg = { .drv_data = di, };
> + struct power_supply_config psy_cfg = {
> + .of_node = di->dev->of_node,
> + .drv_data = di,
> + };
>
> switch(di->chip) {
> case BQ27000:
> - case BQ27010:
> - case BQ27500:
> - case BQ27510:
> - case BQ27530:
> - case BQ27541:
> - case BQ27545:
> - case BQ27421: break;
> + case BQ27010: break;
> + case BQ27500: BQ27XXX_INIT(BQ27500, bq27500_dm_regs, 0x04143672); break;
> + case BQ27510: break;
> + case BQ27530: break;
> + case BQ27541: break;
> + case BQ27545: BQ27XXX_INIT(BQ27545, bq27545_dm_regs, 0x04143672); break;
> + case BQ27421: BQ27XXX_INIT(BQ27421, bq27421_dm_regs, 0x80008000); break;
> case BQ27520: di->chip = BQ27510; break;
> case BQ27531: di->chip = BQ27530; break;
> case BQ27542: di->chip = BQ27541; break;
> case BQ27546: di->chip = BQ27541; break;
> case BQ27742: di->chip = BQ27541; break;
> - case BQ27425: di->chip = BQ27421; break;
> - case BQ27441: di->chip = BQ27421; break;
> - case BQ27621: di->chip = BQ27421; break;
> + case BQ27425: BQ27XXX_INIT(BQ27421, bq27425_dm_regs, 0x04143672); break;
> + case BQ27441: BQ27XXX_INIT(BQ27421, bq27421_dm_regs, 0x80008000); break;
> + case BQ27621: BQ27XXX_INIT(BQ27421, bq27621_dm_regs, 0x80008000); break;
> }
>
> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
> @@ -1062,6 +1515,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>
> dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
>
> + bq27xxx_battery_settings(di);
> bq27xxx_battery_update(di);
>
> mutex_lock(&bq27xxx_list_lock);
> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
> index 90db1cf..dbf1ab9 100644
> --- a/include/linux/power/bq27xxx_battery.h
> +++ b/include/linux/power/bq27xxx_battery.h
> @@ -67,6 +67,8 @@ struct bq27xxx_device_info {
> int id;
> enum bq27xxx_chip chip;
> const char *name;
> + struct bq27xxx_dm_reg *dm_regs;
> + u32 unseal_key;
> struct bq27xxx_access_methods bus;
> struct bq27xxx_reg_cache cache;
> int charge_design_full;
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
2017-03-16 14:44 ` Andrew F. Davis
@ 2017-03-16 20:12 ` Liam Breck
2017-03-16 20:50 ` Andrew F. Davis
0 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-16 20:12 UTC (permalink / raw)
To: Andrew F. Davis; +Cc: Sebastian Reichel, linux-pm, Matt Ranostay, Liam Breck
On Thu, Mar 16, 2017 at 7:44 AM, Andrew F. Davis <afd@ti.com> wrote:
> On 03/15/2017 02:26 PM, Liam Breck wrote:
>> From: Liam Breck <kernel@networkimprov.net>
>>
>> Pass actual chip ID into _setup(), which translates it to a group ID,
>> to allow support for all chips by the power_supply_battery_info code.
>> There are no functional changes to the driver.
>>
>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>> ---
>
> What is this patch based on, it doesn't apply to v4.11-rc1 for me.
Sorry, I don't have all of Chris' patches here. It wasn't a factor
until we attacked the register arrays. Could you send me his patchset
with:
git format-patch --stdout HEAD~x..HEAD~y > bq27xxx-lapa.mbox
>> drivers/power/supply/bq27xxx_battery.c | 19 +++++++++++++++++++
>> drivers/power/supply/bq27xxx_battery_i2c.c | 16 ++++++++--------
>> include/linux/power/bq27xxx_battery.h | 25 ++++++++++++++++++-------
>> 3 files changed, 45 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
>> index 7272d1e..d613d3d 100644
>> --- a/drivers/power/supply/bq27xxx_battery.c
>> +++ b/drivers/power/supply/bq27xxx_battery.c
>> @@ -1020,6 +1020,25 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>> struct power_supply_desc *psy_desc;
>> struct power_supply_config psy_cfg = { .drv_data = di, };
>>
>> + switch(di->chip) {
>> + case BQ27000:
>> + case BQ27010:
>> + case BQ27500:
>> + case BQ27510:
>> + case BQ27530:
>> + case BQ27541:
>> + case BQ27545:
>> + case BQ27421: break;
>
> Why even have these cases then?
You'll get a compiler warning if any are missing. Helps when adding new chips.
>> + case BQ27520: di->chip = BQ27510; break;
>> + case BQ27531: di->chip = BQ27530; break;
>> + case BQ27542: di->chip = BQ27541; break;
>> + case BQ27546: di->chip = BQ27541; break;
>> + case BQ27742: di->chip = BQ27541; break;
>> + case BQ27425: di->chip = BQ27421; break;
>> + case BQ27441: di->chip = BQ27421; break;
>> + case BQ27621: di->chip = BQ27421; break;
>
> Nope, don't like this at all, make a different variable, ->registers or
> something to map to the register table. Plus I think changing the
> variable you are switching on can cause undefined behavior.
We had a different variable, .dmid, but you rejected a second ID
field. I think this is better, as we eliminated the static arrays
.dmid indexed. I didn't rename .chip to .category as that would cause
trivial changes all over the file. I could do that in a final patch
tho.
You can modify a variable after switching on it, I promise.
>> + }
>> +
>> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
>> mutex_init(&di->lock);
>> di->regs = bq27xxx_regs[di->chip];
>> diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
>> index 5c5c3a6..13def59 100644
>> --- a/drivers/power/supply/bq27xxx_battery_i2c.c
>> +++ b/drivers/power/supply/bq27xxx_battery_i2c.c
>> @@ -150,18 +150,18 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
>> { "bq27210", BQ27010 },
>> { "bq27500", BQ27500 },
>> { "bq27510", BQ27510 },
>> - { "bq27520", BQ27510 },
>> + { "bq27520", BQ27520 },
>> { "bq27530", BQ27530 },
>> - { "bq27531", BQ27530 },
>> + { "bq27531", BQ27531 },
>> { "bq27541", BQ27541 },
>> - { "bq27542", BQ27541 },
>> - { "bq27546", BQ27541 },
>> - { "bq27742", BQ27541 },
>> + { "bq27542", BQ27542 },
>> + { "bq27546", BQ27546 },
>> + { "bq27742", BQ27742 },
>> { "bq27545", BQ27545 },
>> { "bq27421", BQ27421 },
>> - { "bq27425", BQ27421 },
>> - { "bq27441", BQ27421 },
>> - { "bq27621", BQ27421 },
>> + { "bq27425", BQ27425 },
>> + { "bq27441", BQ27441 },
>> + { "bq27621", BQ27621 },
>> {},
>> };
>> MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>> index 92df553..90db1cf 100644
>> --- a/include/linux/power/bq27xxx_battery.h
>> +++ b/include/linux/power/bq27xxx_battery.h
>> @@ -2,14 +2,25 @@
>> #define __LINUX_BQ27X00_BATTERY_H__
>>
>> enum bq27xxx_chip {
>> + /* categories; index for bq27xxx_regs[] */
>> BQ27000 = 1, /* bq27000, bq27200 */
>> - BQ27010, /* bq27010, bq27210 */
>> - BQ27500, /* bq27500 */
>> - BQ27510, /* bq27510, bq27520 */
>> - BQ27530, /* bq27530, bq27531 */
>> - BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
>> - BQ27545, /* bq27545 */
>> - BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
>> + BQ27010 = 2, /* bq27010, bq27210 */
>> + BQ27500 = 3, /* bq27500 */
>> + BQ27510 = 4, /* bq27510, bq27520 */
>> + BQ27530 = 5, /* bq27530, bq27531 */
>> + BQ27541 = 6, /* bq27541, bq27542, bq27546, bq27742 */
>> + BQ27545 = 7, /* bq27545 */
>> + BQ27421 = 8, /* bq27421, bq27425, bq27441, bq27621 */
>> +
>> + /* members of categories; translate these to category in _setup() */
>> + BQ27520 = 101,
>> + BQ27531 = 102,
>> + BQ27542 = 103,
>> + BQ27546 = 104,
>> + BQ27742 = 105,
>> + BQ27425 = 106,
>> + BQ27441 = 107,
>> + BQ27621 = 108,
>
> Get rid of this, just add new chip enum names if you need support for
> new chips.
How does a non-DT config obtain chip ID? We want explicit enum values
if they appear in external platform-data objects. I'll mention that in
the next patch description.
The category (original) IDs index bq27xxx_regs[], and you'll probably
extend that in time. So I placed the member (new) IDs well above the
categories to allow permanent explicit values.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
2017-03-16 20:12 ` Liam Breck
@ 2017-03-16 20:50 ` Andrew F. Davis
2017-03-16 21:26 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Andrew F. Davis @ 2017-03-16 20:50 UTC (permalink / raw)
To: Liam Breck; +Cc: Sebastian Reichel, linux-pm, Matt Ranostay, Liam Breck
On 03/16/2017 03:12 PM, Liam Breck wrote:
> On Thu, Mar 16, 2017 at 7:44 AM, Andrew F. Davis <afd@ti.com> wrote:
>> On 03/15/2017 02:26 PM, Liam Breck wrote:
>>> From: Liam Breck <kernel@networkimprov.net>
>>>
>>> Pass actual chip ID into _setup(), which translates it to a group ID,
>>> to allow support for all chips by the power_supply_battery_info code.
>>> There are no functional changes to the driver.
>>>
>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>> ---
>>
>> What is this patch based on, it doesn't apply to v4.11-rc1 for me.
>
> Sorry, I don't have all of Chris' patches here. It wasn't a factor
> until we attacked the register arrays. Could you send me his patchset
> with:
> git format-patch --stdout HEAD~x..HEAD~y > bq27xxx-lapa.mbox
>
Who are you asking?
>>> drivers/power/supply/bq27xxx_battery.c | 19 +++++++++++++++++++
>>> drivers/power/supply/bq27xxx_battery_i2c.c | 16 ++++++++--------
>>> include/linux/power/bq27xxx_battery.h | 25 ++++++++++++++++++-------
>>> 3 files changed, 45 insertions(+), 15 deletions(-)
>>>
>>> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
>>> index 7272d1e..d613d3d 100644
>>> --- a/drivers/power/supply/bq27xxx_battery.c
>>> +++ b/drivers/power/supply/bq27xxx_battery.c
>>> @@ -1020,6 +1020,25 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>> struct power_supply_desc *psy_desc;
>>> struct power_supply_config psy_cfg = { .drv_data = di, };
>>>
>>> + switch(di->chip) {
>>> + case BQ27000:
>>> + case BQ27010:
>>> + case BQ27500:
>>> + case BQ27510:
>>> + case BQ27530:
>>> + case BQ27541:
>>> + case BQ27545:
>>> + case BQ27421: break;
>>
>> Why even have these cases then?
>
> You'll get a compiler warning if any are missing. Helps when adding new chips.
>
>>> + case BQ27520: di->chip = BQ27510; break;
>>> + case BQ27531: di->chip = BQ27530; break;
>>> + case BQ27542: di->chip = BQ27541; break;
>>> + case BQ27546: di->chip = BQ27541; break;
>>> + case BQ27742: di->chip = BQ27541; break;
>>> + case BQ27425: di->chip = BQ27421; break;
>>> + case BQ27441: di->chip = BQ27421; break;
>>> + case BQ27621: di->chip = BQ27421; break;
>>
>> Nope, don't like this at all, make a different variable, ->registers or
>> something to map to the register table. Plus I think changing the
>> variable you are switching on can cause undefined behavior.
>
> We had a different variable, .dmid, but you rejected a second ID
> field. I think this is better, as we eliminated the static arrays
> .dmid indexed. I didn't rename .chip to .category as that would cause
> trivial changes all over the file. I could do that in a final patch
> tho.
>
> You can modify a variable after switching on it, I promise.
>
>>> + }
>>> +
>>> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
>>> mutex_init(&di->lock);
>>> di->regs = bq27xxx_regs[di->chip];
>>> diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
>>> index 5c5c3a6..13def59 100644
>>> --- a/drivers/power/supply/bq27xxx_battery_i2c.c
>>> +++ b/drivers/power/supply/bq27xxx_battery_i2c.c
>>> @@ -150,18 +150,18 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
>>> { "bq27210", BQ27010 },
>>> { "bq27500", BQ27500 },
>>> { "bq27510", BQ27510 },
>>> - { "bq27520", BQ27510 },
>>> + { "bq27520", BQ27520 },
>>> { "bq27530", BQ27530 },
>>> - { "bq27531", BQ27530 },
>>> + { "bq27531", BQ27531 },
>>> { "bq27541", BQ27541 },
>>> - { "bq27542", BQ27541 },
>>> - { "bq27546", BQ27541 },
>>> - { "bq27742", BQ27541 },
>>> + { "bq27542", BQ27542 },
>>> + { "bq27546", BQ27546 },
>>> + { "bq27742", BQ27742 },
>>> { "bq27545", BQ27545 },
>>> { "bq27421", BQ27421 },
>>> - { "bq27425", BQ27421 },
>>> - { "bq27441", BQ27421 },
>>> - { "bq27621", BQ27421 },
>>> + { "bq27425", BQ27425 },
>>> + { "bq27441", BQ27441 },
>>> + { "bq27621", BQ27621 },
>>> {},
>>> };
>>> MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
>>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>>> index 92df553..90db1cf 100644
>>> --- a/include/linux/power/bq27xxx_battery.h
>>> +++ b/include/linux/power/bq27xxx_battery.h
>>> @@ -2,14 +2,25 @@
>>> #define __LINUX_BQ27X00_BATTERY_H__
>>>
>>> enum bq27xxx_chip {
>>> + /* categories; index for bq27xxx_regs[] */
>>> BQ27000 = 1, /* bq27000, bq27200 */
>>> - BQ27010, /* bq27010, bq27210 */
>>> - BQ27500, /* bq27500 */
>>> - BQ27510, /* bq27510, bq27520 */
>>> - BQ27530, /* bq27530, bq27531 */
>>> - BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
>>> - BQ27545, /* bq27545 */
>>> - BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
>>> + BQ27010 = 2, /* bq27010, bq27210 */
>>> + BQ27500 = 3, /* bq27500 */
>>> + BQ27510 = 4, /* bq27510, bq27520 */
>>> + BQ27530 = 5, /* bq27530, bq27531 */
>>> + BQ27541 = 6, /* bq27541, bq27542, bq27546, bq27742 */
>>> + BQ27545 = 7, /* bq27545 */
>>> + BQ27421 = 8, /* bq27421, bq27425, bq27441, bq27621 */
>>> +
>>> + /* members of categories; translate these to category in _setup() */
>>> + BQ27520 = 101,
>>> + BQ27531 = 102,
>>> + BQ27542 = 103,
>>> + BQ27546 = 104,
>>> + BQ27742 = 105,
>>> + BQ27425 = 106,
>>> + BQ27441 = 107,
>>> + BQ27621 = 108,
>>
>> Get rid of this, just add new chip enum names if you need support for
>> new chips.
>
> How does a non-DT config obtain chip ID? We want explicit enum values
> if they appear in external platform-data objects. I'll mention that in
> the next patch description.
>
platform-data is going away, I'm not sure what you are saying here.
> The category (original) IDs index bq27xxx_regs[], and you'll probably
> extend that in time. So I placed the member (new) IDs well above the
> categories to allow permanent explicit values.
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support
2017-03-16 15:00 ` Andrew F. Davis
@ 2017-03-16 21:12 ` Liam Breck
2017-03-16 21:39 ` Andrew F. Davis
0 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-16 21:12 UTC (permalink / raw)
To: Andrew F. Davis; +Cc: Sebastian Reichel, linux-pm, Liam Breck
On Thu, Mar 16, 2017 at 8:00 AM, Andrew F. Davis <afd@ti.com> wrote:
> On 03/15/2017 02:26 PM, Liam Breck wrote:
>> From: Liam Breck <kernel@networkimprov.net>
>>
>> Previously there was no way to configure chip registers in the event that the
>> defaults didn't match the battery in question.
>>
>> BQ27xxx driver now calls power_supply_get_battery_info, checks the inputs,
>> and writes battery data to chip RAM or non-volatile memory.
>>
>> Supports chips BQ27500, 545, 421, 425, 441, 621. Others may be added.
>>
>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>> ---
>> drivers/power/supply/bq27xxx_battery.c | 478 ++++++++++++++++++++++++++++++++-
>> include/linux/power/bq27xxx_battery.h | 2 +
>> 2 files changed, 468 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
>> index d613d3d..fb062db 100644
>> --- a/drivers/power/supply/bq27xxx_battery.c
>> +++ b/drivers/power/supply/bq27xxx_battery.c
>> @@ -51,7 +51,7 @@
>>
>> #include <linux/power/bq27xxx_battery.h>
>>
>> -#define DRIVER_VERSION "1.2.0"
>> +#define DRIVER_VERSION "1.3.0"
>>
>> #define BQ27XXX_MANUFACTURER "Texas Instruments"
>>
>> @@ -59,6 +59,7 @@
>> #define BQ27XXX_FLAG_DSC BIT(0)
>> #define BQ27XXX_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
>> #define BQ27XXX_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
>> +#define BQ27XXX_FLAG_CFGUP BIT(4)
>> #define BQ27XXX_FLAG_FC BIT(9)
>> #define BQ27XXX_FLAG_OTD BIT(14)
>> #define BQ27XXX_FLAG_OTC BIT(15)
>> @@ -72,6 +73,11 @@
>> #define BQ27000_FLAG_FC BIT(5)
>> #define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
>>
>> +/* control register params */
>> +#define BQ27XXX_SEALED 0x20
>> +#define BQ27XXX_SET_CFGUPDATE 0x13
>> +#define BQ27XXX_SOFT_RESET 0x42
>> +
>> #define BQ27XXX_RS (20) /* Resistor sense mOhm */
>> #define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */
>> #define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */
>> @@ -102,6 +108,11 @@ enum bq27xxx_reg_index {
>> BQ27XXX_REG_SOC, /* State-of-Charge */
>> BQ27XXX_REG_DCAP, /* Design Capacity */
>> BQ27XXX_REG_AP, /* Average Power */
>> + BQ27XXX_DM_CTRL, /* BlockDataControl() */
>> + BQ27XXX_DM_CLASS, /* DataClass() */
>> + BQ27XXX_DM_BLOCK, /* DataBlock() */
>> + BQ27XXX_DM_DATA, /* BlockData() */
>> + BQ27XXX_DM_CKSUM, /* BlockDataChecksum() */
>> BQ27XXX_REG_MAX, /* sentinel */
>> };
>>
>> @@ -125,6 +136,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>> [BQ27XXX_REG_SOC] = 0x0b,
>> [BQ27XXX_REG_DCAP] = 0x76,
>> [BQ27XXX_REG_AP] = 0x24,
>> + [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_DATA] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR,
>> },
>> [BQ27010] = {
>> [BQ27XXX_REG_CTRL] = 0x00,
>> @@ -144,6 +160,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>> [BQ27XXX_REG_SOC] = 0x0b,
>> [BQ27XXX_REG_DCAP] = 0x76,
>> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_DATA] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR,
>> },
>> [BQ27500] = {
>> [BQ27XXX_REG_CTRL] = 0x00,
>> @@ -163,6 +184,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>> [BQ27XXX_REG_SOC] = 0x2c,
>> [BQ27XXX_REG_DCAP] = 0x3c,
>> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_CTRL] = 0x61,
>> + [BQ27XXX_DM_CLASS] = 0x3e,
>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>> + [BQ27XXX_DM_DATA] = 0x40,
>> + [BQ27XXX_DM_CKSUM] = 0x60,
>> },
>> [BQ27510] = {
>> [BQ27XXX_REG_CTRL] = 0x00,
>> @@ -182,6 +208,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>> [BQ27XXX_REG_SOC] = 0x20,
>> [BQ27XXX_REG_DCAP] = 0x2e,
>> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
>> + [BQ27XXX_DM_CTRL] = 0x61,
>> + [BQ27XXX_DM_CLASS] = 0x3e,
>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>> + [BQ27XXX_DM_DATA] = 0x40,
>> + [BQ27XXX_DM_CKSUM] = 0x60,
>> },
>> [BQ27530] = {
>> [BQ27XXX_REG_CTRL] = 0x00,
>> @@ -201,6 +232,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>> [BQ27XXX_REG_SOC] = 0x2c,
>> [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
>> [BQ27XXX_REG_AP] = 0x24,
>> + [BQ27XXX_DM_CTRL] = 0x61,
>> + [BQ27XXX_DM_CLASS] = 0x3e,
>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>> + [BQ27XXX_DM_DATA] = 0x40,
>> + [BQ27XXX_DM_CKSUM] = 0x60,
>> },
>> [BQ27541] = {
>> [BQ27XXX_REG_CTRL] = 0x00,
>> @@ -220,6 +256,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>> [BQ27XXX_REG_SOC] = 0x2c,
>> [BQ27XXX_REG_DCAP] = 0x3c,
>> [BQ27XXX_REG_AP] = 0x24,
>> + [BQ27XXX_DM_CTRL] = 0x61,
>> + [BQ27XXX_DM_CLASS] = 0x3e,
>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>> + [BQ27XXX_DM_DATA] = 0x40,
>> + [BQ27XXX_DM_CKSUM] = 0x60,
>> },
>> [BQ27545] = {
>> [BQ27XXX_REG_CTRL] = 0x00,
>> @@ -239,6 +280,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>> [BQ27XXX_REG_SOC] = 0x2c,
>> [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
>> [BQ27XXX_REG_AP] = 0x24,
>> + [BQ27XXX_DM_CTRL] = 0x61,
>> + [BQ27XXX_DM_CLASS] = 0x3e,
>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>> + [BQ27XXX_DM_DATA] = 0x40,
>> + [BQ27XXX_DM_CKSUM] = 0x60,
>> },
>> [BQ27421] = {
>> [BQ27XXX_REG_CTRL] = 0x00,
>> @@ -258,6 +304,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>> [BQ27XXX_REG_SOC] = 0x1c,
>> [BQ27XXX_REG_DCAP] = 0x3c,
>> [BQ27XXX_REG_AP] = 0x18,
>> + [BQ27XXX_DM_CTRL] = 0x61,
>> + [BQ27XXX_DM_CLASS] = 0x3e,
>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>> + [BQ27XXX_DM_DATA] = 0x40,
>> + [BQ27XXX_DM_CKSUM] = 0x60,
>> },
>> };
>>
>> @@ -432,6 +483,82 @@ static struct {
>> static DEFINE_MUTEX(bq27xxx_list_lock);
>> static LIST_HEAD(bq27xxx_battery_devices);
>>
>> +#define BQ27XXX_DM_SZ 32
>> +
>> +#define BQ27XXX_MSLEEP(i) usleep_range((i)*1000, (i)*1000+500)
>> +
>> +struct bq27xxx_dm_reg {
>> + u8 subclass_id;
>> + u8 offset;
>> + u8 bytes;
>> + u16 min, max;
>> +};
>> +
>> +struct bq27xxx_dm_buf {
>> + u8 class;
>> + u8 block;
>> + u8 a[BQ27XXX_DM_SZ];
>> + bool full, updt;
>> +};
>> +
>> +#define BQ27XXX_DM_BUF(di, i) { \
>> + .class = (di)->dm_regs[i].subclass_id, \
>> + .block = (di)->dm_regs[i].offset / BQ27XXX_DM_SZ, \
>> +}
>> +
>> +static inline u16* bq27xxx_dm_reg_ptr(struct bq27xxx_dm_buf *buf,
>> + struct bq27xxx_dm_reg *reg)
>> +{
>> + if (buf->class == reg->subclass_id
>> + && buf->block == reg->offset / BQ27XXX_DM_SZ)
>> + return (u16*) (buf->a + reg->offset % BQ27XXX_DM_SZ);
>> +
>> + return NULL;
>> +}
>> +
>> +enum bq27xxx_dm_reg_id {
>> + BQ27XXX_DM_DESIGN_CAPACITY = 0,
>> + BQ27XXX_DM_DESIGN_ENERGY,
>> + BQ27XXX_DM_TERMINATE_VOLTAGE,
>> +};
>> +
>> +static const char* bq27xxx_dm_reg_name[] = {
>> + [BQ27XXX_DM_DESIGN_CAPACITY] = "design-capacity",
>> + [BQ27XXX_DM_DESIGN_ENERGY] = "design-energy",
>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = "terminate-voltage",
>> +};
>> +
>> +static struct bq27xxx_dm_reg bq27500_dm_regs[] = {
>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 10, 2, 0, 65535 },
>> + [BQ27XXX_DM_DESIGN_ENERGY] = { }, /* missing on chip */
>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 48, 2, 1000, 32767 },
>> +};
>> +
>> +static struct bq27xxx_dm_reg bq27545_dm_regs[] = {
>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 23, 2, 0, 32767 },
>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 48, 25, 2, 0, 32767 },
>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 67, 2, 2800, 3700 },
>> +};
>> +
>> +static struct bq27xxx_dm_reg bq27421_dm_regs[] = {
>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 8000 },
>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 },
>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 16, 2, 2500, 3700 },
>> +};
>> +
>> +static struct bq27xxx_dm_reg bq27425_dm_regs[] = {
>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 12, 2, 0, 32767 },
>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 14, 2, 0, 32767 },
>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 18, 2, 2800, 3700 },
>> +};
>> +
>> +static struct bq27xxx_dm_reg bq27621_dm_regs[] = {
>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 3, 2, 0, 8000 },
>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 5, 2, 0, 32767 },
>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 9, 2, 2500, 3700 },
>> +};
>> +
>> +
>> static int poll_interval_param_set(const char *val, const struct kernel_param *kp)
>> {
>> struct bq27xxx_device_info *di;
>> @@ -476,6 +603,317 @@ static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index,
>> return di->bus.read(di, di->regs[reg_index], single);
>> }
>>
>> +static int bq27xxx_battery_set_seal_state(struct bq27xxx_device_info *di,
>> + bool state)
>> +{
>> + int ret;
>> +
>> + if (state) {
>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], BQ27XXX_SEALED, false);
>
>
> Look at how reads are done, we have a function bq27xxx_read() that
> checks the register and handles the access methods. Do something like
> that for write, then replace all these with that, "bus" should only be
> accessed in that function.
OK. And for bus.{read,write}_bulk() too? They only occur once.
>> + if (ret < 0)
>> + goto out;
>> + } else {
>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], (u16)(di->unseal_key >> 16), false);
>> + if (ret < 0)
>> + goto out;
>> +
>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], (u16)di->unseal_key, false);
>> + if (ret < 0)
>> + goto out;
>> + }
>
> +space
>
> Has this been run through checkpatch?
>
>> + return 0;
>> +
>> +out:
>> + dev_err(di->dev, "bus error on %s: %d\n", state ? "seal" : "unseal", ret);
>> + return ret;
>> +}
>> +
>> +static u8 bq27xxx_battery_checksum_dm_block(struct bq27xxx_dm_buf *buf)
>> +{
>> + u16 sum = 0;
>> + int i;
>> +
>> + for (i = 0; i < BQ27XXX_DM_SZ; i++)
>> + sum += buf->a[i];
>> + sum &= 0xff;
>> +
>> + return 0xff - sum;
>> +}
>> +
>> +static int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di,
>> + struct bq27xxx_dm_buf *buf)
>> +{
>> + int ret;
>> +
>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CLASS], buf->class, true);
>> + if (ret < 0)
>> + goto out;
>> +
>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_BLOCK], buf->block, true);
>> + if (ret < 0)
>> + goto out;
>> +
>> + BQ27XXX_MSLEEP(1);
>> +
>> + ret = di->bus.read_bulk(di, di->regs[BQ27XXX_DM_DATA], buf->a, BQ27XXX_DM_SZ);
>> + if (ret < 0)
>> + goto out;
>> +
>> + ret = di->bus.read(di, di->regs[BQ27XXX_DM_CKSUM], true);
>> + if (ret < 0)
>> + goto out;
>> +
>> + if ((u8)ret != bq27xxx_battery_checksum_dm_block(buf)) {
>> + ret = -EINVAL;
>> + goto out;
>> + }
>> +
>> + buf->full = true;
>> + buf->updt = false;
>> + return 0;
>> +
>> +out:
>> + dev_err(di->dev, "bus error reading chip memory: %d\n", ret);
>
> Instead of this catch-all, each spot should have an error message that
> explains what failed. If they all end up with this generic message we
> cannot possibly diagnose issues for people.
Knowing which bus op failed doesn't help. Any error means either the
bus hw failed or chip died. If we're debugging a new chip, we'll need
extra print statements anyway.
>> + return ret;
>> +}
>> +
>> +static void bq27xxx_battery_update_dm_block(struct bq27xxx_device_info *di,
>> + struct bq27xxx_dm_buf *buf,
>> + enum bq27xxx_dm_reg_id reg_id,
>> + unsigned int val)
>> +{
>> + struct bq27xxx_dm_reg *reg = &di->dm_regs[reg_id];
>> + const char* str = bq27xxx_dm_reg_name[reg_id];
>> + u16 *prev = bq27xxx_dm_reg_ptr(buf, reg);
>> +
>> + if (prev == NULL) {
>> + dev_warn(di->dev, "buffer does not match %s dm spec\n", str);
>> + return;
>> + }
>> +
>> + if (reg->bytes != 2) {
>> + dev_warn(di->dev, "%s dm spec has unsupported byte size\n", str);
>> + return;
>> + }
>> +
>> + if (!buf->full)
>> + return;
>> +
>> + if (be16_to_cpup(prev) == val) {
>> + dev_info(di->dev, "%s has %u\n", str, val);
>> + return;
>> + }
>> +
>> + dev_info(di->dev, "update %s to %u\n", str, val);
>> +
>> + *prev = cpu_to_be16(val);
>> + buf->updt = true;
>> +}
>> +
>> +static int bq27xxx_battery_set_cfgupdate(struct bq27xxx_device_info *di,
>> + bool state)
>
> Why only two states? why bool? you should probably be passing in the
> value, if you really want to do this as a state, then the states should
> have an enum for each state.
You can enter or exit cfgupdate mode. We do the same for
set_seal_state(). And bq27xxx_read() takes a bool arg to indicate one
or two bytes.
>> +{
>> + int ret, try=100;
>> +
>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL],
>> + state ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET,
>> + false);
>> + if (ret < 0)
>> + goto out;
>> +
>> + do {
>> + BQ27XXX_MSLEEP(25);
>> + ret = di->bus.read(di, di->regs[BQ27XXX_REG_FLAGS], false);
>> + if (ret < 0)
>> + goto out;
>> + } while (!(ret & BQ27XXX_FLAG_CFGUP) == state && --try);
>> +
>> + if (!try) {
>> + dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", state);
>> + return -EINVAL;
>> + }
>
> Put this check inside the loop.
We test try inside the loop. This test is only relevant after the loop.
>> +
>> + if (100-try > 3)
>
> Why 3? lets also count up to a set value, 100 is a magic number, if I
> change try to =200, I have to change it down here, that is going to be
> buggy.
OK. 3 because 75ms is a long time.
>> + dev_warn(di->dev, "cfgupdate %d, retries %d\n", state, 100-try);
>> +
>> + return 0;
>> +
>> +out:
>> + dev_err(di->dev, "bus error on %s: %d\n", state ? "set_cfgupdate" : "soft_reset", ret);
>> + return ret;
>> +}
>> +
>> +static int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di,
>> + struct bq27xxx_dm_buf *buf)
>> +{
>> + bool cfgup = di->chip == BQ27421; /* assume group supports cfgupdate */
>> + int ret;
>> +
>> + if (!buf->updt)
>> + return 0;
>> +
>> + if (cfgup) {
>> + ret = bq27xxx_battery_set_cfgupdate(di, true);
>> + if (ret < 0)
>> + return ret;
>> + }
>> +
>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CTRL], 0, true);
>> + if (ret < 0)
>> + goto out;
>> +
>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CLASS], buf->class, true);
>> + if (ret < 0)
>> + goto out;
>> +
>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_BLOCK], buf->block, true);
>> + if (ret < 0)
>> + goto out;
>> +
>> + BQ27XXX_MSLEEP(1);
>> +
>> + ret = di->bus.write_bulk(di, di->regs[BQ27XXX_DM_DATA], buf->a, BQ27XXX_DM_SZ);
>> + if (ret < 0)
>> + goto out;
>> +
>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CKSUM],
>> + bq27xxx_battery_checksum_dm_block(buf), true);
>> + if (ret < 0)
>> + goto out;
>> +
>> + /* THE FOLLOWING SEQUENCE IS TOXIC. DO NOT USE!
>> + * If the 'time' delay is insufficient, NVM corruption results on
>> + * the '425 chip (and perhaps others), which could damage the chip.
>> + * It was suggested in this TI tool:
>> + * http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328
>> + *
>> + * 1. MSLEEP(time) after above write(BQ27XXX_DM_CKSUM, ...)
>> + * 2. write(BQ27XXX_DM_BLOCK, buf->block)
>> + * 3. sum = read(BQ27XXX_DM_CKSUM)
>> + * 4. if (sum != bq27xxx_battery_checksum_dm_block(buf))
>> + * report error
>> + */
>> +
>> + if (cfgup) {
>> + BQ27XXX_MSLEEP(1);
>> + ret = bq27xxx_battery_set_cfgupdate(di, false);
>> + if (ret < 0)
>> + return ret;
>> + } else {
>> + /* flash DM updates in <100ms, but reset time isn't documented */
>> + BQ27XXX_MSLEEP(400);
>> + }
>> +
>> + buf->updt = false;
>> + return 0;
>> +
>> +out:
>> + if (cfgup)
>> + bq27xxx_battery_set_cfgupdate(di, false);
>> +
>> + dev_err(di->dev, "bus error writing chip memory: %d\n", ret);
>> + return ret;
>> +}
>> +
>> +static void bq27xxx_battery_set_config(struct bq27xxx_device_info *di,
>> + struct power_supply_battery_info *info)
>> +{
>> + struct bq27xxx_dm_buf bd = BQ27XXX_DM_BUF(di, BQ27XXX_DM_DESIGN_CAPACITY);
>> + struct bq27xxx_dm_buf bt = BQ27XXX_DM_BUF(di, BQ27XXX_DM_TERMINATE_VOLTAGE);
>> +
>> + if (info->charge_full_design_uah != -EINVAL
>> + && info->energy_full_design_uwh != -EINVAL) {
>> + bq27xxx_battery_read_dm_block(di, &bd);
>> + /* assume design energy & capacity are in same block */
>> + bq27xxx_battery_update_dm_block(di, &bd,
>> + BQ27XXX_DM_DESIGN_CAPACITY,
>> + info->charge_full_design_uah / 1000);
>> + bq27xxx_battery_update_dm_block(di, &bd,
>> + BQ27XXX_DM_DESIGN_ENERGY,
>> + info->energy_full_design_uwh / 1000);
>> + }
>> +
>> + if (info->voltage_min_design_uv != -EINVAL) {
>> + bool same = bd.class == bt.class && bd.block == bt.block;
>> + if (!same)
>> + bq27xxx_battery_read_dm_block(di, &bt);
>> + bq27xxx_battery_update_dm_block(di, same ? &bd : &bt,
>> + BQ27XXX_DM_TERMINATE_VOLTAGE,
>> + info->voltage_min_design_uv / 1000);
>> + }
>> +
>> + bq27xxx_battery_write_dm_block(di, &bd);
>> + bq27xxx_battery_write_dm_block(di, &bt);
>> +}
>> +
>> +void bq27xxx_battery_settings(struct bq27xxx_device_info *di)
>> +{
>> + struct power_supply_battery_info info = {};
>> + unsigned int min, max;
>> +
>> + /* functions don't exist for writing data so abort */
>> + if (!di->bus.write || !di->bus.write_bulk)
>> + return;
>> +
>> + /* no settings to be set for this chipset so abort */
>> + if (!di->dm_regs)
>> + return;
>> +
>> + if (bq27xxx_battery_set_seal_state(di, false) < 0)
>> + return;
>> +
>> + if (power_supply_get_battery_info(di->bat, &info) < 0)
>> + goto out;
>> +
>> + if (info.energy_full_design_uwh != info.charge_full_design_uah) {
>> + if (info.energy_full_design_uwh == -EINVAL)
>> + dev_warn(di->dev,
>> + "missing battery:energy-full-design-microwatt-hours\n");
>> + else if (info.charge_full_design_uah == -EINVAL)
>> + dev_warn(di->dev,
>> + "missing battery:charge-full-design-microamp-hours\n");
>> + }
>> +
>> + /* assume min == 0 */
>> + max = di->dm_regs[BQ27XXX_DM_DESIGN_ENERGY].max;
>> + if (info.energy_full_design_uwh > max * 1000) {
>> + dev_err(di->dev,
>> + "invalid battery:energy-full-design-microwatt-hours %d\n",
>> + info.energy_full_design_uwh);
>> + info.energy_full_design_uwh = -EINVAL;
>> + }
>> +
>> + /* assume min == 0 */
>> + max = di->dm_regs[BQ27XXX_DM_DESIGN_CAPACITY].max;
>> + if (info.charge_full_design_uah > max * 1000) {
>> + dev_err(di->dev,
>> + "invalid battery:charge-full-design-microamp-hours %d\n",
>> + info.charge_full_design_uah);
>> + info.charge_full_design_uah = -EINVAL;
>> + }
>> +
>> + min = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].min;
>> + max = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].max;
>> + if ((info.voltage_min_design_uv < min * 1000
>> + || info.voltage_min_design_uv > max * 1000)
>> + && info.voltage_min_design_uv != -EINVAL) {
>> + dev_err(di->dev,
>> + "invalid battery:voltage-min-design-microvolt %d\n",
>> + info.voltage_min_design_uv);
>> + info.voltage_min_design_uv = -EINVAL;
>> + }
>> +
>> + if ((info.energy_full_design_uwh == -EINVAL
>> + || info.charge_full_design_uah == -EINVAL)
>> + && info.voltage_min_design_uv == -EINVAL)
>> + goto out;
>> +
>> + bq27xxx_battery_set_config(di, &info);
>> +
>> +out:
>> + bq27xxx_battery_set_seal_state(di, true);
>
> Don't use goto unless you have to, this is not such a case.
OK.
>> +}
>> +
>> /*
>> * Return the battery State-of-Charge
>> * Or < 0 if something fails.
>> @@ -985,6 +1423,13 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
>> case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
>> ret = bq27xxx_simple_value(di->charge_design_full, val);
>> break;
>> + /*
>> + * TODO: Implement these to make registers set from
>> + * power_supply_battery_info visible in sysfs.
>> + */
>> + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
>> + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
>> + return -EINVAL;
>> case POWER_SUPPLY_PROP_CYCLE_COUNT:
>> ret = bq27xxx_simple_value(di->cache.cycle_count, val);
>> break;
>> @@ -1015,28 +1460,36 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
>> schedule_delayed_work(&di->work, 0);
>> }
>>
>> +#define BQ27XXX_INIT(c,d,k) \
>> + di->chip = (c); \
>> + di->dm_regs = (d); \
>> + di->unseal_key = (k)
>> +
>> int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>> {
>> struct power_supply_desc *psy_desc;
>> - struct power_supply_config psy_cfg = { .drv_data = di, };
>> + struct power_supply_config psy_cfg = {
>> + .of_node = di->dev->of_node,
>> + .drv_data = di,
>> + };
>>
>> switch(di->chip) {
>> case BQ27000:
>> - case BQ27010:
>> - case BQ27500:
>> - case BQ27510:
>> - case BQ27530:
>> - case BQ27541:
>> - case BQ27545:
>> - case BQ27421: break;
>> + case BQ27010: break;
>> + case BQ27500: BQ27XXX_INIT(BQ27500, bq27500_dm_regs, 0x04143672); break;
>> + case BQ27510: break;
>> + case BQ27530: break;
>> + case BQ27541: break;
>> + case BQ27545: BQ27XXX_INIT(BQ27545, bq27545_dm_regs, 0x04143672); break;
>> + case BQ27421: BQ27XXX_INIT(BQ27421, bq27421_dm_regs, 0x80008000); break;
>> case BQ27520: di->chip = BQ27510; break;
>> case BQ27531: di->chip = BQ27530; break;
>> case BQ27542: di->chip = BQ27541; break;
>> case BQ27546: di->chip = BQ27541; break;
>> case BQ27742: di->chip = BQ27541; break;
>> - case BQ27425: di->chip = BQ27421; break;
>> - case BQ27441: di->chip = BQ27421; break;
>> - case BQ27621: di->chip = BQ27421; break;
>> + case BQ27425: BQ27XXX_INIT(BQ27421, bq27425_dm_regs, 0x04143672); break;
>> + case BQ27441: BQ27XXX_INIT(BQ27421, bq27421_dm_regs, 0x80008000); break;
>> + case BQ27621: BQ27XXX_INIT(BQ27421, bq27621_dm_regs, 0x80008000); break;
>> }
>>
>> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
>> @@ -1062,6 +1515,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>
>> dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
>>
>> + bq27xxx_battery_settings(di);
>> bq27xxx_battery_update(di);
>>
>> mutex_lock(&bq27xxx_list_lock);
>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>> index 90db1cf..dbf1ab9 100644
>> --- a/include/linux/power/bq27xxx_battery.h
>> +++ b/include/linux/power/bq27xxx_battery.h
>> @@ -67,6 +67,8 @@ struct bq27xxx_device_info {
>> int id;
>> enum bq27xxx_chip chip;
>> const char *name;
>> + struct bq27xxx_dm_reg *dm_regs;
>> + u32 unseal_key;
>> struct bq27xxx_access_methods bus;
>> struct bq27xxx_reg_cache cache;
>> int charge_design_full;
>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
2017-03-16 20:50 ` Andrew F. Davis
@ 2017-03-16 21:26 ` Liam Breck
2017-03-16 21:30 ` Andrew F. Davis
0 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-16 21:26 UTC (permalink / raw)
To: Andrew F. Davis; +Cc: Sebastian Reichel, linux-pm, Matt Ranostay, Liam Breck
On Thu, Mar 16, 2017 at 1:50 PM, Andrew F. Davis <afd@ti.com> wrote:
> On 03/16/2017 03:12 PM, Liam Breck wrote:
>> On Thu, Mar 16, 2017 at 7:44 AM, Andrew F. Davis <afd@ti.com> wrote:
>>> On 03/15/2017 02:26 PM, Liam Breck wrote:
>>>> From: Liam Breck <kernel@networkimprov.net>
>>>>
>>>> Pass actual chip ID into _setup(), which translates it to a group ID,
>>>> to allow support for all chips by the power_supply_battery_info code.
>>>> There are no functional changes to the driver.
>>>>
>>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>>> ---
>>>
>>> What is this patch based on, it doesn't apply to v4.11-rc1 for me.
>>
>> Sorry, I don't have all of Chris' patches here. It wasn't a factor
>> until we attacked the register arrays. Could you send me his patchset
>> with:
>> git format-patch --stdout HEAD~x..HEAD~y > bq27xxx-lapa.mbox
>>
>
> Who are you asking?
You, if I may impose...
>>>> drivers/power/supply/bq27xxx_battery.c | 19 +++++++++++++++++++
>>>> drivers/power/supply/bq27xxx_battery_i2c.c | 16 ++++++++--------
>>>> include/linux/power/bq27xxx_battery.h | 25 ++++++++++++++++++-------
>>>> 3 files changed, 45 insertions(+), 15 deletions(-)
>>>>
>>>> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
>>>> index 7272d1e..d613d3d 100644
>>>> --- a/drivers/power/supply/bq27xxx_battery.c
>>>> +++ b/drivers/power/supply/bq27xxx_battery.c
>>>> @@ -1020,6 +1020,25 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>>> struct power_supply_desc *psy_desc;
>>>> struct power_supply_config psy_cfg = { .drv_data = di, };
>>>>
>>>> + switch(di->chip) {
>>>> + case BQ27000:
>>>> + case BQ27010:
>>>> + case BQ27500:
>>>> + case BQ27510:
>>>> + case BQ27530:
>>>> + case BQ27541:
>>>> + case BQ27545:
>>>> + case BQ27421: break;
>>>
>>> Why even have these cases then?
>>
>> You'll get a compiler warning if any are missing. Helps when adding new chips.
>>
>>>> + case BQ27520: di->chip = BQ27510; break;
>>>> + case BQ27531: di->chip = BQ27530; break;
>>>> + case BQ27542: di->chip = BQ27541; break;
>>>> + case BQ27546: di->chip = BQ27541; break;
>>>> + case BQ27742: di->chip = BQ27541; break;
>>>> + case BQ27425: di->chip = BQ27421; break;
>>>> + case BQ27441: di->chip = BQ27421; break;
>>>> + case BQ27621: di->chip = BQ27421; break;
>>>
>>> Nope, don't like this at all, make a different variable, ->registers or
>>> something to map to the register table. Plus I think changing the
>>> variable you are switching on can cause undefined behavior.
>>
>> We had a different variable, .dmid, but you rejected a second ID
>> field. I think this is better, as we eliminated the static arrays
>> .dmid indexed. I didn't rename .chip to .category as that would cause
>> trivial changes all over the file. I could do that in a final patch
>> tho.
>>
>> You can modify a variable after switching on it, I promise.
>>
>>>> + }
>>>> +
>>>> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
>>>> mutex_init(&di->lock);
>>>> di->regs = bq27xxx_regs[di->chip];
>>>> diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
>>>> index 5c5c3a6..13def59 100644
>>>> --- a/drivers/power/supply/bq27xxx_battery_i2c.c
>>>> +++ b/drivers/power/supply/bq27xxx_battery_i2c.c
>>>> @@ -150,18 +150,18 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
>>>> { "bq27210", BQ27010 },
>>>> { "bq27500", BQ27500 },
>>>> { "bq27510", BQ27510 },
>>>> - { "bq27520", BQ27510 },
>>>> + { "bq27520", BQ27520 },
>>>> { "bq27530", BQ27530 },
>>>> - { "bq27531", BQ27530 },
>>>> + { "bq27531", BQ27531 },
>>>> { "bq27541", BQ27541 },
>>>> - { "bq27542", BQ27541 },
>>>> - { "bq27546", BQ27541 },
>>>> - { "bq27742", BQ27541 },
>>>> + { "bq27542", BQ27542 },
>>>> + { "bq27546", BQ27546 },
>>>> + { "bq27742", BQ27742 },
>>>> { "bq27545", BQ27545 },
>>>> { "bq27421", BQ27421 },
>>>> - { "bq27425", BQ27421 },
>>>> - { "bq27441", BQ27421 },
>>>> - { "bq27621", BQ27421 },
>>>> + { "bq27425", BQ27425 },
>>>> + { "bq27441", BQ27441 },
>>>> + { "bq27621", BQ27621 },
>>>> {},
>>>> };
>>>> MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
>>>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>>>> index 92df553..90db1cf 100644
>>>> --- a/include/linux/power/bq27xxx_battery.h
>>>> +++ b/include/linux/power/bq27xxx_battery.h
>>>> @@ -2,14 +2,25 @@
>>>> #define __LINUX_BQ27X00_BATTERY_H__
>>>>
>>>> enum bq27xxx_chip {
>>>> + /* categories; index for bq27xxx_regs[] */
>>>> BQ27000 = 1, /* bq27000, bq27200 */
>>>> - BQ27010, /* bq27010, bq27210 */
>>>> - BQ27500, /* bq27500 */
>>>> - BQ27510, /* bq27510, bq27520 */
>>>> - BQ27530, /* bq27530, bq27531 */
>>>> - BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
>>>> - BQ27545, /* bq27545 */
>>>> - BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
>>>> + BQ27010 = 2, /* bq27010, bq27210 */
>>>> + BQ27500 = 3, /* bq27500 */
>>>> + BQ27510 = 4, /* bq27510, bq27520 */
>>>> + BQ27530 = 5, /* bq27530, bq27531 */
>>>> + BQ27541 = 6, /* bq27541, bq27542, bq27546, bq27742 */
>>>> + BQ27545 = 7, /* bq27545 */
>>>> + BQ27421 = 8, /* bq27421, bq27425, bq27441, bq27621 */
>>>> +
>>>> + /* members of categories; translate these to category in _setup() */
>>>> + BQ27520 = 101,
>>>> + BQ27531 = 102,
>>>> + BQ27542 = 103,
>>>> + BQ27546 = 104,
>>>> + BQ27742 = 105,
>>>> + BQ27425 = 106,
>>>> + BQ27441 = 107,
>>>> + BQ27621 = 108,
>>>
>>> Get rid of this, just add new chip enum names if you need support for
>>> new chips.
>>
>> How does a non-DT config obtain chip ID? We want explicit enum values
>> if they appear in external platform-data objects. I'll mention that in
>> the next patch description.
>>
>
> platform-data is going away, I'm not sure what you are saying here.
Don't 1-wire users have a platform-data config? You plan to force them
to replace it with DT? I thought that wasn't kosher.
>> The category (original) IDs index bq27xxx_regs[], and you'll probably
>> extend that in time. So I placed the member (new) IDs well above the
>> categories to allow permanent explicit values.
>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
2017-03-16 21:26 ` Liam Breck
@ 2017-03-16 21:30 ` Andrew F. Davis
2017-03-16 21:47 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Andrew F. Davis @ 2017-03-16 21:30 UTC (permalink / raw)
To: Liam Breck; +Cc: Sebastian Reichel, linux-pm, Matt Ranostay, Liam Breck
On 03/16/2017 04:26 PM, Liam Breck wrote:
> On Thu, Mar 16, 2017 at 1:50 PM, Andrew F. Davis <afd@ti.com> wrote:
>> On 03/16/2017 03:12 PM, Liam Breck wrote:
>>> On Thu, Mar 16, 2017 at 7:44 AM, Andrew F. Davis <afd@ti.com> wrote:
>>>> On 03/15/2017 02:26 PM, Liam Breck wrote:
>>>>> From: Liam Breck <kernel@networkimprov.net>
>>>>>
>>>>> Pass actual chip ID into _setup(), which translates it to a group ID,
>>>>> to allow support for all chips by the power_supply_battery_info code.
>>>>> There are no functional changes to the driver.
>>>>>
>>>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>>>> ---
>>>>
>>>> What is this patch based on, it doesn't apply to v4.11-rc1 for me.
>>>
>>> Sorry, I don't have all of Chris' patches here. It wasn't a factor
>>> until we attacked the register arrays. Could you send me his patchset
>>> with:
>>> git format-patch --stdout HEAD~x..HEAD~y > bq27xxx-lapa.mbox
>>>
>>
>> Who are you asking?
>
> You, if I may impose...
>
Just rebase on v4.11-rc1...
>>>>> drivers/power/supply/bq27xxx_battery.c | 19 +++++++++++++++++++
>>>>> drivers/power/supply/bq27xxx_battery_i2c.c | 16 ++++++++--------
>>>>> include/linux/power/bq27xxx_battery.h | 25 ++++++++++++++++++-------
>>>>> 3 files changed, 45 insertions(+), 15 deletions(-)
>>>>>
>>>>> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
>>>>> index 7272d1e..d613d3d 100644
>>>>> --- a/drivers/power/supply/bq27xxx_battery.c
>>>>> +++ b/drivers/power/supply/bq27xxx_battery.c
>>>>> @@ -1020,6 +1020,25 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>>>> struct power_supply_desc *psy_desc;
>>>>> struct power_supply_config psy_cfg = { .drv_data = di, };
>>>>>
>>>>> + switch(di->chip) {
>>>>> + case BQ27000:
>>>>> + case BQ27010:
>>>>> + case BQ27500:
>>>>> + case BQ27510:
>>>>> + case BQ27530:
>>>>> + case BQ27541:
>>>>> + case BQ27545:
>>>>> + case BQ27421: break;
>>>>
>>>> Why even have these cases then?
>>>
>>> You'll get a compiler warning if any are missing. Helps when adding new chips.
>>>
>>>>> + case BQ27520: di->chip = BQ27510; break;
>>>>> + case BQ27531: di->chip = BQ27530; break;
>>>>> + case BQ27542: di->chip = BQ27541; break;
>>>>> + case BQ27546: di->chip = BQ27541; break;
>>>>> + case BQ27742: di->chip = BQ27541; break;
>>>>> + case BQ27425: di->chip = BQ27421; break;
>>>>> + case BQ27441: di->chip = BQ27421; break;
>>>>> + case BQ27621: di->chip = BQ27421; break;
>>>>
>>>> Nope, don't like this at all, make a different variable, ->registers or
>>>> something to map to the register table. Plus I think changing the
>>>> variable you are switching on can cause undefined behavior.
>>>
>>> We had a different variable, .dmid, but you rejected a second ID
>>> field. I think this is better, as we eliminated the static arrays
>>> .dmid indexed. I didn't rename .chip to .category as that would cause
>>> trivial changes all over the file. I could do that in a final patch
>>> tho.
>>>
>>> You can modify a variable after switching on it, I promise.
>>>
>>>>> + }
>>>>> +
>>>>> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
>>>>> mutex_init(&di->lock);
>>>>> di->regs = bq27xxx_regs[di->chip];
>>>>> diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>> index 5c5c3a6..13def59 100644
>>>>> --- a/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>> +++ b/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>> @@ -150,18 +150,18 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
>>>>> { "bq27210", BQ27010 },
>>>>> { "bq27500", BQ27500 },
>>>>> { "bq27510", BQ27510 },
>>>>> - { "bq27520", BQ27510 },
>>>>> + { "bq27520", BQ27520 },
>>>>> { "bq27530", BQ27530 },
>>>>> - { "bq27531", BQ27530 },
>>>>> + { "bq27531", BQ27531 },
>>>>> { "bq27541", BQ27541 },
>>>>> - { "bq27542", BQ27541 },
>>>>> - { "bq27546", BQ27541 },
>>>>> - { "bq27742", BQ27541 },
>>>>> + { "bq27542", BQ27542 },
>>>>> + { "bq27546", BQ27546 },
>>>>> + { "bq27742", BQ27742 },
>>>>> { "bq27545", BQ27545 },
>>>>> { "bq27421", BQ27421 },
>>>>> - { "bq27425", BQ27421 },
>>>>> - { "bq27441", BQ27421 },
>>>>> - { "bq27621", BQ27421 },
>>>>> + { "bq27425", BQ27425 },
>>>>> + { "bq27441", BQ27441 },
>>>>> + { "bq27621", BQ27621 },
>>>>> {},
>>>>> };
>>>>> MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
>>>>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>>>>> index 92df553..90db1cf 100644
>>>>> --- a/include/linux/power/bq27xxx_battery.h
>>>>> +++ b/include/linux/power/bq27xxx_battery.h
>>>>> @@ -2,14 +2,25 @@
>>>>> #define __LINUX_BQ27X00_BATTERY_H__
>>>>>
>>>>> enum bq27xxx_chip {
>>>>> + /* categories; index for bq27xxx_regs[] */
>>>>> BQ27000 = 1, /* bq27000, bq27200 */
>>>>> - BQ27010, /* bq27010, bq27210 */
>>>>> - BQ27500, /* bq27500 */
>>>>> - BQ27510, /* bq27510, bq27520 */
>>>>> - BQ27530, /* bq27530, bq27531 */
>>>>> - BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
>>>>> - BQ27545, /* bq27545 */
>>>>> - BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
>>>>> + BQ27010 = 2, /* bq27010, bq27210 */
>>>>> + BQ27500 = 3, /* bq27500 */
>>>>> + BQ27510 = 4, /* bq27510, bq27520 */
>>>>> + BQ27530 = 5, /* bq27530, bq27531 */
>>>>> + BQ27541 = 6, /* bq27541, bq27542, bq27546, bq27742 */
>>>>> + BQ27545 = 7, /* bq27545 */
>>>>> + BQ27421 = 8, /* bq27421, bq27425, bq27441, bq27621 */
>>>>> +
>>>>> + /* members of categories; translate these to category in _setup() */
>>>>> + BQ27520 = 101,
>>>>> + BQ27531 = 102,
>>>>> + BQ27542 = 103,
>>>>> + BQ27546 = 104,
>>>>> + BQ27742 = 105,
>>>>> + BQ27425 = 106,
>>>>> + BQ27441 = 107,
>>>>> + BQ27621 = 108,
>>>>
>>>> Get rid of this, just add new chip enum names if you need support for
>>>> new chips.
>>>
>>> How does a non-DT config obtain chip ID? We want explicit enum values
>>> if they appear in external platform-data objects. I'll mention that in
>>> the next patch description.
>>>
>>
>> platform-data is going away, I'm not sure what you are saying here.
>
> Don't 1-wire users have a platform-data config? You plan to force them
> to replace it with DT? I thought that wasn't kosher.
>
The 1-wire driver generates this platform-data, 1-wire is a discoverable
bus, they never needed to define DT or platform data and still will not.
>>> The category (original) IDs index bq27xxx_regs[], and you'll probably
>>> extend that in time. So I placed the member (new) IDs well above the
>>> categories to allow permanent explicit values.
>>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support
2017-03-16 21:12 ` Liam Breck
@ 2017-03-16 21:39 ` Andrew F. Davis
2017-03-16 22:31 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Andrew F. Davis @ 2017-03-16 21:39 UTC (permalink / raw)
To: Liam Breck; +Cc: Sebastian Reichel, linux-pm, Liam Breck
On 03/16/2017 04:12 PM, Liam Breck wrote:
> On Thu, Mar 16, 2017 at 8:00 AM, Andrew F. Davis <afd@ti.com> wrote:
>> On 03/15/2017 02:26 PM, Liam Breck wrote:
>>> From: Liam Breck <kernel@networkimprov.net>
>>>
>>> Previously there was no way to configure chip registers in the event that the
>>> defaults didn't match the battery in question.
>>>
>>> BQ27xxx driver now calls power_supply_get_battery_info, checks the inputs,
>>> and writes battery data to chip RAM or non-volatile memory.
>>>
>>> Supports chips BQ27500, 545, 421, 425, 441, 621. Others may be added.
>>>
>>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>> ---
>>> drivers/power/supply/bq27xxx_battery.c | 478 ++++++++++++++++++++++++++++++++-
>>> include/linux/power/bq27xxx_battery.h | 2 +
>>> 2 files changed, 468 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
>>> index d613d3d..fb062db 100644
>>> --- a/drivers/power/supply/bq27xxx_battery.c
>>> +++ b/drivers/power/supply/bq27xxx_battery.c
>>> @@ -51,7 +51,7 @@
>>>
>>> #include <linux/power/bq27xxx_battery.h>
>>>
>>> -#define DRIVER_VERSION "1.2.0"
>>> +#define DRIVER_VERSION "1.3.0"
>>>
>>> #define BQ27XXX_MANUFACTURER "Texas Instruments"
>>>
>>> @@ -59,6 +59,7 @@
>>> #define BQ27XXX_FLAG_DSC BIT(0)
>>> #define BQ27XXX_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
>>> #define BQ27XXX_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
>>> +#define BQ27XXX_FLAG_CFGUP BIT(4)
>>> #define BQ27XXX_FLAG_FC BIT(9)
>>> #define BQ27XXX_FLAG_OTD BIT(14)
>>> #define BQ27XXX_FLAG_OTC BIT(15)
>>> @@ -72,6 +73,11 @@
>>> #define BQ27000_FLAG_FC BIT(5)
>>> #define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
>>>
>>> +/* control register params */
>>> +#define BQ27XXX_SEALED 0x20
>>> +#define BQ27XXX_SET_CFGUPDATE 0x13
>>> +#define BQ27XXX_SOFT_RESET 0x42
>>> +
>>> #define BQ27XXX_RS (20) /* Resistor sense mOhm */
>>> #define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */
>>> #define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */
>>> @@ -102,6 +108,11 @@ enum bq27xxx_reg_index {
>>> BQ27XXX_REG_SOC, /* State-of-Charge */
>>> BQ27XXX_REG_DCAP, /* Design Capacity */
>>> BQ27XXX_REG_AP, /* Average Power */
>>> + BQ27XXX_DM_CTRL, /* BlockDataControl() */
>>> + BQ27XXX_DM_CLASS, /* DataClass() */
>>> + BQ27XXX_DM_BLOCK, /* DataBlock() */
>>> + BQ27XXX_DM_DATA, /* BlockData() */
>>> + BQ27XXX_DM_CKSUM, /* BlockDataChecksum() */
>>> BQ27XXX_REG_MAX, /* sentinel */
>>> };
>>>
>>> @@ -125,6 +136,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>> [BQ27XXX_REG_SOC] = 0x0b,
>>> [BQ27XXX_REG_DCAP] = 0x76,
>>> [BQ27XXX_REG_AP] = 0x24,
>>> + [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_DATA] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR,
>>> },
>>> [BQ27010] = {
>>> [BQ27XXX_REG_CTRL] = 0x00,
>>> @@ -144,6 +160,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>> [BQ27XXX_REG_SOC] = 0x0b,
>>> [BQ27XXX_REG_DCAP] = 0x76,
>>> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_DATA] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR,
>>> },
>>> [BQ27500] = {
>>> [BQ27XXX_REG_CTRL] = 0x00,
>>> @@ -163,6 +184,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>> [BQ27XXX_REG_SOC] = 0x2c,
>>> [BQ27XXX_REG_DCAP] = 0x3c,
>>> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>> + [BQ27XXX_DM_DATA] = 0x40,
>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>> },
>>> [BQ27510] = {
>>> [BQ27XXX_REG_CTRL] = 0x00,
>>> @@ -182,6 +208,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>> [BQ27XXX_REG_SOC] = 0x20,
>>> [BQ27XXX_REG_DCAP] = 0x2e,
>>> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>> + [BQ27XXX_DM_DATA] = 0x40,
>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>> },
>>> [BQ27530] = {
>>> [BQ27XXX_REG_CTRL] = 0x00,
>>> @@ -201,6 +232,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>> [BQ27XXX_REG_SOC] = 0x2c,
>>> [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
>>> [BQ27XXX_REG_AP] = 0x24,
>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>> + [BQ27XXX_DM_DATA] = 0x40,
>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>> },
>>> [BQ27541] = {
>>> [BQ27XXX_REG_CTRL] = 0x00,
>>> @@ -220,6 +256,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>> [BQ27XXX_REG_SOC] = 0x2c,
>>> [BQ27XXX_REG_DCAP] = 0x3c,
>>> [BQ27XXX_REG_AP] = 0x24,
>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>> + [BQ27XXX_DM_DATA] = 0x40,
>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>> },
>>> [BQ27545] = {
>>> [BQ27XXX_REG_CTRL] = 0x00,
>>> @@ -239,6 +280,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>> [BQ27XXX_REG_SOC] = 0x2c,
>>> [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
>>> [BQ27XXX_REG_AP] = 0x24,
>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>> + [BQ27XXX_DM_DATA] = 0x40,
>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>> },
>>> [BQ27421] = {
>>> [BQ27XXX_REG_CTRL] = 0x00,
>>> @@ -258,6 +304,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>> [BQ27XXX_REG_SOC] = 0x1c,
>>> [BQ27XXX_REG_DCAP] = 0x3c,
>>> [BQ27XXX_REG_AP] = 0x18,
>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>> + [BQ27XXX_DM_DATA] = 0x40,
>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>> },
>>> };
>>>
>>> @@ -432,6 +483,82 @@ static struct {
>>> static DEFINE_MUTEX(bq27xxx_list_lock);
>>> static LIST_HEAD(bq27xxx_battery_devices);
>>>
>>> +#define BQ27XXX_DM_SZ 32
>>> +
>>> +#define BQ27XXX_MSLEEP(i) usleep_range((i)*1000, (i)*1000+500)
>>> +
>>> +struct bq27xxx_dm_reg {
>>> + u8 subclass_id;
>>> + u8 offset;
>>> + u8 bytes;
>>> + u16 min, max;
>>> +};
>>> +
>>> +struct bq27xxx_dm_buf {
>>> + u8 class;
>>> + u8 block;
>>> + u8 a[BQ27XXX_DM_SZ];
>>> + bool full, updt;
>>> +};
>>> +
>>> +#define BQ27XXX_DM_BUF(di, i) { \
>>> + .class = (di)->dm_regs[i].subclass_id, \
>>> + .block = (di)->dm_regs[i].offset / BQ27XXX_DM_SZ, \
>>> +}
>>> +
>>> +static inline u16* bq27xxx_dm_reg_ptr(struct bq27xxx_dm_buf *buf,
>>> + struct bq27xxx_dm_reg *reg)
>>> +{
>>> + if (buf->class == reg->subclass_id
>>> + && buf->block == reg->offset / BQ27XXX_DM_SZ)
>>> + return (u16*) (buf->a + reg->offset % BQ27XXX_DM_SZ);
>>> +
>>> + return NULL;
>>> +}
>>> +
>>> +enum bq27xxx_dm_reg_id {
>>> + BQ27XXX_DM_DESIGN_CAPACITY = 0,
>>> + BQ27XXX_DM_DESIGN_ENERGY,
>>> + BQ27XXX_DM_TERMINATE_VOLTAGE,
>>> +};
>>> +
>>> +static const char* bq27xxx_dm_reg_name[] = {
>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = "design-capacity",
>>> + [BQ27XXX_DM_DESIGN_ENERGY] = "design-energy",
>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = "terminate-voltage",
>>> +};
>>> +
>>> +static struct bq27xxx_dm_reg bq27500_dm_regs[] = {
>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 10, 2, 0, 65535 },
>>> + [BQ27XXX_DM_DESIGN_ENERGY] = { }, /* missing on chip */
>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 48, 2, 1000, 32767 },
>>> +};
>>> +
>>> +static struct bq27xxx_dm_reg bq27545_dm_regs[] = {
>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 23, 2, 0, 32767 },
>>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 48, 25, 2, 0, 32767 },
>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 67, 2, 2800, 3700 },
>>> +};
>>> +
>>> +static struct bq27xxx_dm_reg bq27421_dm_regs[] = {
>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 8000 },
>>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 },
>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 16, 2, 2500, 3700 },
>>> +};
>>> +
>>> +static struct bq27xxx_dm_reg bq27425_dm_regs[] = {
>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 12, 2, 0, 32767 },
>>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 14, 2, 0, 32767 },
>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 18, 2, 2800, 3700 },
>>> +};
>>> +
>>> +static struct bq27xxx_dm_reg bq27621_dm_regs[] = {
>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 3, 2, 0, 8000 },
>>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 5, 2, 0, 32767 },
>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 9, 2, 2500, 3700 },
>>> +};
>>> +
>>> +
>>> static int poll_interval_param_set(const char *val, const struct kernel_param *kp)
>>> {
>>> struct bq27xxx_device_info *di;
>>> @@ -476,6 +603,317 @@ static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index,
>>> return di->bus.read(di, di->regs[reg_index], single);
>>> }
>>>
>>> +static int bq27xxx_battery_set_seal_state(struct bq27xxx_device_info *di,
>>> + bool state)
>>> +{
>>> + int ret;
>>> +
>>> + if (state) {
>>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], BQ27XXX_SEALED, false);
>>
>>
>> Look at how reads are done, we have a function bq27xxx_read() that
>> checks the register and handles the access methods. Do something like
>> that for write, then replace all these with that, "bus" should only be
>> accessed in that function.
>
> OK. And for bus.{read,write}_bulk() too? They only occur once.
>
Sure, why not
>>> + if (ret < 0)
>>> + goto out;
>>> + } else {
>>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], (u16)(di->unseal_key >> 16), false);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], (u16)di->unseal_key, false);
>>> + if (ret < 0)
>>> + goto out;
>>> + }
>>
>> +space
>>
>> Has this been run through checkpatch?
>>
Well...
>>> + return 0;
>>> +
>>> +out:
>>> + dev_err(di->dev, "bus error on %s: %d\n", state ? "seal" : "unseal", ret);
>>> + return ret;
>>> +}
>>> +
>>> +static u8 bq27xxx_battery_checksum_dm_block(struct bq27xxx_dm_buf *buf)
>>> +{
>>> + u16 sum = 0;
>>> + int i;
>>> +
>>> + for (i = 0; i < BQ27XXX_DM_SZ; i++)
>>> + sum += buf->a[i];
>>> + sum &= 0xff;
>>> +
>>> + return 0xff - sum;
>>> +}
>>> +
>>> +static int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di,
>>> + struct bq27xxx_dm_buf *buf)
>>> +{
>>> + int ret;
>>> +
>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CLASS], buf->class, true);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_BLOCK], buf->block, true);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + BQ27XXX_MSLEEP(1);
>>> +
>>> + ret = di->bus.read_bulk(di, di->regs[BQ27XXX_DM_DATA], buf->a, BQ27XXX_DM_SZ);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + ret = di->bus.read(di, di->regs[BQ27XXX_DM_CKSUM], true);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + if ((u8)ret != bq27xxx_battery_checksum_dm_block(buf)) {
>>> + ret = -EINVAL;
>>> + goto out;
>>> + }
>>> +
>>> + buf->full = true;
>>> + buf->updt = false;
>>> + return 0;
>>> +
>>> +out:
>>> + dev_err(di->dev, "bus error reading chip memory: %d\n", ret);
>>
>> Instead of this catch-all, each spot should have an error message that
>> explains what failed. If they all end up with this generic message we
>> cannot possibly diagnose issues for people.
>
> Knowing which bus op failed doesn't help.
Sure it does, knowing which step it fails or locks the chip is useful.
> Any error means either the
> bus hw failed or chip died. If we're debugging a new chip, we'll need
> extra print statements anyway.
>
>>> + return ret;
>>> +}
>>> +
>>> +static void bq27xxx_battery_update_dm_block(struct bq27xxx_device_info *di,
>>> + struct bq27xxx_dm_buf *buf,
>>> + enum bq27xxx_dm_reg_id reg_id,
>>> + unsigned int val)
>>> +{
>>> + struct bq27xxx_dm_reg *reg = &di->dm_regs[reg_id];
>>> + const char* str = bq27xxx_dm_reg_name[reg_id];
>>> + u16 *prev = bq27xxx_dm_reg_ptr(buf, reg);
>>> +
>>> + if (prev == NULL) {
>>> + dev_warn(di->dev, "buffer does not match %s dm spec\n", str);
>>> + return;
>>> + }
>>> +
>>> + if (reg->bytes != 2) {
>>> + dev_warn(di->dev, "%s dm spec has unsupported byte size\n", str);
>>> + return;
>>> + }
>>> +
>>> + if (!buf->full)
>>> + return;
>>> +
>>> + if (be16_to_cpup(prev) == val) {
>>> + dev_info(di->dev, "%s has %u\n", str, val);
>>> + return;
>>> + }
>>> +
>>> + dev_info(di->dev, "update %s to %u\n", str, val);
>>> +
>>> + *prev = cpu_to_be16(val);
>>> + buf->updt = true;
>>> +}
>>> +
>>> +static int bq27xxx_battery_set_cfgupdate(struct bq27xxx_device_info *di,
>>> + bool state)
>>
>> Why only two states? why bool? you should probably be passing in the
>> value, if you really want to do this as a state, then the states should
>> have an enum for each state.
>
> You can enter or exit cfgupdate mode. We do the same for
> set_seal_state(). And bq27xxx_read() takes a bool arg to indicate one
> or two bytes.
>
bq27xxx_read() has the arg as a question, "Is this a two byte read?
(true/false)", yours is "What state would you like to set?
(true/false)", see how one doesn't work, fix that.
>>> +{
>>> + int ret, try=100;
>>> +
>>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL],
>>> + state ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET,
>>> + false);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + do {
>>> + BQ27XXX_MSLEEP(25);
>>> + ret = di->bus.read(di, di->regs[BQ27XXX_REG_FLAGS], false);
>>> + if (ret < 0)
>>> + goto out;
>>> + } while (!(ret & BQ27XXX_FLAG_CFGUP) == state && --try);
>>> +
>>> + if (!try) {
>>> + dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", state);
>>> + return -EINVAL;
>>> + }
>>
>> Put this check inside the loop.
>
> We test try inside the loop. This test is only relevant after the loop.
>
It is not, try to think what I'm saying, if you move the test inside,
then we don't have to test as part of the while, and we don't have to
test after.
>>> +
>>> + if (100-try > 3)
>>
>> Why 3? lets also count up to a set value, 100 is a magic number, if I
>> change try to =200, I have to change it down here, that is going to be
>> buggy.
>
> OK. 3 because 75ms is a long time.
>
says who?
>>> + dev_warn(di->dev, "cfgupdate %d, retries %d\n", state, 100-try);
>>> +
>>> + return 0;
>>> +
>>> +out:
>>> + dev_err(di->dev, "bus error on %s: %d\n", state ? "set_cfgupdate" : "soft_reset", ret);
>>> + return ret;
>>> +}
>>> +
>>> +static int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di,
>>> + struct bq27xxx_dm_buf *buf)
>>> +{
>>> + bool cfgup = di->chip == BQ27421; /* assume group supports cfgupdate */
>>> + int ret;
>>> +
>>> + if (!buf->updt)
>>> + return 0;
>>> +
>>> + if (cfgup) {
>>> + ret = bq27xxx_battery_set_cfgupdate(di, true);
>>> + if (ret < 0)
>>> + return ret;
>>> + }
>>> +
>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CTRL], 0, true);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CLASS], buf->class, true);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_BLOCK], buf->block, true);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + BQ27XXX_MSLEEP(1);
>>> +
>>> + ret = di->bus.write_bulk(di, di->regs[BQ27XXX_DM_DATA], buf->a, BQ27XXX_DM_SZ);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CKSUM],
>>> + bq27xxx_battery_checksum_dm_block(buf), true);
>>> + if (ret < 0)
>>> + goto out;
>>> +
>>> + /* THE FOLLOWING SEQUENCE IS TOXIC. DO NOT USE!
>>> + * If the 'time' delay is insufficient, NVM corruption results on
>>> + * the '425 chip (and perhaps others), which could damage the chip.
>>> + * It was suggested in this TI tool:
>>> + * http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328
>>> + *
>>> + * 1. MSLEEP(time) after above write(BQ27XXX_DM_CKSUM, ...)
>>> + * 2. write(BQ27XXX_DM_BLOCK, buf->block)
>>> + * 3. sum = read(BQ27XXX_DM_CKSUM)
>>> + * 4. if (sum != bq27xxx_battery_checksum_dm_block(buf))
>>> + * report error
>>> + */
>>> +
>>> + if (cfgup) {
>>> + BQ27XXX_MSLEEP(1);
>>> + ret = bq27xxx_battery_set_cfgupdate(di, false);
>>> + if (ret < 0)
>>> + return ret;
>>> + } else {
>>> + /* flash DM updates in <100ms, but reset time isn't documented */
>>> + BQ27XXX_MSLEEP(400);
>>> + }
>>> +
>>> + buf->updt = false;
>>> + return 0;
>>> +
>>> +out:
>>> + if (cfgup)
>>> + bq27xxx_battery_set_cfgupdate(di, false);
>>> +
>>> + dev_err(di->dev, "bus error writing chip memory: %d\n", ret);
>>> + return ret;
>>> +}
>>> +
>>> +static void bq27xxx_battery_set_config(struct bq27xxx_device_info *di,
>>> + struct power_supply_battery_info *info)
>>> +{
>>> + struct bq27xxx_dm_buf bd = BQ27XXX_DM_BUF(di, BQ27XXX_DM_DESIGN_CAPACITY);
>>> + struct bq27xxx_dm_buf bt = BQ27XXX_DM_BUF(di, BQ27XXX_DM_TERMINATE_VOLTAGE);
>>> +
>>> + if (info->charge_full_design_uah != -EINVAL
>>> + && info->energy_full_design_uwh != -EINVAL) {
>>> + bq27xxx_battery_read_dm_block(di, &bd);
>>> + /* assume design energy & capacity are in same block */
>>> + bq27xxx_battery_update_dm_block(di, &bd,
>>> + BQ27XXX_DM_DESIGN_CAPACITY,
>>> + info->charge_full_design_uah / 1000);
>>> + bq27xxx_battery_update_dm_block(di, &bd,
>>> + BQ27XXX_DM_DESIGN_ENERGY,
>>> + info->energy_full_design_uwh / 1000);
>>> + }
>>> +
>>> + if (info->voltage_min_design_uv != -EINVAL) {
>>> + bool same = bd.class == bt.class && bd.block == bt.block;
>>> + if (!same)
>>> + bq27xxx_battery_read_dm_block(di, &bt);
>>> + bq27xxx_battery_update_dm_block(di, same ? &bd : &bt,
>>> + BQ27XXX_DM_TERMINATE_VOLTAGE,
>>> + info->voltage_min_design_uv / 1000);
>>> + }
>>> +
>>> + bq27xxx_battery_write_dm_block(di, &bd);
>>> + bq27xxx_battery_write_dm_block(di, &bt);
>>> +}
>>> +
>>> +void bq27xxx_battery_settings(struct bq27xxx_device_info *di)
>>> +{
>>> + struct power_supply_battery_info info = {};
>>> + unsigned int min, max;
>>> +
>>> + /* functions don't exist for writing data so abort */
>>> + if (!di->bus.write || !di->bus.write_bulk)
>>> + return;
>>> +
>>> + /* no settings to be set for this chipset so abort */
>>> + if (!di->dm_regs)
>>> + return;
>>> +
>>> + if (bq27xxx_battery_set_seal_state(di, false) < 0)
>>> + return;
>>> +
>>> + if (power_supply_get_battery_info(di->bat, &info) < 0)
>>> + goto out;
>>> +
>>> + if (info.energy_full_design_uwh != info.charge_full_design_uah) {
>>> + if (info.energy_full_design_uwh == -EINVAL)
>>> + dev_warn(di->dev,
>>> + "missing battery:energy-full-design-microwatt-hours\n");
>>> + else if (info.charge_full_design_uah == -EINVAL)
>>> + dev_warn(di->dev,
>>> + "missing battery:charge-full-design-microamp-hours\n");
>>> + }
>>> +
>>> + /* assume min == 0 */
>>> + max = di->dm_regs[BQ27XXX_DM_DESIGN_ENERGY].max;
>>> + if (info.energy_full_design_uwh > max * 1000) {
>>> + dev_err(di->dev,
>>> + "invalid battery:energy-full-design-microwatt-hours %d\n",
>>> + info.energy_full_design_uwh);
>>> + info.energy_full_design_uwh = -EINVAL;
>>> + }
>>> +
>>> + /* assume min == 0 */
>>> + max = di->dm_regs[BQ27XXX_DM_DESIGN_CAPACITY].max;
>>> + if (info.charge_full_design_uah > max * 1000) {
>>> + dev_err(di->dev,
>>> + "invalid battery:charge-full-design-microamp-hours %d\n",
>>> + info.charge_full_design_uah);
>>> + info.charge_full_design_uah = -EINVAL;
>>> + }
>>> +
>>> + min = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].min;
>>> + max = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].max;
>>> + if ((info.voltage_min_design_uv < min * 1000
>>> + || info.voltage_min_design_uv > max * 1000)
>>> + && info.voltage_min_design_uv != -EINVAL) {
>>> + dev_err(di->dev,
>>> + "invalid battery:voltage-min-design-microvolt %d\n",
>>> + info.voltage_min_design_uv);
>>> + info.voltage_min_design_uv = -EINVAL;
>>> + }
>>> +
>>> + if ((info.energy_full_design_uwh == -EINVAL
>>> + || info.charge_full_design_uah == -EINVAL)
>>> + && info.voltage_min_design_uv == -EINVAL)
>>> + goto out;
>>> +
>>> + bq27xxx_battery_set_config(di, &info);
>>> +
>>> +out:
>>> + bq27xxx_battery_set_seal_state(di, true);
>>
>> Don't use goto unless you have to, this is not such a case.
>
> OK.
>
>>> +}
>>> +
>>> /*
>>> * Return the battery State-of-Charge
>>> * Or < 0 if something fails.
>>> @@ -985,6 +1423,13 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
>>> case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
>>> ret = bq27xxx_simple_value(di->charge_design_full, val);
>>> break;
>>> + /*
>>> + * TODO: Implement these to make registers set from
>>> + * power_supply_battery_info visible in sysfs.
>>> + */
>>> + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
>>> + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
>>> + return -EINVAL;
>>> case POWER_SUPPLY_PROP_CYCLE_COUNT:
>>> ret = bq27xxx_simple_value(di->cache.cycle_count, val);
>>> break;
>>> @@ -1015,28 +1460,36 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
>>> schedule_delayed_work(&di->work, 0);
>>> }
>>>
>>> +#define BQ27XXX_INIT(c,d,k) \
>>> + di->chip = (c); \
>>> + di->dm_regs = (d); \
>>> + di->unseal_key = (k)
>>> +
>>> int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>> {
>>> struct power_supply_desc *psy_desc;
>>> - struct power_supply_config psy_cfg = { .drv_data = di, };
>>> + struct power_supply_config psy_cfg = {
>>> + .of_node = di->dev->of_node,
>>> + .drv_data = di,
>>> + };
>>>
>>> switch(di->chip) {
>>> case BQ27000:
>>> - case BQ27010:
>>> - case BQ27500:
>>> - case BQ27510:
>>> - case BQ27530:
>>> - case BQ27541:
>>> - case BQ27545:
>>> - case BQ27421: break;
>>> + case BQ27010: break;
>>> + case BQ27500: BQ27XXX_INIT(BQ27500, bq27500_dm_regs, 0x04143672); break;
>>> + case BQ27510: break;
>>> + case BQ27530: break;
>>> + case BQ27541: break;
>>> + case BQ27545: BQ27XXX_INIT(BQ27545, bq27545_dm_regs, 0x04143672); break;
>>> + case BQ27421: BQ27XXX_INIT(BQ27421, bq27421_dm_regs, 0x80008000); break;
>>> case BQ27520: di->chip = BQ27510; break;
>>> case BQ27531: di->chip = BQ27530; break;
>>> case BQ27542: di->chip = BQ27541; break;
>>> case BQ27546: di->chip = BQ27541; break;
>>> case BQ27742: di->chip = BQ27541; break;
>>> - case BQ27425: di->chip = BQ27421; break;
>>> - case BQ27441: di->chip = BQ27421; break;
>>> - case BQ27621: di->chip = BQ27421; break;
>>> + case BQ27425: BQ27XXX_INIT(BQ27421, bq27425_dm_regs, 0x04143672); break;
>>> + case BQ27441: BQ27XXX_INIT(BQ27421, bq27421_dm_regs, 0x80008000); break;
>>> + case BQ27621: BQ27XXX_INIT(BQ27421, bq27621_dm_regs, 0x80008000); break;
>>> }
>>>
>>> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
>>> @@ -1062,6 +1515,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>>
>>> dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
>>>
>>> + bq27xxx_battery_settings(di);
>>> bq27xxx_battery_update(di);
>>>
>>> mutex_lock(&bq27xxx_list_lock);
>>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>>> index 90db1cf..dbf1ab9 100644
>>> --- a/include/linux/power/bq27xxx_battery.h
>>> +++ b/include/linux/power/bq27xxx_battery.h
>>> @@ -67,6 +67,8 @@ struct bq27xxx_device_info {
>>> int id;
>>> enum bq27xxx_chip chip;
>>> const char *name;
>>> + struct bq27xxx_dm_reg *dm_regs;
>>> + u32 unseal_key;
>>> struct bq27xxx_access_methods bus;
>>> struct bq27xxx_reg_cache cache;
>>> int charge_design_full;
>>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
2017-03-16 21:30 ` Andrew F. Davis
@ 2017-03-16 21:47 ` Liam Breck
2017-03-16 21:53 ` Andrew F. Davis
0 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-16 21:47 UTC (permalink / raw)
To: Andrew F. Davis; +Cc: Sebastian Reichel, linux-pm, Matt Ranostay, Liam Breck
On Thu, Mar 16, 2017 at 2:30 PM, Andrew F. Davis <afd@ti.com> wrote:
> On 03/16/2017 04:26 PM, Liam Breck wrote:
>> On Thu, Mar 16, 2017 at 1:50 PM, Andrew F. Davis <afd@ti.com> wrote:
>>> On 03/16/2017 03:12 PM, Liam Breck wrote:
>>>> On Thu, Mar 16, 2017 at 7:44 AM, Andrew F. Davis <afd@ti.com> wrote:
>>>>> On 03/15/2017 02:26 PM, Liam Breck wrote:
>>>>>> From: Liam Breck <kernel@networkimprov.net>
>>>>>>
>>>>>> Pass actual chip ID into _setup(), which translates it to a group ID,
>>>>>> to allow support for all chips by the power_supply_battery_info code.
>>>>>> There are no functional changes to the driver.
>>>>>>
>>>>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>>>>> ---
>>>>>
>>>>> What is this patch based on, it doesn't apply to v4.11-rc1 for me.
>>>>
>>>> Sorry, I don't have all of Chris' patches here. It wasn't a factor
>>>> until we attacked the register arrays. Could you send me his patchset
>>>> with:
>>>> git format-patch --stdout HEAD~x..HEAD~y > bq27xxx-lapa.mbox
>>>>
>>>
>>> Who are you asking?
>>
>> You, if I may impose...
>>
>
> Just rebase on v4.11-rc1...
>
>>>>>> drivers/power/supply/bq27xxx_battery.c | 19 +++++++++++++++++++
>>>>>> drivers/power/supply/bq27xxx_battery_i2c.c | 16 ++++++++--------
>>>>>> include/linux/power/bq27xxx_battery.h | 25 ++++++++++++++++++-------
>>>>>> 3 files changed, 45 insertions(+), 15 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
>>>>>> index 7272d1e..d613d3d 100644
>>>>>> --- a/drivers/power/supply/bq27xxx_battery.c
>>>>>> +++ b/drivers/power/supply/bq27xxx_battery.c
>>>>>> @@ -1020,6 +1020,25 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>>>>> struct power_supply_desc *psy_desc;
>>>>>> struct power_supply_config psy_cfg = { .drv_data = di, };
>>>>>>
>>>>>> + switch(di->chip) {
>>>>>> + case BQ27000:
>>>>>> + case BQ27010:
>>>>>> + case BQ27500:
>>>>>> + case BQ27510:
>>>>>> + case BQ27530:
>>>>>> + case BQ27541:
>>>>>> + case BQ27545:
>>>>>> + case BQ27421: break;
>>>>>
>>>>> Why even have these cases then?
>>>>
>>>> You'll get a compiler warning if any are missing. Helps when adding new chips.
>>>>
>>>>>> + case BQ27520: di->chip = BQ27510; break;
>>>>>> + case BQ27531: di->chip = BQ27530; break;
>>>>>> + case BQ27542: di->chip = BQ27541; break;
>>>>>> + case BQ27546: di->chip = BQ27541; break;
>>>>>> + case BQ27742: di->chip = BQ27541; break;
>>>>>> + case BQ27425: di->chip = BQ27421; break;
>>>>>> + case BQ27441: di->chip = BQ27421; break;
>>>>>> + case BQ27621: di->chip = BQ27421; break;
>>>>>
>>>>> Nope, don't like this at all, make a different variable, ->registers or
>>>>> something to map to the register table. Plus I think changing the
>>>>> variable you are switching on can cause undefined behavior.
>>>>
>>>> We had a different variable, .dmid, but you rejected a second ID
>>>> field. I think this is better, as we eliminated the static arrays
>>>> .dmid indexed. I didn't rename .chip to .category as that would cause
>>>> trivial changes all over the file. I could do that in a final patch
>>>> tho.
>>>>
>>>> You can modify a variable after switching on it, I promise.
>>>>
>>>>>> + }
>>>>>> +
>>>>>> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
>>>>>> mutex_init(&di->lock);
>>>>>> di->regs = bq27xxx_regs[di->chip];
>>>>>> diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>>> index 5c5c3a6..13def59 100644
>>>>>> --- a/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>>> +++ b/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>>> @@ -150,18 +150,18 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
>>>>>> { "bq27210", BQ27010 },
>>>>>> { "bq27500", BQ27500 },
>>>>>> { "bq27510", BQ27510 },
>>>>>> - { "bq27520", BQ27510 },
>>>>>> + { "bq27520", BQ27520 },
>>>>>> { "bq27530", BQ27530 },
>>>>>> - { "bq27531", BQ27530 },
>>>>>> + { "bq27531", BQ27531 },
>>>>>> { "bq27541", BQ27541 },
>>>>>> - { "bq27542", BQ27541 },
>>>>>> - { "bq27546", BQ27541 },
>>>>>> - { "bq27742", BQ27541 },
>>>>>> + { "bq27542", BQ27542 },
>>>>>> + { "bq27546", BQ27546 },
>>>>>> + { "bq27742", BQ27742 },
>>>>>> { "bq27545", BQ27545 },
>>>>>> { "bq27421", BQ27421 },
>>>>>> - { "bq27425", BQ27421 },
>>>>>> - { "bq27441", BQ27421 },
>>>>>> - { "bq27621", BQ27421 },
>>>>>> + { "bq27425", BQ27425 },
>>>>>> + { "bq27441", BQ27441 },
>>>>>> + { "bq27621", BQ27621 },
>>>>>> {},
>>>>>> };
>>>>>> MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
>>>>>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>>>>>> index 92df553..90db1cf 100644
>>>>>> --- a/include/linux/power/bq27xxx_battery.h
>>>>>> +++ b/include/linux/power/bq27xxx_battery.h
>>>>>> @@ -2,14 +2,25 @@
>>>>>> #define __LINUX_BQ27X00_BATTERY_H__
>>>>>>
>>>>>> enum bq27xxx_chip {
>>>>>> + /* categories; index for bq27xxx_regs[] */
>>>>>> BQ27000 = 1, /* bq27000, bq27200 */
>>>>>> - BQ27010, /* bq27010, bq27210 */
>>>>>> - BQ27500, /* bq27500 */
>>>>>> - BQ27510, /* bq27510, bq27520 */
>>>>>> - BQ27530, /* bq27530, bq27531 */
>>>>>> - BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
>>>>>> - BQ27545, /* bq27545 */
>>>>>> - BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
>>>>>> + BQ27010 = 2, /* bq27010, bq27210 */
>>>>>> + BQ27500 = 3, /* bq27500 */
>>>>>> + BQ27510 = 4, /* bq27510, bq27520 */
>>>>>> + BQ27530 = 5, /* bq27530, bq27531 */
>>>>>> + BQ27541 = 6, /* bq27541, bq27542, bq27546, bq27742 */
>>>>>> + BQ27545 = 7, /* bq27545 */
>>>>>> + BQ27421 = 8, /* bq27421, bq27425, bq27441, bq27621 */
>>>>>> +
>>>>>> + /* members of categories; translate these to category in _setup() */
>>>>>> + BQ27520 = 101,
>>>>>> + BQ27531 = 102,
>>>>>> + BQ27542 = 103,
>>>>>> + BQ27546 = 104,
>>>>>> + BQ27742 = 105,
>>>>>> + BQ27425 = 106,
>>>>>> + BQ27441 = 107,
>>>>>> + BQ27621 = 108,
>>>>>
>>>>> Get rid of this, just add new chip enum names if you need support for
>>>>> new chips.
>>>>
>>>> How does a non-DT config obtain chip ID? We want explicit enum values
>>>> if they appear in external platform-data objects. I'll mention that in
>>>> the next patch description.
>>>>
>>>
>>> platform-data is going away, I'm not sure what you are saying here.
>>
>> Don't 1-wire users have a platform-data config? You plan to force them
>> to replace it with DT? I thought that wasn't kosher.
>>
>
> The 1-wire driver generates this platform-data, 1-wire is a discoverable
> bus, they never needed to define DT or platform data and still will not.
How does it map a discovered chip type to a bq27xxx_chip enum?
>>>> The category (original) IDs index bq27xxx_regs[], and you'll probably
>>>> extend that in time. So I placed the member (new) IDs well above the
>>>> categories to allow permanent explicit values.
>>>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
2017-03-16 21:47 ` Liam Breck
@ 2017-03-16 21:53 ` Andrew F. Davis
2017-03-16 22:38 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Andrew F. Davis @ 2017-03-16 21:53 UTC (permalink / raw)
To: Liam Breck; +Cc: Sebastian Reichel, linux-pm, Matt Ranostay, Liam Breck
On 03/16/2017 04:47 PM, Liam Breck wrote:
> On Thu, Mar 16, 2017 at 2:30 PM, Andrew F. Davis <afd@ti.com> wrote:
>> On 03/16/2017 04:26 PM, Liam Breck wrote:
>>> On Thu, Mar 16, 2017 at 1:50 PM, Andrew F. Davis <afd@ti.com> wrote:
>>>> On 03/16/2017 03:12 PM, Liam Breck wrote:
>>>>> On Thu, Mar 16, 2017 at 7:44 AM, Andrew F. Davis <afd@ti.com> wrote:
>>>>>> On 03/15/2017 02:26 PM, Liam Breck wrote:
>>>>>>> From: Liam Breck <kernel@networkimprov.net>
>>>>>>>
>>>>>>> Pass actual chip ID into _setup(), which translates it to a group ID,
>>>>>>> to allow support for all chips by the power_supply_battery_info code.
>>>>>>> There are no functional changes to the driver.
>>>>>>>
>>>>>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>>>>>> ---
>>>>>>
>>>>>> What is this patch based on, it doesn't apply to v4.11-rc1 for me.
>>>>>
>>>>> Sorry, I don't have all of Chris' patches here. It wasn't a factor
>>>>> until we attacked the register arrays. Could you send me his patchset
>>>>> with:
>>>>> git format-patch --stdout HEAD~x..HEAD~y > bq27xxx-lapa.mbox
>>>>>
>>>>
>>>> Who are you asking?
>>>
>>> You, if I may impose...
>>>
>>
>> Just rebase on v4.11-rc1...
>>
>>>>>>> drivers/power/supply/bq27xxx_battery.c | 19 +++++++++++++++++++
>>>>>>> drivers/power/supply/bq27xxx_battery_i2c.c | 16 ++++++++--------
>>>>>>> include/linux/power/bq27xxx_battery.h | 25 ++++++++++++++++++-------
>>>>>>> 3 files changed, 45 insertions(+), 15 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
>>>>>>> index 7272d1e..d613d3d 100644
>>>>>>> --- a/drivers/power/supply/bq27xxx_battery.c
>>>>>>> +++ b/drivers/power/supply/bq27xxx_battery.c
>>>>>>> @@ -1020,6 +1020,25 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>>>>>> struct power_supply_desc *psy_desc;
>>>>>>> struct power_supply_config psy_cfg = { .drv_data = di, };
>>>>>>>
>>>>>>> + switch(di->chip) {
>>>>>>> + case BQ27000:
>>>>>>> + case BQ27010:
>>>>>>> + case BQ27500:
>>>>>>> + case BQ27510:
>>>>>>> + case BQ27530:
>>>>>>> + case BQ27541:
>>>>>>> + case BQ27545:
>>>>>>> + case BQ27421: break;
>>>>>>
>>>>>> Why even have these cases then?
>>>>>
>>>>> You'll get a compiler warning if any are missing. Helps when adding new chips.
>>>>>
>>>>>>> + case BQ27520: di->chip = BQ27510; break;
>>>>>>> + case BQ27531: di->chip = BQ27530; break;
>>>>>>> + case BQ27542: di->chip = BQ27541; break;
>>>>>>> + case BQ27546: di->chip = BQ27541; break;
>>>>>>> + case BQ27742: di->chip = BQ27541; break;
>>>>>>> + case BQ27425: di->chip = BQ27421; break;
>>>>>>> + case BQ27441: di->chip = BQ27421; break;
>>>>>>> + case BQ27621: di->chip = BQ27421; break;
>>>>>>
>>>>>> Nope, don't like this at all, make a different variable, ->registers or
>>>>>> something to map to the register table. Plus I think changing the
>>>>>> variable you are switching on can cause undefined behavior.
>>>>>
>>>>> We had a different variable, .dmid, but you rejected a second ID
>>>>> field. I think this is better, as we eliminated the static arrays
>>>>> .dmid indexed. I didn't rename .chip to .category as that would cause
>>>>> trivial changes all over the file. I could do that in a final patch
>>>>> tho.
>>>>>
>>>>> You can modify a variable after switching on it, I promise.
>>>>>
>>>>>>> + }
>>>>>>> +
>>>>>>> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
>>>>>>> mutex_init(&di->lock);
>>>>>>> di->regs = bq27xxx_regs[di->chip];
>>>>>>> diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>>>> index 5c5c3a6..13def59 100644
>>>>>>> --- a/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>>>> +++ b/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>>>> @@ -150,18 +150,18 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
>>>>>>> { "bq27210", BQ27010 },
>>>>>>> { "bq27500", BQ27500 },
>>>>>>> { "bq27510", BQ27510 },
>>>>>>> - { "bq27520", BQ27510 },
>>>>>>> + { "bq27520", BQ27520 },
>>>>>>> { "bq27530", BQ27530 },
>>>>>>> - { "bq27531", BQ27530 },
>>>>>>> + { "bq27531", BQ27531 },
>>>>>>> { "bq27541", BQ27541 },
>>>>>>> - { "bq27542", BQ27541 },
>>>>>>> - { "bq27546", BQ27541 },
>>>>>>> - { "bq27742", BQ27541 },
>>>>>>> + { "bq27542", BQ27542 },
>>>>>>> + { "bq27546", BQ27546 },
>>>>>>> + { "bq27742", BQ27742 },
>>>>>>> { "bq27545", BQ27545 },
>>>>>>> { "bq27421", BQ27421 },
>>>>>>> - { "bq27425", BQ27421 },
>>>>>>> - { "bq27441", BQ27421 },
>>>>>>> - { "bq27621", BQ27421 },
>>>>>>> + { "bq27425", BQ27425 },
>>>>>>> + { "bq27441", BQ27441 },
>>>>>>> + { "bq27621", BQ27621 },
>>>>>>> {},
>>>>>>> };
>>>>>>> MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
>>>>>>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>>>>>>> index 92df553..90db1cf 100644
>>>>>>> --- a/include/linux/power/bq27xxx_battery.h
>>>>>>> +++ b/include/linux/power/bq27xxx_battery.h
>>>>>>> @@ -2,14 +2,25 @@
>>>>>>> #define __LINUX_BQ27X00_BATTERY_H__
>>>>>>>
>>>>>>> enum bq27xxx_chip {
>>>>>>> + /* categories; index for bq27xxx_regs[] */
>>>>>>> BQ27000 = 1, /* bq27000, bq27200 */
>>>>>>> - BQ27010, /* bq27010, bq27210 */
>>>>>>> - BQ27500, /* bq27500 */
>>>>>>> - BQ27510, /* bq27510, bq27520 */
>>>>>>> - BQ27530, /* bq27530, bq27531 */
>>>>>>> - BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
>>>>>>> - BQ27545, /* bq27545 */
>>>>>>> - BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
>>>>>>> + BQ27010 = 2, /* bq27010, bq27210 */
>>>>>>> + BQ27500 = 3, /* bq27500 */
>>>>>>> + BQ27510 = 4, /* bq27510, bq27520 */
>>>>>>> + BQ27530 = 5, /* bq27530, bq27531 */
>>>>>>> + BQ27541 = 6, /* bq27541, bq27542, bq27546, bq27742 */
>>>>>>> + BQ27545 = 7, /* bq27545 */
>>>>>>> + BQ27421 = 8, /* bq27421, bq27425, bq27441, bq27621 */
>>>>>>> +
>>>>>>> + /* members of categories; translate these to category in _setup() */
>>>>>>> + BQ27520 = 101,
>>>>>>> + BQ27531 = 102,
>>>>>>> + BQ27542 = 103,
>>>>>>> + BQ27546 = 104,
>>>>>>> + BQ27742 = 105,
>>>>>>> + BQ27425 = 106,
>>>>>>> + BQ27441 = 107,
>>>>>>> + BQ27621 = 108,
>>>>>>
>>>>>> Get rid of this, just add new chip enum names if you need support for
>>>>>> new chips.
>>>>>
>>>>> How does a non-DT config obtain chip ID? We want explicit enum values
>>>>> if they appear in external platform-data objects. I'll mention that in
>>>>> the next patch description.
>>>>>
>>>>
>>>> platform-data is going away, I'm not sure what you are saying here.
>>>
>>> Don't 1-wire users have a platform-data config? You plan to force them
>>> to replace it with DT? I thought that wasn't kosher.
>>>
>>
>> The 1-wire driver generates this platform-data, 1-wire is a discoverable
>> bus, they never needed to define DT or platform data and still will not.
>
> How does it map a discovered chip type to a bq27xxx_chip enum?
>
Right now it just assumes the chip is a BQ27000, see line 45 of
drivers/w1/slaves/w1_bq27000.c
>>>>> The category (original) IDs index bq27xxx_regs[], and you'll probably
>>>>> extend that in time. So I placed the member (new) IDs well above the
>>>>> categories to allow permanent explicit values.
>>>>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support
2017-03-16 21:39 ` Andrew F. Davis
@ 2017-03-16 22:31 ` Liam Breck
0 siblings, 0 replies; 35+ messages in thread
From: Liam Breck @ 2017-03-16 22:31 UTC (permalink / raw)
To: Andrew F. Davis; +Cc: Sebastian Reichel, linux-pm, Liam Breck
On Thu, Mar 16, 2017 at 2:39 PM, Andrew F. Davis <afd@ti.com> wrote:
> On 03/16/2017 04:12 PM, Liam Breck wrote:
>> On Thu, Mar 16, 2017 at 8:00 AM, Andrew F. Davis <afd@ti.com> wrote:
>>> On 03/15/2017 02:26 PM, Liam Breck wrote:
>>>> From: Liam Breck <kernel@networkimprov.net>
>>>>
>>>> Previously there was no way to configure chip registers in the event that the
>>>> defaults didn't match the battery in question.
>>>>
>>>> BQ27xxx driver now calls power_supply_get_battery_info, checks the inputs,
>>>> and writes battery data to chip RAM or non-volatile memory.
>>>>
>>>> Supports chips BQ27500, 545, 421, 425, 441, 621. Others may be added.
>>>>
>>>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>>> ---
>>>> drivers/power/supply/bq27xxx_battery.c | 478 ++++++++++++++++++++++++++++++++-
>>>> include/linux/power/bq27xxx_battery.h | 2 +
>>>> 2 files changed, 468 insertions(+), 12 deletions(-)
>>>>
>>>> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
>>>> index d613d3d..fb062db 100644
>>>> --- a/drivers/power/supply/bq27xxx_battery.c
>>>> +++ b/drivers/power/supply/bq27xxx_battery.c
>>>> @@ -51,7 +51,7 @@
>>>>
>>>> #include <linux/power/bq27xxx_battery.h>
>>>>
>>>> -#define DRIVER_VERSION "1.2.0"
>>>> +#define DRIVER_VERSION "1.3.0"
>>>>
>>>> #define BQ27XXX_MANUFACTURER "Texas Instruments"
>>>>
>>>> @@ -59,6 +59,7 @@
>>>> #define BQ27XXX_FLAG_DSC BIT(0)
>>>> #define BQ27XXX_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
>>>> #define BQ27XXX_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
>>>> +#define BQ27XXX_FLAG_CFGUP BIT(4)
>>>> #define BQ27XXX_FLAG_FC BIT(9)
>>>> #define BQ27XXX_FLAG_OTD BIT(14)
>>>> #define BQ27XXX_FLAG_OTC BIT(15)
>>>> @@ -72,6 +73,11 @@
>>>> #define BQ27000_FLAG_FC BIT(5)
>>>> #define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
>>>>
>>>> +/* control register params */
>>>> +#define BQ27XXX_SEALED 0x20
>>>> +#define BQ27XXX_SET_CFGUPDATE 0x13
>>>> +#define BQ27XXX_SOFT_RESET 0x42
>>>> +
>>>> #define BQ27XXX_RS (20) /* Resistor sense mOhm */
>>>> #define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */
>>>> #define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */
>>>> @@ -102,6 +108,11 @@ enum bq27xxx_reg_index {
>>>> BQ27XXX_REG_SOC, /* State-of-Charge */
>>>> BQ27XXX_REG_DCAP, /* Design Capacity */
>>>> BQ27XXX_REG_AP, /* Average Power */
>>>> + BQ27XXX_DM_CTRL, /* BlockDataControl() */
>>>> + BQ27XXX_DM_CLASS, /* DataClass() */
>>>> + BQ27XXX_DM_BLOCK, /* DataBlock() */
>>>> + BQ27XXX_DM_DATA, /* BlockData() */
>>>> + BQ27XXX_DM_CKSUM, /* BlockDataChecksum() */
>>>> BQ27XXX_REG_MAX, /* sentinel */
>>>> };
>>>>
>>>> @@ -125,6 +136,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>>> [BQ27XXX_REG_SOC] = 0x0b,
>>>> [BQ27XXX_REG_DCAP] = 0x76,
>>>> [BQ27XXX_REG_AP] = 0x24,
>>>> + [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_DATA] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR,
>>>> },
>>>> [BQ27010] = {
>>>> [BQ27XXX_REG_CTRL] = 0x00,
>>>> @@ -144,6 +160,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>>> [BQ27XXX_REG_SOC] = 0x0b,
>>>> [BQ27XXX_REG_DCAP] = 0x76,
>>>> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_DATA] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR,
>>>> },
>>>> [BQ27500] = {
>>>> [BQ27XXX_REG_CTRL] = 0x00,
>>>> @@ -163,6 +184,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>>> [BQ27XXX_REG_SOC] = 0x2c,
>>>> [BQ27XXX_REG_DCAP] = 0x3c,
>>>> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>>> + [BQ27XXX_DM_DATA] = 0x40,
>>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>>> },
>>>> [BQ27510] = {
>>>> [BQ27XXX_REG_CTRL] = 0x00,
>>>> @@ -182,6 +208,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>>> [BQ27XXX_REG_SOC] = 0x20,
>>>> [BQ27XXX_REG_DCAP] = 0x2e,
>>>> [BQ27XXX_REG_AP] = INVALID_REG_ADDR,
>>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>>> + [BQ27XXX_DM_DATA] = 0x40,
>>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>>> },
>>>> [BQ27530] = {
>>>> [BQ27XXX_REG_CTRL] = 0x00,
>>>> @@ -201,6 +232,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>>> [BQ27XXX_REG_SOC] = 0x2c,
>>>> [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
>>>> [BQ27XXX_REG_AP] = 0x24,
>>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>>> + [BQ27XXX_DM_DATA] = 0x40,
>>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>>> },
>>>> [BQ27541] = {
>>>> [BQ27XXX_REG_CTRL] = 0x00,
>>>> @@ -220,6 +256,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>>> [BQ27XXX_REG_SOC] = 0x2c,
>>>> [BQ27XXX_REG_DCAP] = 0x3c,
>>>> [BQ27XXX_REG_AP] = 0x24,
>>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>>> + [BQ27XXX_DM_DATA] = 0x40,
>>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>>> },
>>>> [BQ27545] = {
>>>> [BQ27XXX_REG_CTRL] = 0x00,
>>>> @@ -239,6 +280,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>>> [BQ27XXX_REG_SOC] = 0x2c,
>>>> [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
>>>> [BQ27XXX_REG_AP] = 0x24,
>>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>>> + [BQ27XXX_DM_DATA] = 0x40,
>>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>>> },
>>>> [BQ27421] = {
>>>> [BQ27XXX_REG_CTRL] = 0x00,
>>>> @@ -258,6 +304,11 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
>>>> [BQ27XXX_REG_SOC] = 0x1c,
>>>> [BQ27XXX_REG_DCAP] = 0x3c,
>>>> [BQ27XXX_REG_AP] = 0x18,
>>>> + [BQ27XXX_DM_CTRL] = 0x61,
>>>> + [BQ27XXX_DM_CLASS] = 0x3e,
>>>> + [BQ27XXX_DM_BLOCK] = 0x3f,
>>>> + [BQ27XXX_DM_DATA] = 0x40,
>>>> + [BQ27XXX_DM_CKSUM] = 0x60,
>>>> },
>>>> };
>>>>
>>>> @@ -432,6 +483,82 @@ static struct {
>>>> static DEFINE_MUTEX(bq27xxx_list_lock);
>>>> static LIST_HEAD(bq27xxx_battery_devices);
>>>>
>>>> +#define BQ27XXX_DM_SZ 32
>>>> +
>>>> +#define BQ27XXX_MSLEEP(i) usleep_range((i)*1000, (i)*1000+500)
>>>> +
>>>> +struct bq27xxx_dm_reg {
>>>> + u8 subclass_id;
>>>> + u8 offset;
>>>> + u8 bytes;
>>>> + u16 min, max;
>>>> +};
>>>> +
>>>> +struct bq27xxx_dm_buf {
>>>> + u8 class;
>>>> + u8 block;
>>>> + u8 a[BQ27XXX_DM_SZ];
>>>> + bool full, updt;
>>>> +};
>>>> +
>>>> +#define BQ27XXX_DM_BUF(di, i) { \
>>>> + .class = (di)->dm_regs[i].subclass_id, \
>>>> + .block = (di)->dm_regs[i].offset / BQ27XXX_DM_SZ, \
>>>> +}
>>>> +
>>>> +static inline u16* bq27xxx_dm_reg_ptr(struct bq27xxx_dm_buf *buf,
>>>> + struct bq27xxx_dm_reg *reg)
>>>> +{
>>>> + if (buf->class == reg->subclass_id
>>>> + && buf->block == reg->offset / BQ27XXX_DM_SZ)
>>>> + return (u16*) (buf->a + reg->offset % BQ27XXX_DM_SZ);
>>>> +
>>>> + return NULL;
>>>> +}
>>>> +
>>>> +enum bq27xxx_dm_reg_id {
>>>> + BQ27XXX_DM_DESIGN_CAPACITY = 0,
>>>> + BQ27XXX_DM_DESIGN_ENERGY,
>>>> + BQ27XXX_DM_TERMINATE_VOLTAGE,
>>>> +};
>>>> +
>>>> +static const char* bq27xxx_dm_reg_name[] = {
>>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = "design-capacity",
>>>> + [BQ27XXX_DM_DESIGN_ENERGY] = "design-energy",
>>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = "terminate-voltage",
>>>> +};
>>>> +
>>>> +static struct bq27xxx_dm_reg bq27500_dm_regs[] = {
>>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 10, 2, 0, 65535 },
>>>> + [BQ27XXX_DM_DESIGN_ENERGY] = { }, /* missing on chip */
>>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 48, 2, 1000, 32767 },
>>>> +};
>>>> +
>>>> +static struct bq27xxx_dm_reg bq27545_dm_regs[] = {
>>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 23, 2, 0, 32767 },
>>>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 48, 25, 2, 0, 32767 },
>>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 67, 2, 2800, 3700 },
>>>> +};
>>>> +
>>>> +static struct bq27xxx_dm_reg bq27421_dm_regs[] = {
>>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 8000 },
>>>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 },
>>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 16, 2, 2500, 3700 },
>>>> +};
>>>> +
>>>> +static struct bq27xxx_dm_reg bq27425_dm_regs[] = {
>>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 12, 2, 0, 32767 },
>>>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 14, 2, 0, 32767 },
>>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 18, 2, 2800, 3700 },
>>>> +};
>>>> +
>>>> +static struct bq27xxx_dm_reg bq27621_dm_regs[] = {
>>>> + [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 3, 2, 0, 8000 },
>>>> + [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 5, 2, 0, 32767 },
>>>> + [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 9, 2, 2500, 3700 },
>>>> +};
>>>> +
>>>> +
>>>> static int poll_interval_param_set(const char *val, const struct kernel_param *kp)
>>>> {
>>>> struct bq27xxx_device_info *di;
>>>> @@ -476,6 +603,317 @@ static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index,
>>>> return di->bus.read(di, di->regs[reg_index], single);
>>>> }
>>>>
>>>> +static int bq27xxx_battery_set_seal_state(struct bq27xxx_device_info *di,
>>>> + bool state)
>>>> +{
>>>> + int ret;
>>>> +
>>>> + if (state) {
>>>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], BQ27XXX_SEALED, false);
>>>
>>>
>>> Look at how reads are done, we have a function bq27xxx_read() that
>>> checks the register and handles the access methods. Do something like
>>> that for write, then replace all these with that, "bus" should only be
>>> accessed in that function.
>>
>> OK. And for bus.{read,write}_bulk() too? They only occur once.
>>
>
> Sure, why not
OK
>>>> + if (ret < 0)
>>>> + goto out;
>>>> + } else {
>>>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], (u16)(di->unseal_key >> 16), false);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL], (u16)di->unseal_key, false);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> + }
>>>
>>> +space
Where?
>>> Has this been run through checkpatch?
>
> Well...
I defer newline formatting if things are in-flux.
>>>> + return 0;
>>>> +
>>>> +out:
>>>> + dev_err(di->dev, "bus error on %s: %d\n", state ? "seal" : "unseal", ret);
>>>> + return ret;
>>>> +}
>>>> +
>>>> +static u8 bq27xxx_battery_checksum_dm_block(struct bq27xxx_dm_buf *buf)
>>>> +{
>>>> + u16 sum = 0;
>>>> + int i;
>>>> +
>>>> + for (i = 0; i < BQ27XXX_DM_SZ; i++)
>>>> + sum += buf->a[i];
>>>> + sum &= 0xff;
>>>> +
>>>> + return 0xff - sum;
>>>> +}
>>>> +
>>>> +static int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di,
>>>> + struct bq27xxx_dm_buf *buf)
>>>> +{
>>>> + int ret;
>>>> +
>>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CLASS], buf->class, true);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_BLOCK], buf->block, true);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + BQ27XXX_MSLEEP(1);
>>>> +
>>>> + ret = di->bus.read_bulk(di, di->regs[BQ27XXX_DM_DATA], buf->a, BQ27XXX_DM_SZ);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + ret = di->bus.read(di, di->regs[BQ27XXX_DM_CKSUM], true);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + if ((u8)ret != bq27xxx_battery_checksum_dm_block(buf)) {
>>>> + ret = -EINVAL;
>>>> + goto out;
>>>> + }
>>>> +
>>>> + buf->full = true;
>>>> + buf->updt = false;
>>>> + return 0;
>>>> +
>>>> +out:
>>>> + dev_err(di->dev, "bus error reading chip memory: %d\n", ret);
>>>
>>> Instead of this catch-all, each spot should have an error message that
>>> explains what failed. If they all end up with this generic message we
>>> cannot possibly diagnose issues for people.
>>
>> Knowing which bus op failed doesn't help.
>
> Sure it does, knowing which step it fails or locks the chip is useful.
The chips do not check/reject register inputs. If the bus hw or chip
are flaky, any step may fail. Knowing which won't diagnose anything.
If there's a bug in the bus driver, you need print stmts elsewhere.
>> Any error means either the
>> bus hw failed or chip died. If we're debugging a new chip, we'll need
>> extra print statements anyway.
>>
>>>> + return ret;
>>>> +}
>>>> +
>>>> +static void bq27xxx_battery_update_dm_block(struct bq27xxx_device_info *di,
>>>> + struct bq27xxx_dm_buf *buf,
>>>> + enum bq27xxx_dm_reg_id reg_id,
>>>> + unsigned int val)
>>>> +{
>>>> + struct bq27xxx_dm_reg *reg = &di->dm_regs[reg_id];
>>>> + const char* str = bq27xxx_dm_reg_name[reg_id];
>>>> + u16 *prev = bq27xxx_dm_reg_ptr(buf, reg);
>>>> +
>>>> + if (prev == NULL) {
>>>> + dev_warn(di->dev, "buffer does not match %s dm spec\n", str);
>>>> + return;
>>>> + }
>>>> +
>>>> + if (reg->bytes != 2) {
>>>> + dev_warn(di->dev, "%s dm spec has unsupported byte size\n", str);
>>>> + return;
>>>> + }
>>>> +
>>>> + if (!buf->full)
>>>> + return;
>>>> +
>>>> + if (be16_to_cpup(prev) == val) {
>>>> + dev_info(di->dev, "%s has %u\n", str, val);
>>>> + return;
>>>> + }
>>>> +
>>>> + dev_info(di->dev, "update %s to %u\n", str, val);
>>>> +
>>>> + *prev = cpu_to_be16(val);
>>>> + buf->updt = true;
>>>> +}
>>>> +
>>>> +static int bq27xxx_battery_set_cfgupdate(struct bq27xxx_device_info *di,
>>>> + bool state)
>>>
>>> Why only two states? why bool? you should probably be passing in the
>>> value, if you really want to do this as a state, then the states should
>>> have an enum for each state.
>>
>> You can enter or exit cfgupdate mode. We do the same for
>> set_seal_state(). And bq27xxx_read() takes a bool arg to indicate one
>> or two bytes.
>>
>
> bq27xxx_read() has the arg as a question, "Is this a two byte read?
> (true/false)", yours is "What state would you like to set?
> (true/false)", see how one doesn't work, fix that.
This? set_cfgupdate(struct bq27xxx_device_info *di, bool updt)
>>>> +{
>>>> + int ret, try=100;
>>>> +
>>>> + ret = di->bus.write(di, di->regs[BQ27XXX_REG_CTRL],
>>>> + state ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET,
>>>> + false);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + do {
>>>> + BQ27XXX_MSLEEP(25);
>>>> + ret = di->bus.read(di, di->regs[BQ27XXX_REG_FLAGS], false);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> + } while (!(ret & BQ27XXX_FLAG_CFGUP) == state && --try);
>>>> +
>>>> + if (!try) {
>>>> + dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", state);
>>>> + return -EINVAL;
>>>> + }
>>>
>>> Put this check inside the loop.
>>
>> We test try inside the loop. This test is only relevant after the loop.
>>
>
> It is not, try to think what I'm saying, if you move the test inside,
> then we don't have to test as part of the while, and we don't have to
> test after.
We have to test flag before try, so this would duplicate the flag
test. Duplicating the try test is simpler.
>>>> +
>>>> + if (100-try > 3)
>>>
>>> Why 3? lets also count up to a set value, 100 is a magic number, if I
>>> change try to =200, I have to change it down here, that is going to be
>>> buggy.
>>
>> OK. 3 because 75ms is a long time.
>>
>
> says who?
I intend it to succeed after the first sleep. If it doesn't we should
warn at some level. 2, 3, 4, 10, 42?
>>>> + dev_warn(di->dev, "cfgupdate %d, retries %d\n", state, 100-try);
>>>> +
>>>> + return 0;
>>>> +
>>>> +out:
>>>> + dev_err(di->dev, "bus error on %s: %d\n", state ? "set_cfgupdate" : "soft_reset", ret);
>>>> + return ret;
>>>> +}
>>>> +
>>>> +static int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di,
>>>> + struct bq27xxx_dm_buf *buf)
>>>> +{
>>>> + bool cfgup = di->chip == BQ27421; /* assume group supports cfgupdate */
>>>> + int ret;
>>>> +
>>>> + if (!buf->updt)
>>>> + return 0;
>>>> +
>>>> + if (cfgup) {
>>>> + ret = bq27xxx_battery_set_cfgupdate(di, true);
>>>> + if (ret < 0)
>>>> + return ret;
>>>> + }
>>>> +
>>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CTRL], 0, true);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CLASS], buf->class, true);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_BLOCK], buf->block, true);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + BQ27XXX_MSLEEP(1);
>>>> +
>>>> + ret = di->bus.write_bulk(di, di->regs[BQ27XXX_DM_DATA], buf->a, BQ27XXX_DM_SZ);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + ret = di->bus.write(di, di->regs[BQ27XXX_DM_CKSUM],
>>>> + bq27xxx_battery_checksum_dm_block(buf), true);
>>>> + if (ret < 0)
>>>> + goto out;
>>>> +
>>>> + /* THE FOLLOWING SEQUENCE IS TOXIC. DO NOT USE!
>>>> + * If the 'time' delay is insufficient, NVM corruption results on
>>>> + * the '425 chip (and perhaps others), which could damage the chip.
>>>> + * It was suggested in this TI tool:
>>>> + * http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328
>>>> + *
>>>> + * 1. MSLEEP(time) after above write(BQ27XXX_DM_CKSUM, ...)
>>>> + * 2. write(BQ27XXX_DM_BLOCK, buf->block)
>>>> + * 3. sum = read(BQ27XXX_DM_CKSUM)
>>>> + * 4. if (sum != bq27xxx_battery_checksum_dm_block(buf))
>>>> + * report error
>>>> + */
>>>> +
>>>> + if (cfgup) {
>>>> + BQ27XXX_MSLEEP(1);
>>>> + ret = bq27xxx_battery_set_cfgupdate(di, false);
>>>> + if (ret < 0)
>>>> + return ret;
>>>> + } else {
>>>> + /* flash DM updates in <100ms, but reset time isn't documented */
>>>> + BQ27XXX_MSLEEP(400);
>>>> + }
>>>> +
>>>> + buf->updt = false;
>>>> + return 0;
>>>> +
>>>> +out:
>>>> + if (cfgup)
>>>> + bq27xxx_battery_set_cfgupdate(di, false);
>>>> +
>>>> + dev_err(di->dev, "bus error writing chip memory: %d\n", ret);
>>>> + return ret;
>>>> +}
>>>> +
>>>> +static void bq27xxx_battery_set_config(struct bq27xxx_device_info *di,
>>>> + struct power_supply_battery_info *info)
>>>> +{
>>>> + struct bq27xxx_dm_buf bd = BQ27XXX_DM_BUF(di, BQ27XXX_DM_DESIGN_CAPACITY);
>>>> + struct bq27xxx_dm_buf bt = BQ27XXX_DM_BUF(di, BQ27XXX_DM_TERMINATE_VOLTAGE);
>>>> +
>>>> + if (info->charge_full_design_uah != -EINVAL
>>>> + && info->energy_full_design_uwh != -EINVAL) {
>>>> + bq27xxx_battery_read_dm_block(di, &bd);
>>>> + /* assume design energy & capacity are in same block */
>>>> + bq27xxx_battery_update_dm_block(di, &bd,
>>>> + BQ27XXX_DM_DESIGN_CAPACITY,
>>>> + info->charge_full_design_uah / 1000);
>>>> + bq27xxx_battery_update_dm_block(di, &bd,
>>>> + BQ27XXX_DM_DESIGN_ENERGY,
>>>> + info->energy_full_design_uwh / 1000);
>>>> + }
>>>> +
>>>> + if (info->voltage_min_design_uv != -EINVAL) {
>>>> + bool same = bd.class == bt.class && bd.block == bt.block;
>>>> + if (!same)
>>>> + bq27xxx_battery_read_dm_block(di, &bt);
>>>> + bq27xxx_battery_update_dm_block(di, same ? &bd : &bt,
>>>> + BQ27XXX_DM_TERMINATE_VOLTAGE,
>>>> + info->voltage_min_design_uv / 1000);
>>>> + }
>>>> +
>>>> + bq27xxx_battery_write_dm_block(di, &bd);
>>>> + bq27xxx_battery_write_dm_block(di, &bt);
>>>> +}
>>>> +
>>>> +void bq27xxx_battery_settings(struct bq27xxx_device_info *di)
>>>> +{
>>>> + struct power_supply_battery_info info = {};
>>>> + unsigned int min, max;
>>>> +
>>>> + /* functions don't exist for writing data so abort */
>>>> + if (!di->bus.write || !di->bus.write_bulk)
>>>> + return;
>>>> +
>>>> + /* no settings to be set for this chipset so abort */
>>>> + if (!di->dm_regs)
>>>> + return;
>>>> +
>>>> + if (bq27xxx_battery_set_seal_state(di, false) < 0)
>>>> + return;
>>>> +
>>>> + if (power_supply_get_battery_info(di->bat, &info) < 0)
>>>> + goto out;
>>>> +
>>>> + if (info.energy_full_design_uwh != info.charge_full_design_uah) {
>>>> + if (info.energy_full_design_uwh == -EINVAL)
>>>> + dev_warn(di->dev,
>>>> + "missing battery:energy-full-design-microwatt-hours\n");
>>>> + else if (info.charge_full_design_uah == -EINVAL)
>>>> + dev_warn(di->dev,
>>>> + "missing battery:charge-full-design-microamp-hours\n");
>>>> + }
>>>> +
>>>> + /* assume min == 0 */
>>>> + max = di->dm_regs[BQ27XXX_DM_DESIGN_ENERGY].max;
>>>> + if (info.energy_full_design_uwh > max * 1000) {
>>>> + dev_err(di->dev,
>>>> + "invalid battery:energy-full-design-microwatt-hours %d\n",
>>>> + info.energy_full_design_uwh);
>>>> + info.energy_full_design_uwh = -EINVAL;
>>>> + }
>>>> +
>>>> + /* assume min == 0 */
>>>> + max = di->dm_regs[BQ27XXX_DM_DESIGN_CAPACITY].max;
>>>> + if (info.charge_full_design_uah > max * 1000) {
>>>> + dev_err(di->dev,
>>>> + "invalid battery:charge-full-design-microamp-hours %d\n",
>>>> + info.charge_full_design_uah);
>>>> + info.charge_full_design_uah = -EINVAL;
>>>> + }
>>>> +
>>>> + min = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].min;
>>>> + max = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].max;
>>>> + if ((info.voltage_min_design_uv < min * 1000
>>>> + || info.voltage_min_design_uv > max * 1000)
>>>> + && info.voltage_min_design_uv != -EINVAL) {
>>>> + dev_err(di->dev,
>>>> + "invalid battery:voltage-min-design-microvolt %d\n",
>>>> + info.voltage_min_design_uv);
>>>> + info.voltage_min_design_uv = -EINVAL;
>>>> + }
>>>> +
>>>> + if ((info.energy_full_design_uwh == -EINVAL
>>>> + || info.charge_full_design_uah == -EINVAL)
>>>> + && info.voltage_min_design_uv == -EINVAL)
>>>> + goto out;
>>>> +
>>>> + bq27xxx_battery_set_config(di, &info);
>>>> +
>>>> +out:
>>>> + bq27xxx_battery_set_seal_state(di, true);
>>>
>>> Don't use goto unless you have to, this is not such a case.
>>
>> OK.
>>
>>>> +}
>>>> +
>>>> /*
>>>> * Return the battery State-of-Charge
>>>> * Or < 0 if something fails.
>>>> @@ -985,6 +1423,13 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
>>>> case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
>>>> ret = bq27xxx_simple_value(di->charge_design_full, val);
>>>> break;
>>>> + /*
>>>> + * TODO: Implement these to make registers set from
>>>> + * power_supply_battery_info visible in sysfs.
>>>> + */
>>>> + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
>>>> + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
>>>> + return -EINVAL;
>>>> case POWER_SUPPLY_PROP_CYCLE_COUNT:
>>>> ret = bq27xxx_simple_value(di->cache.cycle_count, val);
>>>> break;
>>>> @@ -1015,28 +1460,36 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
>>>> schedule_delayed_work(&di->work, 0);
>>>> }
>>>>
>>>> +#define BQ27XXX_INIT(c,d,k) \
>>>> + di->chip = (c); \
>>>> + di->dm_regs = (d); \
>>>> + di->unseal_key = (k)
>>>> +
>>>> int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>>> {
>>>> struct power_supply_desc *psy_desc;
>>>> - struct power_supply_config psy_cfg = { .drv_data = di, };
>>>> + struct power_supply_config psy_cfg = {
>>>> + .of_node = di->dev->of_node,
>>>> + .drv_data = di,
>>>> + };
>>>>
>>>> switch(di->chip) {
>>>> case BQ27000:
>>>> - case BQ27010:
>>>> - case BQ27500:
>>>> - case BQ27510:
>>>> - case BQ27530:
>>>> - case BQ27541:
>>>> - case BQ27545:
>>>> - case BQ27421: break;
>>>> + case BQ27010: break;
>>>> + case BQ27500: BQ27XXX_INIT(BQ27500, bq27500_dm_regs, 0x04143672); break;
>>>> + case BQ27510: break;
>>>> + case BQ27530: break;
>>>> + case BQ27541: break;
>>>> + case BQ27545: BQ27XXX_INIT(BQ27545, bq27545_dm_regs, 0x04143672); break;
>>>> + case BQ27421: BQ27XXX_INIT(BQ27421, bq27421_dm_regs, 0x80008000); break;
>>>> case BQ27520: di->chip = BQ27510; break;
>>>> case BQ27531: di->chip = BQ27530; break;
>>>> case BQ27542: di->chip = BQ27541; break;
>>>> case BQ27546: di->chip = BQ27541; break;
>>>> case BQ27742: di->chip = BQ27541; break;
>>>> - case BQ27425: di->chip = BQ27421; break;
>>>> - case BQ27441: di->chip = BQ27421; break;
>>>> - case BQ27621: di->chip = BQ27421; break;
>>>> + case BQ27425: BQ27XXX_INIT(BQ27421, bq27425_dm_regs, 0x04143672); break;
>>>> + case BQ27441: BQ27XXX_INIT(BQ27421, bq27421_dm_regs, 0x80008000); break;
>>>> + case BQ27621: BQ27XXX_INIT(BQ27421, bq27621_dm_regs, 0x80008000); break;
>>>> }
>>>>
>>>> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
>>>> @@ -1062,6 +1515,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>>>
>>>> dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
>>>>
>>>> + bq27xxx_battery_settings(di);
>>>> bq27xxx_battery_update(di);
>>>>
>>>> mutex_lock(&bq27xxx_list_lock);
>>>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>>>> index 90db1cf..dbf1ab9 100644
>>>> --- a/include/linux/power/bq27xxx_battery.h
>>>> +++ b/include/linux/power/bq27xxx_battery.h
>>>> @@ -67,6 +67,8 @@ struct bq27xxx_device_info {
>>>> int id;
>>>> enum bq27xxx_chip chip;
>>>> const char *name;
>>>> + struct bq27xxx_dm_reg *dm_regs;
>>>> + u32 unseal_key;
>>>> struct bq27xxx_access_methods bus;
>>>> struct bq27xxx_reg_cache cache;
>>>> int charge_design_full;
>>>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
2017-03-16 21:53 ` Andrew F. Davis
@ 2017-03-16 22:38 ` Liam Breck
0 siblings, 0 replies; 35+ messages in thread
From: Liam Breck @ 2017-03-16 22:38 UTC (permalink / raw)
To: Andrew F. Davis; +Cc: Sebastian Reichel, linux-pm, Liam Breck
On Thu, Mar 16, 2017 at 2:53 PM, Andrew F. Davis <afd@ti.com> wrote:
> On 03/16/2017 04:47 PM, Liam Breck wrote:
>> On Thu, Mar 16, 2017 at 2:30 PM, Andrew F. Davis <afd@ti.com> wrote:
>>> On 03/16/2017 04:26 PM, Liam Breck wrote:
>>>> On Thu, Mar 16, 2017 at 1:50 PM, Andrew F. Davis <afd@ti.com> wrote:
>>>>> On 03/16/2017 03:12 PM, Liam Breck wrote:
>>>>>> On Thu, Mar 16, 2017 at 7:44 AM, Andrew F. Davis <afd@ti.com> wrote:
>>>>>>> On 03/15/2017 02:26 PM, Liam Breck wrote:
>>>>>>>> From: Liam Breck <kernel@networkimprov.net>
>>>>>>>>
>>>>>>>> Pass actual chip ID into _setup(), which translates it to a group ID,
>>>>>>>> to allow support for all chips by the power_supply_battery_info code.
>>>>>>>> There are no functional changes to the driver.
>>>>>>>>
>>>>>>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>>>>>>> ---
>>>>>>>
>>>>>>> What is this patch based on, it doesn't apply to v4.11-rc1 for me.
>>>>>>
>>>>>> Sorry, I don't have all of Chris' patches here. It wasn't a factor
>>>>>> until we attacked the register arrays. Could you send me his patchset
>>>>>> with:
>>>>>> git format-patch --stdout HEAD~x..HEAD~y > bq27xxx-lapa.mbox
>>>>>>
>>>>>
>>>>> Who are you asking?
>>>>
>>>> You, if I may impose...
>>>>
>>>
>>> Just rebase on v4.11-rc1...
>>>
>>>>>>>> drivers/power/supply/bq27xxx_battery.c | 19 +++++++++++++++++++
>>>>>>>> drivers/power/supply/bq27xxx_battery_i2c.c | 16 ++++++++--------
>>>>>>>> include/linux/power/bq27xxx_battery.h | 25 ++++++++++++++++++-------
>>>>>>>> 3 files changed, 45 insertions(+), 15 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
>>>>>>>> index 7272d1e..d613d3d 100644
>>>>>>>> --- a/drivers/power/supply/bq27xxx_battery.c
>>>>>>>> +++ b/drivers/power/supply/bq27xxx_battery.c
>>>>>>>> @@ -1020,6 +1020,25 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
>>>>>>>> struct power_supply_desc *psy_desc;
>>>>>>>> struct power_supply_config psy_cfg = { .drv_data = di, };
>>>>>>>>
>>>>>>>> + switch(di->chip) {
>>>>>>>> + case BQ27000:
>>>>>>>> + case BQ27010:
>>>>>>>> + case BQ27500:
>>>>>>>> + case BQ27510:
>>>>>>>> + case BQ27530:
>>>>>>>> + case BQ27541:
>>>>>>>> + case BQ27545:
>>>>>>>> + case BQ27421: break;
>>>>>>>
>>>>>>> Why even have these cases then?
>>>>>>
>>>>>> You'll get a compiler warning if any are missing. Helps when adding new chips.
>>>>>>
>>>>>>>> + case BQ27520: di->chip = BQ27510; break;
>>>>>>>> + case BQ27531: di->chip = BQ27530; break;
>>>>>>>> + case BQ27542: di->chip = BQ27541; break;
>>>>>>>> + case BQ27546: di->chip = BQ27541; break;
>>>>>>>> + case BQ27742: di->chip = BQ27541; break;
>>>>>>>> + case BQ27425: di->chip = BQ27421; break;
>>>>>>>> + case BQ27441: di->chip = BQ27421; break;
>>>>>>>> + case BQ27621: di->chip = BQ27421; break;
>>>>>>>
>>>>>>> Nope, don't like this at all, make a different variable, ->registers or
>>>>>>> something to map to the register table. Plus I think changing the
>>>>>>> variable you are switching on can cause undefined behavior.
>>>>>>
>>>>>> We had a different variable, .dmid, but you rejected a second ID
>>>>>> field. I think this is better, as we eliminated the static arrays
>>>>>> .dmid indexed. I didn't rename .chip to .category as that would cause
>>>>>> trivial changes all over the file. I could do that in a final patch
>>>>>> tho.
>>>>>>
>>>>>> You can modify a variable after switching on it, I promise.
>>>>>>
>>>>>>>> + }
>>>>>>>> +
>>>>>>>> INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
>>>>>>>> mutex_init(&di->lock);
>>>>>>>> di->regs = bq27xxx_regs[di->chip];
>>>>>>>> diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>>>>> index 5c5c3a6..13def59 100644
>>>>>>>> --- a/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>>>>> +++ b/drivers/power/supply/bq27xxx_battery_i2c.c
>>>>>>>> @@ -150,18 +150,18 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
>>>>>>>> { "bq27210", BQ27010 },
>>>>>>>> { "bq27500", BQ27500 },
>>>>>>>> { "bq27510", BQ27510 },
>>>>>>>> - { "bq27520", BQ27510 },
>>>>>>>> + { "bq27520", BQ27520 },
>>>>>>>> { "bq27530", BQ27530 },
>>>>>>>> - { "bq27531", BQ27530 },
>>>>>>>> + { "bq27531", BQ27531 },
>>>>>>>> { "bq27541", BQ27541 },
>>>>>>>> - { "bq27542", BQ27541 },
>>>>>>>> - { "bq27546", BQ27541 },
>>>>>>>> - { "bq27742", BQ27541 },
>>>>>>>> + { "bq27542", BQ27542 },
>>>>>>>> + { "bq27546", BQ27546 },
>>>>>>>> + { "bq27742", BQ27742 },
>>>>>>>> { "bq27545", BQ27545 },
>>>>>>>> { "bq27421", BQ27421 },
>>>>>>>> - { "bq27425", BQ27421 },
>>>>>>>> - { "bq27441", BQ27421 },
>>>>>>>> - { "bq27621", BQ27421 },
>>>>>>>> + { "bq27425", BQ27425 },
>>>>>>>> + { "bq27441", BQ27441 },
>>>>>>>> + { "bq27621", BQ27621 },
>>>>>>>> {},
>>>>>>>> };
>>>>>>>> MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
>>>>>>>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>>>>>>>> index 92df553..90db1cf 100644
>>>>>>>> --- a/include/linux/power/bq27xxx_battery.h
>>>>>>>> +++ b/include/linux/power/bq27xxx_battery.h
>>>>>>>> @@ -2,14 +2,25 @@
>>>>>>>> #define __LINUX_BQ27X00_BATTERY_H__
>>>>>>>>
>>>>>>>> enum bq27xxx_chip {
>>>>>>>> + /* categories; index for bq27xxx_regs[] */
>>>>>>>> BQ27000 = 1, /* bq27000, bq27200 */
>>>>>>>> - BQ27010, /* bq27010, bq27210 */
>>>>>>>> - BQ27500, /* bq27500 */
>>>>>>>> - BQ27510, /* bq27510, bq27520 */
>>>>>>>> - BQ27530, /* bq27530, bq27531 */
>>>>>>>> - BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
>>>>>>>> - BQ27545, /* bq27545 */
>>>>>>>> - BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
>>>>>>>> + BQ27010 = 2, /* bq27010, bq27210 */
>>>>>>>> + BQ27500 = 3, /* bq27500 */
>>>>>>>> + BQ27510 = 4, /* bq27510, bq27520 */
>>>>>>>> + BQ27530 = 5, /* bq27530, bq27531 */
>>>>>>>> + BQ27541 = 6, /* bq27541, bq27542, bq27546, bq27742 */
>>>>>>>> + BQ27545 = 7, /* bq27545 */
>>>>>>>> + BQ27421 = 8, /* bq27421, bq27425, bq27441, bq27621 */
>>>>>>>> +
>>>>>>>> + /* members of categories; translate these to category in _setup() */
>>>>>>>> + BQ27520 = 101,
>>>>>>>> + BQ27531 = 102,
>>>>>>>> + BQ27542 = 103,
>>>>>>>> + BQ27546 = 104,
>>>>>>>> + BQ27742 = 105,
>>>>>>>> + BQ27425 = 106,
>>>>>>>> + BQ27441 = 107,
>>>>>>>> + BQ27621 = 108,
>>>>>>>
>>>>>>> Get rid of this, just add new chip enum names if you need support for
>>>>>>> new chips.
>>>>>>
>>>>>> How does a non-DT config obtain chip ID? We want explicit enum values
>>>>>> if they appear in external platform-data objects. I'll mention that in
>>>>>> the next patch description.
>>>>>>
>>>>>
>>>>> platform-data is going away, I'm not sure what you are saying here.
>>>>
>>>> Don't 1-wire users have a platform-data config? You plan to force them
>>>> to replace it with DT? I thought that wasn't kosher.
>>>>
>>>
>>> The 1-wire driver generates this platform-data, 1-wire is a discoverable
>>> bus, they never needed to define DT or platform data and still will not.
>>
>> How does it map a discovered chip type to a bq27xxx_chip enum?
>>
>
> Right now it just assumes the chip is a BQ27000, see line 45 of
> drivers/w1/slaves/w1_bq27000.c
OK then we don't need explicit enum values. We still need the category
members after the categories, since the latter index bq27xxx_regs[].
>>>>>> The category (original) IDs index bq27xxx_regs[], and you'll probably
>>>>>> extend that in time. So I placed the member (new) IDs well above the
>>>>>> categories to allow permanent explicit values.
>>>>>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
2017-03-16 13:21 ` Andrew F. Davis
@ 2017-03-16 22:58 ` Liam Breck
2017-03-17 15:21 ` Andrew F. Davis
0 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-16 22:58 UTC (permalink / raw)
To: Andrew F. Davis
Cc: Sebastian Reichel, linux-pm, Rob Herring, devicetree, Liam Breck
On Thu, Mar 16, 2017 at 6:21 AM, Andrew F. Davis <afd@ti.com> wrote:
> On 03/15/2017 05:57 PM, Sebastian Reichel wrote:
>> Hi,
>>
>> On Wed, Mar 15, 2017 at 03:18:17PM -0700, Liam Breck wrote:
>>> Hey Sebastian, welcome back :-)
>>>
>>> I've taken over work on this patchset from Matt.
>>
>> Ok.
>>
>>> On Wed, Mar 15, 2017 at 3:04 PM, Sebastian Reichel <sre@kernel.org> wrote:
>>>> Hi Liam & Matt,
>>>>
>>>> Sorry for my absence in the discussion. I skipped the previous
>>>> iterations for now and start with this version.
>>>>
>>>> On Wed, Mar 15, 2017 at 12:26:46PM -0700, Liam Breck wrote:
>>>>> From: Liam Breck <kernel@networkimprov.net>
>>>>>
>>>>> Documentation of static battery characteristics that can be defined
>>>>> for batteries which cannot self-identify. This information is required
>>>>> by fuel-gauge and charger chips for proper handling of the battery.
>>>>>
>>>>> Cc: Rob Herring <robh@kernel.org>
>>>>> Cc: devicetree@vger.kernel.org
>>>>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>>>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>>>> ---
>>>>> .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++
>>>>> 1 file changed, 45 insertions(+)
>>>>> create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>> new file mode 100644
>>>>> index 0000000..0278617
>>>>> --- /dev/null
>>>>> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>> @@ -0,0 +1,45 @@
>>>>> +Battery Characteristics
>>>>
>>>> Maybe add something like
>>>>
>>>> This device provides static battery information, that is usually
>>>> available in the EEPROM of a smart battery. It's supposed to be
>>>> used for batteries, which do not have their own EEPROM (or if its
>>>> unusable).
>>>
>>> OK.
>>>
>>>>> +Required Properties:
>>>>> + - compatible: Must be "fixed-battery"
>>>
>>> Rob questioned the term "fixed". Shall we consider other terms --
>>> simple-battery, plain-battery...?
>>
>> I don't like the term either, but it was the best I came up with.
>> They are known as "dumb" batteries, but that term looks too
>> colloquial for DT usage. While I think "simple-battery" is not
>> perfect either, it's better than "fixed-battery", so please switch
>> to that in the next revision.
>>
>
> I rather like "fixed-battery", it matches the regulator and other power
> source DTs better. To answer Rob's question on what a non-fixed battery
> would look like we can think of a future battery that can change its
> physical properties (chemical or physical perhaps) in response to
> software. Although I've not seen such a battery I don't think it's too
> far-fetched.
A "fixed" battery sounds like a non-removable one to me. I'll switch
to "simple-battery" in v11 unless a better idea bubbles up first.
> All the properties described here are "fixed", if we say "simple" then a
> battery with more properties would be a "complex" battery..
Simple is not a boolean term; it really doesn't mandate a
"complex-battery" type.
>>>>> +Optional Properties:
>>>>> + - voltage-min-design-microvolt: drained battery voltage
>>>>> + - energy-full-design-microwatt-hours: battery design energy
>>>>> + - charge-full-design-microamp-hours: battery design capacity
>>>>
>>>> Looks fine to me.
>>>>
>>>>> +Because drivers surface properties in sysfs using names derived
>>>>> +from enum power_supply_property, e.g.
>>>>> +/sys/class/power_supply/<device>/charge_full_design, our
>>>>> +battery properties must be named for the corresponding elements in
>>>>> +enum power_supply_property, defined in include/linux/power_supply.h.
>>>>
>>>> This is Linux/implementation specific and does not belong
>>>> into a DT binding document.
>>>
>>> I just wrote on a thread for an earlier version of this patch:
>>>
>>> "Sebastian proposed DT:battery specifically to be consumed by
>>> power_supply_core. Allowing names in DT:battery and
>>> power_supply_property to diverge would cause confusion and wasted
>>> time, for no particular benefit. As there is no rationale to
>>> reconsider the names of these fields for DT:battery, let's write that
>>> into the docs."
>>
>> DT bindings are not "Linux hardware information bindings". Of course
>> there is no need to diverge without a good reason, but that kind of
>> Documentation just does not belong into the DT bindings.
>>
>>>>> +Batteries must be referenced by chargers and/or fuel-gauges
>>>>> +using a phandle. The phandle's property should be named
>>>>> +"monitored-battery".
>>>>
>>>> This looks fine.
>>>>
>>>>> +Driver code should call power_supply_get_battery_info() to obtain
>>>>> +battery properties via monitored-battery. For details see:
>>>>> + drivers/power/supply/power_supply_core.c
>>>>> + drivers/power/supply/bq27xxx_battery.c
>>>>
>>>> This is also Linux/implementation specific and should be dropped.
>>>
>>> We ought to mention how drivers are expected to consume DT:battery.
>>
>> That kind of documentation does not belong into
>> Documentation/devicetree/bindings. We can add something to
>> Documentation/power/power_supply_class.txt instead.
>>
>>>>> +Example:
>>>>> +
>>>>> + bat: battery {
>>>>> + compatible = "fixed-battery";
>>>>> + voltage-min-design-microvolt = <3200000>;
>>>>> + energy-full-design-microwatt-hours = <5290000>;
>>>>> + charge-full-design-microamp-hours = <1430000>;
>>>>> + };
>>>>> +
>>>>> + charger: charger@11 {
>>>>> + ....
>>>>> + monitored-battery = <&bat>;
>>>>> + ...
>>>>> + };
>>>>> +
>>>>> + fuel_gauge: fuel-gauge@22 {
>>>>> + ....
>>>>> + monitored-battery = <&bat>;
>>>>> + ...
>>>>> + };
>>>>> --
>>>>> 2.9.3
>>>>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
2017-03-16 22:58 ` Liam Breck
@ 2017-03-17 15:21 ` Andrew F. Davis
2017-03-17 21:43 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Andrew F. Davis @ 2017-03-17 15:21 UTC (permalink / raw)
To: Liam Breck
Cc: Sebastian Reichel, linux-pm, Rob Herring, devicetree, Liam Breck
On 03/16/2017 05:58 PM, Liam Breck wrote:
> On Thu, Mar 16, 2017 at 6:21 AM, Andrew F. Davis <afd@ti.com> wrote:
>> On 03/15/2017 05:57 PM, Sebastian Reichel wrote:
>>> Hi,
>>>
>>> On Wed, Mar 15, 2017 at 03:18:17PM -0700, Liam Breck wrote:
>>>> Hey Sebastian, welcome back :-)
>>>>
>>>> I've taken over work on this patchset from Matt.
>>>
>>> Ok.
>>>
>>>> On Wed, Mar 15, 2017 at 3:04 PM, Sebastian Reichel <sre@kernel.org> wrote:
>>>>> Hi Liam & Matt,
>>>>>
>>>>> Sorry for my absence in the discussion. I skipped the previous
>>>>> iterations for now and start with this version.
>>>>>
>>>>> On Wed, Mar 15, 2017 at 12:26:46PM -0700, Liam Breck wrote:
>>>>>> From: Liam Breck <kernel@networkimprov.net>
>>>>>>
>>>>>> Documentation of static battery characteristics that can be defined
>>>>>> for batteries which cannot self-identify. This information is required
>>>>>> by fuel-gauge and charger chips for proper handling of the battery.
>>>>>>
>>>>>> Cc: Rob Herring <robh@kernel.org>
>>>>>> Cc: devicetree@vger.kernel.org
>>>>>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>>>>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>>>>> ---
>>>>>> .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++
>>>>>> 1 file changed, 45 insertions(+)
>>>>>> create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>
>>>>>> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>> new file mode 100644
>>>>>> index 0000000..0278617
>>>>>> --- /dev/null
>>>>>> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>> @@ -0,0 +1,45 @@
>>>>>> +Battery Characteristics
>>>>>
>>>>> Maybe add something like
>>>>>
>>>>> This device provides static battery information, that is usually
>>>>> available in the EEPROM of a smart battery. It's supposed to be
>>>>> used for batteries, which do not have their own EEPROM (or if its
>>>>> unusable).
>>>>
>>>> OK.
>>>>
>>>>>> +Required Properties:
>>>>>> + - compatible: Must be "fixed-battery"
>>>>
>>>> Rob questioned the term "fixed". Shall we consider other terms --
>>>> simple-battery, plain-battery...?
>>>
>>> I don't like the term either, but it was the best I came up with.
>>> They are known as "dumb" batteries, but that term looks too
>>> colloquial for DT usage. While I think "simple-battery" is not
>>> perfect either, it's better than "fixed-battery", so please switch
>>> to that in the next revision.
>>>
>>
>> I rather like "fixed-battery", it matches the regulator and other power
>> source DTs better. To answer Rob's question on what a non-fixed battery
>> would look like we can think of a future battery that can change its
>> physical properties (chemical or physical perhaps) in response to
>> software. Although I've not seen such a battery I don't think it's too
>> far-fetched.
>
> A "fixed" battery sounds like a non-removable one to me. I'll switch
> to "simple-battery" in v11 unless a better idea bubbles up first.
>
Are fixed-regulators non-removable, or do most people understand. Also
this is for non-removable batteries, if a battery is changeable then
this DT is not valid as it would be describing the current configuration
of the device. I guess it could be done with overlays for the current
battery, not sure, but something to think about.
>> All the properties described here are "fixed", if we say "simple" then a
>> battery with more properties would be a "complex" battery..
>
> Simple is not a boolean term; it really doesn't mandate a
> "complex-battery" type.
>
Yes, but the spectrum would imply levels of simplicity, what would *you*
call a "non-simple" battery?
>>>>>> +Optional Properties:
>>>>>> + - voltage-min-design-microvolt: drained battery voltage
>>>>>> + - energy-full-design-microwatt-hours: battery design energy
>>>>>> + - charge-full-design-microamp-hours: battery design capacity
>>>>>
>>>>> Looks fine to me.
>>>>>
>>>>>> +Because drivers surface properties in sysfs using names derived
>>>>>> +from enum power_supply_property, e.g.
>>>>>> +/sys/class/power_supply/<device>/charge_full_design, our
>>>>>> +battery properties must be named for the corresponding elements in
>>>>>> +enum power_supply_property, defined in include/linux/power_supply.h.
>>>>>
>>>>> This is Linux/implementation specific and does not belong
>>>>> into a DT binding document.
>>>>
>>>> I just wrote on a thread for an earlier version of this patch:
>>>>
>>>> "Sebastian proposed DT:battery specifically to be consumed by
>>>> power_supply_core. Allowing names in DT:battery and
>>>> power_supply_property to diverge would cause confusion and wasted
>>>> time, for no particular benefit. As there is no rationale to
>>>> reconsider the names of these fields for DT:battery, let's write that
>>>> into the docs."
>>>
>>> DT bindings are not "Linux hardware information bindings". Of course
>>> there is no need to diverge without a good reason, but that kind of
>>> Documentation just does not belong into the DT bindings.
>>>
>>>>>> +Batteries must be referenced by chargers and/or fuel-gauges
>>>>>> +using a phandle. The phandle's property should be named
>>>>>> +"monitored-battery".
>>>>>
>>>>> This looks fine.
>>>>>
>>>>>> +Driver code should call power_supply_get_battery_info() to obtain
>>>>>> +battery properties via monitored-battery. For details see:
>>>>>> + drivers/power/supply/power_supply_core.c
>>>>>> + drivers/power/supply/bq27xxx_battery.c
>>>>>
>>>>> This is also Linux/implementation specific and should be dropped.
>>>>
>>>> We ought to mention how drivers are expected to consume DT:battery.
>>>
>>> That kind of documentation does not belong into
>>> Documentation/devicetree/bindings. We can add something to
>>> Documentation/power/power_supply_class.txt instead.
>>>
>>>>>> +Example:
>>>>>> +
>>>>>> + bat: battery {
>>>>>> + compatible = "fixed-battery";
>>>>>> + voltage-min-design-microvolt = <3200000>;
>>>>>> + energy-full-design-microwatt-hours = <5290000>;
>>>>>> + charge-full-design-microamp-hours = <1430000>;
>>>>>> + };
>>>>>> +
>>>>>> + charger: charger@11 {
>>>>>> + ....
>>>>>> + monitored-battery = <&bat>;
>>>>>> + ...
>>>>>> + };
>>>>>> +
>>>>>> + fuel_gauge: fuel-gauge@22 {
>>>>>> + ....
>>>>>> + monitored-battery = <&bat>;
>>>>>> + ...
>>>>>> + };
>>>>>> --
>>>>>> 2.9.3
>>>>>>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
2017-03-17 15:21 ` Andrew F. Davis
@ 2017-03-17 21:43 ` Liam Breck
[not found] ` <CAKvHMgS92WFoJa=imfAFiEEc0VyiSsDBbuYi4yzZ=LEa7__yKA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 35+ messages in thread
From: Liam Breck @ 2017-03-17 21:43 UTC (permalink / raw)
To: Andrew F. Davis
Cc: Sebastian Reichel, linux-pm, Rob Herring, devicetree, Liam Breck
On Fri, Mar 17, 2017 at 8:21 AM, Andrew F. Davis <afd@ti.com> wrote:
> On 03/16/2017 05:58 PM, Liam Breck wrote:
>> On Thu, Mar 16, 2017 at 6:21 AM, Andrew F. Davis <afd@ti.com> wrote:
>>> On 03/15/2017 05:57 PM, Sebastian Reichel wrote:
>>>> Hi,
>>>>
>>>> On Wed, Mar 15, 2017 at 03:18:17PM -0700, Liam Breck wrote:
>>>>> Hey Sebastian, welcome back :-)
>>>>>
>>>>> I've taken over work on this patchset from Matt.
>>>>
>>>> Ok.
>>>>
>>>>> On Wed, Mar 15, 2017 at 3:04 PM, Sebastian Reichel <sre@kernel.org> wrote:
>>>>>> Hi Liam & Matt,
>>>>>>
>>>>>> Sorry for my absence in the discussion. I skipped the previous
>>>>>> iterations for now and start with this version.
>>>>>>
>>>>>> On Wed, Mar 15, 2017 at 12:26:46PM -0700, Liam Breck wrote:
>>>>>>> From: Liam Breck <kernel@networkimprov.net>
>>>>>>>
>>>>>>> Documentation of static battery characteristics that can be defined
>>>>>>> for batteries which cannot self-identify. This information is required
>>>>>>> by fuel-gauge and charger chips for proper handling of the battery.
>>>>>>>
>>>>>>> Cc: Rob Herring <robh@kernel.org>
>>>>>>> Cc: devicetree@vger.kernel.org
>>>>>>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>>>>>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>>>>>> ---
>>>>>>> .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++
>>>>>>> 1 file changed, 45 insertions(+)
>>>>>>> create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>
>>>>>>> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>> new file mode 100644
>>>>>>> index 0000000..0278617
>>>>>>> --- /dev/null
>>>>>>> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>> @@ -0,0 +1,45 @@
>>>>>>> +Battery Characteristics
>>>>>>
>>>>>> Maybe add something like
>>>>>>
>>>>>> This device provides static battery information, that is usually
>>>>>> available in the EEPROM of a smart battery. It's supposed to be
>>>>>> used for batteries, which do not have their own EEPROM (or if its
>>>>>> unusable).
>>>>>
>>>>> OK.
>>>>>
>>>>>>> +Required Properties:
>>>>>>> + - compatible: Must be "fixed-battery"
>>>>>
>>>>> Rob questioned the term "fixed". Shall we consider other terms --
>>>>> simple-battery, plain-battery...?
>>>>
>>>> I don't like the term either, but it was the best I came up with.
>>>> They are known as "dumb" batteries, but that term looks too
>>>> colloquial for DT usage. While I think "simple-battery" is not
>>>> perfect either, it's better than "fixed-battery", so please switch
>>>> to that in the next revision.
>>>>
>>>
>>> I rather like "fixed-battery", it matches the regulator and other power
>>> source DTs better. To answer Rob's question on what a non-fixed battery
>>> would look like we can think of a future battery that can change its
>>> physical properties (chemical or physical perhaps) in response to
>>> software. Although I've not seen such a battery I don't think it's too
>>> far-fetched.
>>
>> A "fixed" battery sounds like a non-removable one to me. I'll switch
>> to "simple-battery" in v11 unless a better idea bubbles up first.
>>
>
> Are fixed-regulators non-removable, or do most people understand. Also
> this is for non-removable batteries, if a battery is changeable then
> this DT is not valid as it would be describing the current configuration
> of the device. I guess it could be done with overlays for the current
> battery, not sure, but something to think about.
I know little about regulators, but wikipedia mentions fixed and
variable/adjustable kinds. We're not contemplating an "adjustable
battery" type, so the fixed/adjustable dichotomy isn't a natural fit
here.
>>> All the properties described here are "fixed", if we say "simple" then a
>>> battery with more properties would be a "complex" battery..
>>
>> Simple is not a boolean term; it really doesn't mandate a
>> "complex-battery" type.
>>
>
> Yes, but the spectrum would imply levels of simplicity, what would *you*
> call a "non-simple" battery?
Simple is not an integral term, either :-)
simple-battery, gauged-battery, coin-battery, bare-battery (no
protection circuit)...
>>>>>>> +Optional Properties:
>>>>>>> + - voltage-min-design-microvolt: drained battery voltage
>>>>>>> + - energy-full-design-microwatt-hours: battery design energy
>>>>>>> + - charge-full-design-microamp-hours: battery design capacity
>>>>>>
>>>>>> Looks fine to me.
>>>>>>
>>>>>>> +Because drivers surface properties in sysfs using names derived
>>>>>>> +from enum power_supply_property, e.g.
>>>>>>> +/sys/class/power_supply/<device>/charge_full_design, our
>>>>>>> +battery properties must be named for the corresponding elements in
>>>>>>> +enum power_supply_property, defined in include/linux/power_supply.h.
>>>>>>
>>>>>> This is Linux/implementation specific and does not belong
>>>>>> into a DT binding document.
>>>>>
>>>>> I just wrote on a thread for an earlier version of this patch:
>>>>>
>>>>> "Sebastian proposed DT:battery specifically to be consumed by
>>>>> power_supply_core. Allowing names in DT:battery and
>>>>> power_supply_property to diverge would cause confusion and wasted
>>>>> time, for no particular benefit. As there is no rationale to
>>>>> reconsider the names of these fields for DT:battery, let's write that
>>>>> into the docs."
>>>>
>>>> DT bindings are not "Linux hardware information bindings". Of course
>>>> there is no need to diverge without a good reason, but that kind of
>>>> Documentation just does not belong into the DT bindings.
>>>>
>>>>>>> +Batteries must be referenced by chargers and/or fuel-gauges
>>>>>>> +using a phandle. The phandle's property should be named
>>>>>>> +"monitored-battery".
>>>>>>
>>>>>> This looks fine.
>>>>>>
>>>>>>> +Driver code should call power_supply_get_battery_info() to obtain
>>>>>>> +battery properties via monitored-battery. For details see:
>>>>>>> + drivers/power/supply/power_supply_core.c
>>>>>>> + drivers/power/supply/bq27xxx_battery.c
>>>>>>
>>>>>> This is also Linux/implementation specific and should be dropped.
>>>>>
>>>>> We ought to mention how drivers are expected to consume DT:battery.
>>>>
>>>> That kind of documentation does not belong into
>>>> Documentation/devicetree/bindings. We can add something to
>>>> Documentation/power/power_supply_class.txt instead.
>>>>
>>>>>>> +Example:
>>>>>>> +
>>>>>>> + bat: battery {
>>>>>>> + compatible = "fixed-battery";
>>>>>>> + voltage-min-design-microvolt = <3200000>;
>>>>>>> + energy-full-design-microwatt-hours = <5290000>;
>>>>>>> + charge-full-design-microamp-hours = <1430000>;
>>>>>>> + };
>>>>>>> +
>>>>>>> + charger: charger@11 {
>>>>>>> + ....
>>>>>>> + monitored-battery = <&bat>;
>>>>>>> + ...
>>>>>>> + };
>>>>>>> +
>>>>>>> + fuel_gauge: fuel-gauge@22 {
>>>>>>> + ....
>>>>>>> + monitored-battery = <&bat>;
>>>>>>> + ...
>>>>>>> + };
>>>>>>> --
>>>>>>> 2.9.3
>>>>>>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe devicetree" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
[not found] ` <CAKvHMgS92WFoJa=imfAFiEEc0VyiSsDBbuYi4yzZ=LEa7__yKA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2017-03-20 16:45 ` Andrew F. Davis
2017-03-20 18:26 ` Liam Breck
0 siblings, 1 reply; 35+ messages in thread
From: Andrew F. Davis @ 2017-03-20 16:45 UTC (permalink / raw)
To: Liam Breck
Cc: Sebastian Reichel, linux-pm-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA, Liam Breck
On 03/17/2017 04:43 PM, Liam Breck wrote:
> On Fri, Mar 17, 2017 at 8:21 AM, Andrew F. Davis <afd-l0cyMroinI0@public.gmane.org> wrote:
>> On 03/16/2017 05:58 PM, Liam Breck wrote:
>>> On Thu, Mar 16, 2017 at 6:21 AM, Andrew F. Davis <afd-l0cyMroinI0@public.gmane.org> wrote:
>>>> On 03/15/2017 05:57 PM, Sebastian Reichel wrote:
>>>>> Hi,
>>>>>
>>>>> On Wed, Mar 15, 2017 at 03:18:17PM -0700, Liam Breck wrote:
>>>>>> Hey Sebastian, welcome back :-)
>>>>>>
>>>>>> I've taken over work on this patchset from Matt.
>>>>>
>>>>> Ok.
>>>>>
>>>>>> On Wed, Mar 15, 2017 at 3:04 PM, Sebastian Reichel <sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>>>>>>> Hi Liam & Matt,
>>>>>>>
>>>>>>> Sorry for my absence in the discussion. I skipped the previous
>>>>>>> iterations for now and start with this version.
>>>>>>>
>>>>>>> On Wed, Mar 15, 2017 at 12:26:46PM -0700, Liam Breck wrote:
>>>>>>>> From: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
>>>>>>>>
>>>>>>>> Documentation of static battery characteristics that can be defined
>>>>>>>> for batteries which cannot self-identify. This information is required
>>>>>>>> by fuel-gauge and charger chips for proper handling of the battery.
>>>>>>>>
>>>>>>>> Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>>>>>>>> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>>>>>>>> Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
>>>>>>>> Signed-off-by: Liam Breck <kernel-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
>>>>>>>> ---
>>>>>>>> .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++
>>>>>>>> 1 file changed, 45 insertions(+)
>>>>>>>> create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>>
>>>>>>>> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>> new file mode 100644
>>>>>>>> index 0000000..0278617
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>> @@ -0,0 +1,45 @@
>>>>>>>> +Battery Characteristics
>>>>>>>
>>>>>>> Maybe add something like
>>>>>>>
>>>>>>> This device provides static battery information, that is usually
>>>>>>> available in the EEPROM of a smart battery. It's supposed to be
>>>>>>> used for batteries, which do not have their own EEPROM (or if its
>>>>>>> unusable).
>>>>>>
>>>>>> OK.
>>>>>>
>>>>>>>> +Required Properties:
>>>>>>>> + - compatible: Must be "fixed-battery"
>>>>>>
>>>>>> Rob questioned the term "fixed". Shall we consider other terms --
>>>>>> simple-battery, plain-battery...?
>>>>>
>>>>> I don't like the term either, but it was the best I came up with.
>>>>> They are known as "dumb" batteries, but that term looks too
>>>>> colloquial for DT usage. While I think "simple-battery" is not
>>>>> perfect either, it's better than "fixed-battery", so please switch
>>>>> to that in the next revision.
>>>>>
>>>>
>>>> I rather like "fixed-battery", it matches the regulator and other power
>>>> source DTs better. To answer Rob's question on what a non-fixed battery
>>>> would look like we can think of a future battery that can change its
>>>> physical properties (chemical or physical perhaps) in response to
>>>> software. Although I've not seen such a battery I don't think it's too
>>>> far-fetched.
>>>
>>> A "fixed" battery sounds like a non-removable one to me. I'll switch
>>> to "simple-battery" in v11 unless a better idea bubbles up first.
>>>
>>
>> Are fixed-regulators non-removable, or do most people understand. Also
>> this is for non-removable batteries, if a battery is changeable then
>> this DT is not valid as it would be describing the current configuration
>> of the device. I guess it could be done with overlays for the current
>> battery, not sure, but something to think about.
>
> I know little about regulators, but wikipedia mentions fixed and
> variable/adjustable kinds. We're not contemplating an "adjustable
> battery" type, so the fixed/adjustable dichotomy isn't a natural fit
> here.
>
I think we are though, you are saying this is a "simple" battery because
it has fixed design parameters. Any battery that does not have fixed
design parameters is some kinda futuristic adjustable battery, what else
would you call a battery with non-fixed design parameters?
>>>> All the properties described here are "fixed", if we say "simple" then a
>>>> battery with more properties would be a "complex" battery..
>>>
>>> Simple is not a boolean term; it really doesn't mandate a
>>> "complex-battery" type.
>>>
>>
>> Yes, but the spectrum would imply levels of simplicity, what would *you*
>> call a "non-simple" battery?
>
> Simple is not an integral term, either :-)
>
> simple-battery, gauged-battery, coin-battery, bare-battery (no
> protection circuit)...
>
Fixed/simple/coin/bare batteries are all the same to DT and so do not
need new node/compatible names. "Gauged-battery" would be described by a
node representing the fuel-gauge and that node would then point to the
battery that it gauges, no still no need for a new term.
In our world we still have only three things:
Charger -
| |-> Battery
\/ |
Gauge - -
Sometimes we will have a battery, sometimes we will have a charger or a
gauge with an attached battery, and sometimes we will have charger with
embedded gauging functions. All these relations can be described in DT
without adding extra compatibles.
>>>>>>>> +Optional Properties:
>>>>>>>> + - voltage-min-design-microvolt: drained battery voltage
>>>>>>>> + - energy-full-design-microwatt-hours: battery design energy
>>>>>>>> + - charge-full-design-microamp-hours: battery design capacity
>>>>>>>
>>>>>>> Looks fine to me.
>>>>>>>
>>>>>>>> +Because drivers surface properties in sysfs using names derived
>>>>>>>> +from enum power_supply_property, e.g.
>>>>>>>> +/sys/class/power_supply/<device>/charge_full_design, our
>>>>>>>> +battery properties must be named for the corresponding elements in
>>>>>>>> +enum power_supply_property, defined in include/linux/power_supply.h.
>>>>>>>
>>>>>>> This is Linux/implementation specific and does not belong
>>>>>>> into a DT binding document.
>>>>>>
>>>>>> I just wrote on a thread for an earlier version of this patch:
>>>>>>
>>>>>> "Sebastian proposed DT:battery specifically to be consumed by
>>>>>> power_supply_core. Allowing names in DT:battery and
>>>>>> power_supply_property to diverge would cause confusion and wasted
>>>>>> time, for no particular benefit. As there is no rationale to
>>>>>> reconsider the names of these fields for DT:battery, let's write that
>>>>>> into the docs."
>>>>>
>>>>> DT bindings are not "Linux hardware information bindings". Of course
>>>>> there is no need to diverge without a good reason, but that kind of
>>>>> Documentation just does not belong into the DT bindings.
>>>>>
>>>>>>>> +Batteries must be referenced by chargers and/or fuel-gauges
>>>>>>>> +using a phandle. The phandle's property should be named
>>>>>>>> +"monitored-battery".
>>>>>>>
>>>>>>> This looks fine.
>>>>>>>
>>>>>>>> +Driver code should call power_supply_get_battery_info() to obtain
>>>>>>>> +battery properties via monitored-battery. For details see:
>>>>>>>> + drivers/power/supply/power_supply_core.c
>>>>>>>> + drivers/power/supply/bq27xxx_battery.c
>>>>>>>
>>>>>>> This is also Linux/implementation specific and should be dropped.
>>>>>>
>>>>>> We ought to mention how drivers are expected to consume DT:battery.
>>>>>
>>>>> That kind of documentation does not belong into
>>>>> Documentation/devicetree/bindings. We can add something to
>>>>> Documentation/power/power_supply_class.txt instead.
>>>>>
>>>>>>>> +Example:
>>>>>>>> +
>>>>>>>> + bat: battery {
>>>>>>>> + compatible = "fixed-battery";
>>>>>>>> + voltage-min-design-microvolt = <3200000>;
>>>>>>>> + energy-full-design-microwatt-hours = <5290000>;
>>>>>>>> + charge-full-design-microamp-hours = <1430000>;
>>>>>>>> + };
>>>>>>>> +
>>>>>>>> + charger: charger@11 {
>>>>>>>> + ....
>>>>>>>> + monitored-battery = <&bat>;
>>>>>>>> + ...
>>>>>>>> + };
>>>>>>>> +
>>>>>>>> + fuel_gauge: fuel-gauge@22 {
>>>>>>>> + ....
>>>>>>>> + monitored-battery = <&bat>;
>>>>>>>> + ...
>>>>>>>> + };
>>>>>>>> --
>>>>>>>> 2.9.3
>>>>>>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe devicetree" in
>>> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
2017-03-20 16:45 ` Andrew F. Davis
@ 2017-03-20 18:26 ` Liam Breck
0 siblings, 0 replies; 35+ messages in thread
From: Liam Breck @ 2017-03-20 18:26 UTC (permalink / raw)
To: Andrew F. Davis
Cc: Sebastian Reichel, linux-pm, Rob Herring, devicetree, Liam Breck
On Mon, Mar 20, 2017 at 9:45 AM, Andrew F. Davis <afd@ti.com> wrote:
> On 03/17/2017 04:43 PM, Liam Breck wrote:
>> On Fri, Mar 17, 2017 at 8:21 AM, Andrew F. Davis <afd@ti.com> wrote:
>>> On 03/16/2017 05:58 PM, Liam Breck wrote:
>>>> On Thu, Mar 16, 2017 at 6:21 AM, Andrew F. Davis <afd@ti.com> wrote:
>>>>> On 03/15/2017 05:57 PM, Sebastian Reichel wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On Wed, Mar 15, 2017 at 03:18:17PM -0700, Liam Breck wrote:
>>>>>>> Hey Sebastian, welcome back :-)
>>>>>>>
>>>>>>> I've taken over work on this patchset from Matt.
>>>>>>
>>>>>> Ok.
>>>>>>
>>>>>>> On Wed, Mar 15, 2017 at 3:04 PM, Sebastian Reichel <sre@kernel.org> wrote:
>>>>>>>> Hi Liam & Matt,
>>>>>>>>
>>>>>>>> Sorry for my absence in the discussion. I skipped the previous
>>>>>>>> iterations for now and start with this version.
>>>>>>>>
>>>>>>>> On Wed, Mar 15, 2017 at 12:26:46PM -0700, Liam Breck wrote:
>>>>>>>>> From: Liam Breck <kernel@networkimprov.net>
>>>>>>>>>
>>>>>>>>> Documentation of static battery characteristics that can be defined
>>>>>>>>> for batteries which cannot self-identify. This information is required
>>>>>>>>> by fuel-gauge and charger chips for proper handling of the battery.
>>>>>>>>>
>>>>>>>>> Cc: Rob Herring <robh@kernel.org>
>>>>>>>>> Cc: devicetree@vger.kernel.org
>>>>>>>>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>>>>>>>>> Signed-off-by: Liam Breck <kernel@networkimprov.net>
>>>>>>>>> ---
>>>>>>>>> .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++
>>>>>>>>> 1 file changed, 45 insertions(+)
>>>>>>>>> create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>>>
>>>>>>>>> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>>> new file mode 100644
>>>>>>>>> index 0000000..0278617
>>>>>>>>> --- /dev/null
>>>>>>>>> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>>> @@ -0,0 +1,45 @@
>>>>>>>>> +Battery Characteristics
>>>>>>>>
>>>>>>>> Maybe add something like
>>>>>>>>
>>>>>>>> This device provides static battery information, that is usually
>>>>>>>> available in the EEPROM of a smart battery. It's supposed to be
>>>>>>>> used for batteries, which do not have their own EEPROM (or if its
>>>>>>>> unusable).
>>>>>>>
>>>>>>> OK.
>>>>>>>
>>>>>>>>> +Required Properties:
>>>>>>>>> + - compatible: Must be "fixed-battery"
>>>>>>>
>>>>>>> Rob questioned the term "fixed". Shall we consider other terms --
>>>>>>> simple-battery, plain-battery...?
>>>>>>
>>>>>> I don't like the term either, but it was the best I came up with.
>>>>>> They are known as "dumb" batteries, but that term looks too
>>>>>> colloquial for DT usage. While I think "simple-battery" is not
>>>>>> perfect either, it's better than "fixed-battery", so please switch
>>>>>> to that in the next revision.
>>>>>>
>>>>>
>>>>> I rather like "fixed-battery", it matches the regulator and other power
>>>>> source DTs better. To answer Rob's question on what a non-fixed battery
>>>>> would look like we can think of a future battery that can change its
>>>>> physical properties (chemical or physical perhaps) in response to
>>>>> software. Although I've not seen such a battery I don't think it's too
>>>>> far-fetched.
>>>>
>>>> A "fixed" battery sounds like a non-removable one to me. I'll switch
>>>> to "simple-battery" in v11 unless a better idea bubbles up first.
>>>>
>>>
>>> Are fixed-regulators non-removable, or do most people understand. Also
>>> this is for non-removable batteries, if a battery is changeable then
>>> this DT is not valid as it would be describing the current configuration
>>> of the device. I guess it could be done with overlays for the current
>>> battery, not sure, but something to think about.
>>
>> I know little about regulators, but wikipedia mentions fixed and
>> variable/adjustable kinds. We're not contemplating an "adjustable
>> battery" type, so the fixed/adjustable dichotomy isn't a natural fit
>> here.
>>
>
> I think we are though, you are saying this is a "simple" battery because
> it has fixed design parameters. Any battery that does not have fixed
> design parameters is some kinda futuristic adjustable battery, what else
> would you call a battery with non-fixed design parameters?
fantasy-battery :-)
>>>>> All the properties described here are "fixed", if we say "simple" then a
>>>>> battery with more properties would be a "complex" battery..
>>>>
>>>> Simple is not a boolean term; it really doesn't mandate a
>>>> "complex-battery" type.
>>>>
>>>
>>> Yes, but the spectrum would imply levels of simplicity, what would *you*
>>> call a "non-simple" battery?
>>
>> Simple is not an integral term, either :-)
>>
>> simple-battery, gauged-battery, coin-battery, bare-battery (no
>> protection circuit)...
>>
>
> Fixed/simple/coin/bare batteries are all the same to DT and so do not
> need new node/compatible names. "Gauged-battery" would be described by a
> node representing the fuel-gauge and that node would then point to the
> battery that it gauges, no still no need for a new term.
>
> In our world we still have only three things:
> Charger -
> | |-> Battery
> \/ |
> Gauge - -
>
> Sometimes we will have a battery, sometimes we will have a charger or a
> gauge with an attached battery, and sometimes we will have charger with
> embedded gauging functions. All these relations can be described in DT
> without adding extra compatibles.
Here's the dichotomy you want: clever-battery, simple-battery :-)
But seriously... acpi-battery could be relevant.
>>>>>>>>> +Optional Properties:
>>>>>>>>> + - voltage-min-design-microvolt: drained battery voltage
>>>>>>>>> + - energy-full-design-microwatt-hours: battery design energy
>>>>>>>>> + - charge-full-design-microamp-hours: battery design capacity
>>>>>>>>
>>>>>>>> Looks fine to me.
>>>>>>>>
>>>>>>>>> +Because drivers surface properties in sysfs using names derived
>>>>>>>>> +from enum power_supply_property, e.g.
>>>>>>>>> +/sys/class/power_supply/<device>/charge_full_design, our
>>>>>>>>> +battery properties must be named for the corresponding elements in
>>>>>>>>> +enum power_supply_property, defined in include/linux/power_supply.h.
>>>>>>>>
>>>>>>>> This is Linux/implementation specific and does not belong
>>>>>>>> into a DT binding document.
>>>>>>>
>>>>>>> I just wrote on a thread for an earlier version of this patch:
>>>>>>>
>>>>>>> "Sebastian proposed DT:battery specifically to be consumed by
>>>>>>> power_supply_core. Allowing names in DT:battery and
>>>>>>> power_supply_property to diverge would cause confusion and wasted
>>>>>>> time, for no particular benefit. As there is no rationale to
>>>>>>> reconsider the names of these fields for DT:battery, let's write that
>>>>>>> into the docs."
>>>>>>
>>>>>> DT bindings are not "Linux hardware information bindings". Of course
>>>>>> there is no need to diverge without a good reason, but that kind of
>>>>>> Documentation just does not belong into the DT bindings.
>>>>>>
>>>>>>>>> +Batteries must be referenced by chargers and/or fuel-gauges
>>>>>>>>> +using a phandle. The phandle's property should be named
>>>>>>>>> +"monitored-battery".
>>>>>>>>
>>>>>>>> This looks fine.
>>>>>>>>
>>>>>>>>> +Driver code should call power_supply_get_battery_info() to obtain
>>>>>>>>> +battery properties via monitored-battery. For details see:
>>>>>>>>> + drivers/power/supply/power_supply_core.c
>>>>>>>>> + drivers/power/supply/bq27xxx_battery.c
>>>>>>>>
>>>>>>>> This is also Linux/implementation specific and should be dropped.
>>>>>>>
>>>>>>> We ought to mention how drivers are expected to consume DT:battery.
>>>>>>
>>>>>> That kind of documentation does not belong into
>>>>>> Documentation/devicetree/bindings. We can add something to
>>>>>> Documentation/power/power_supply_class.txt instead.
>>>>>>
>>>>>>>>> +Example:
>>>>>>>>> +
>>>>>>>>> + bat: battery {
>>>>>>>>> + compatible = "fixed-battery";
>>>>>>>>> + voltage-min-design-microvolt = <3200000>;
>>>>>>>>> + energy-full-design-microwatt-hours = <5290000>;
>>>>>>>>> + charge-full-design-microamp-hours = <1430000>;
>>>>>>>>> + };
>>>>>>>>> +
>>>>>>>>> + charger: charger@11 {
>>>>>>>>> + ....
>>>>>>>>> + monitored-battery = <&bat>;
>>>>>>>>> + ...
>>>>>>>>> + };
>>>>>>>>> +
>>>>>>>>> + fuel_gauge: fuel-gauge@22 {
>>>>>>>>> + ....
>>>>>>>>> + monitored-battery = <&bat>;
>>>>>>>>> + ...
>>>>>>>>> + };
>>>>>>>>> --
>>>>>>>>> 2.9.3
>>>>>>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe devicetree" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>>
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2017-03-20 18:26 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-15 19:26 [PATCH v10 0/8] devicetree battery support and client bq27xxx_battery Liam Breck
2017-03-15 19:26 ` [PATCH v10 2/8] devicetree: property-units: Add uWh and uAh units Liam Breck
[not found] ` <20170315192653.26799-1-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
2017-03-15 19:26 ` [PATCH v10 1/8] devicetree: power: Add battery.txt Liam Breck
2017-03-15 22:04 ` Sebastian Reichel
2017-03-15 22:18 ` Liam Breck
2017-03-15 22:57 ` Sebastian Reichel
2017-03-16 13:21 ` Andrew F. Davis
2017-03-16 22:58 ` Liam Breck
2017-03-17 15:21 ` Andrew F. Davis
2017-03-17 21:43 ` Liam Breck
[not found] ` <CAKvHMgS92WFoJa=imfAFiEEc0VyiSsDBbuYi4yzZ=LEa7__yKA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-03-20 16:45 ` Andrew F. Davis
2017-03-20 18:26 ` Liam Breck
2017-03-15 19:26 ` [PATCH v10 3/8] devicetree: power: bq27xxx: Add monitored-battery documentation Liam Breck
[not found] ` <20170315192653.26799-4-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org>
2017-03-15 22:06 ` Sebastian Reichel
2017-03-15 19:26 ` [PATCH v10 4/8] power: power_supply: Add power_supply_battery_info and API Liam Breck
2017-03-15 22:07 ` Sebastian Reichel
2017-03-15 19:26 ` [PATCH v10 5/8] power: bq27xxx_battery: Define access methods to write chip registers Liam Breck
2017-03-15 19:26 ` [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id Liam Breck
2017-03-16 14:44 ` Andrew F. Davis
2017-03-16 20:12 ` Liam Breck
2017-03-16 20:50 ` Andrew F. Davis
2017-03-16 21:26 ` Liam Breck
2017-03-16 21:30 ` Andrew F. Davis
2017-03-16 21:47 ` Liam Breck
2017-03-16 21:53 ` Andrew F. Davis
2017-03-16 22:38 ` Liam Breck
2017-03-15 19:26 ` [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support Liam Breck
2017-03-16 15:00 ` Andrew F. Davis
2017-03-16 21:12 ` Liam Breck
2017-03-16 21:39 ` Andrew F. Davis
2017-03-16 22:31 ` Liam Breck
2017-03-15 19:26 ` [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions Liam Breck
2017-03-15 22:14 ` Sebastian Reichel
2017-03-15 22:34 ` Liam Breck
2017-03-15 23:03 ` Sebastian Reichel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.