All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.