devicetree battery support and client bq27xxx_battery
Subsystems (4)
v10 cover devicetree battery support and client bq27xxx_battery
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
Signature · 1 line
2.9.3
A message that is not in the archive (sent off-list or not yet received): 20170315192653.26799-1-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org
PATCH v10 1/8 devicetree: power: Add battery.txt
From: Liam Breck <[email protected]>
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.
--- .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
Documentation/devicetree/bindings/power/supply/battery.txt new file +45 -0
@@ -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>; + ... + };
Signature · 6 lines
2.9.3 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Sebastian Reichel
maintainerRe: [PATCH v10 1/8] devicetree: power: Add battery.txt
Hi Liam & Matt,
Sorry for my absence in the discussion. I skipped the previous iterations for now and start with this version.
Quoted 21 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txtDocumentation/devicetree/bindings/power/supply/battery.txt new file +0
-0
Documentation/devicetree/bindings/power/supply/battery.txt line 1
Quoted 1 line
Documentation/devicetree/bindings/power/supply/battery.txt new file +1
-0@@ -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).
Documentation/devicetree/bindings/power/supply/battery.txt line 9
Quoted 7 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +7
-0+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.
Documentation/devicetree/bindings/power/supply/battery.txt line 15
Quoted 5 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-0+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.
Documentation/devicetree/bindings/power/supply/battery.txt line 19
Quoted 3 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +3
-0+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.
Documentation/devicetree/bindings/power/supply/battery.txt line 24
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+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.
Quoted 23 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +20
-0+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>; + ... + };Signature · 1 line
2.9.3
Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
Hey Sebastian, welcome back :-)
I've taken over work on this patchset from Matt.
Quoted 31 lines · Sebastian Reichel
Hi Liam & Matt,
Sorry for my absence in the discussion. I skipped the previous iterations for now and start with this version.
Quoted 21 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txtDocumentation/devicetree/bindings/power/supply/battery.txt new file +0
-0Documentation/devicetree/bindings/power/supply/battery.txt line 1
Quoted 1 line
Documentation/devicetree/bindings/power/supply/battery.txt new file +1
-0@@ -0,0 +1,45 @@ +Battery CharacteristicsMaybe add something like
Quoted 4 lines
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.
Quoted 2 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 4
Quoted 2 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +2
-0+Required Properties: + - compatible: Must be "fixed-battery"
Rob questioned the term "fixed". Shall we consider other terms -- simple-battery, plain-battery...?
Quoted 7 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 9
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+Optional Properties: + - voltage-min-design-microvolt: drained battery voltage + - energy-full-design-microwatt-hours: battery design energy + - charge-full-design-microamp-hours: battery design capacityLooks fine to me.
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 15
Quoted 5 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-0+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."
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 19
Quoted 3 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +3
-0+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.
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 24
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+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.cThis is also Linux/implementation specific and should be dropped.
We ought to mention how drivers are expected to consume DT:battery.
Quoted 15 lines
Quoted 15 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +15
-0+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>; + ... + }; +
Quoted 8 lines
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-1+ 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 [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Sebastian Reichel
maintainerRe: [PATCH v10 1/8] devicetree: power: Add battery.txt
Hi,
Quoted 3 lines · Liam Breck
Hey Sebastian, welcome back :-)
I've taken over work on this patchset from Matt.
Ok.
Quoted 37 lines · Sebastian Reichel
Quoted 31 lines
Hi Liam & Matt,
Sorry for my absence in the discussion. I skipped the previous iterations for now and start with this version.
Quoted 21 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txtDocumentation/devicetree/bindings/power/supply/battery.txt new file +0
-0Documentation/devicetree/bindings/power/supply/battery.txt line 1
Quoted 1 line
Documentation/devicetree/bindings/power/supply/battery.txt new file +1
-0@@ -0,0 +1,45 @@ +Battery CharacteristicsMaybe add something like
Quoted 4 lines
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).
Quoted 7 lines
OK.
Quoted 2 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 4
Quoted 2 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +2
-0+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.
Quoted 16 lines
Quoted 7 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 9
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+Optional Properties: + - voltage-min-design-microvolt: drained battery voltage + - energy-full-design-microwatt-hours: battery design energy + - charge-full-design-microamp-hours: battery design capacityLooks fine to me.
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 15
Quoted 5 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-0+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.
Quoted 8 lines
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 andpower_supply_propertyto 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.
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 19
Quoted 3 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +3
-0+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.
Quoted 8 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 24
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+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.cThis 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.
Quoted 23 lines
Quoted 23 lines
Quoted 23 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +20
-1+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
Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
Quoted 51 lines · Sebastian Reichel
Hi,
Quoted 3 lines · Liam Breck
Hey Sebastian, welcome back :-)
I've taken over work on this patchset from Matt.
Ok.
Quoted 42 lines · Sebastian Reichel
Quoted 31 lines
Hi Liam & Matt,
Sorry for my absence in the discussion. I skipped the previous iterations for now and start with this version.
Quoted 21 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txtDocumentation/devicetree/bindings/power/supply/battery.txt new file +0
-0Documentation/devicetree/bindings/power/supply/battery.txt line 1
Quoted 1 line
Documentation/devicetree/bindings/power/supply/battery.txt new file +1
-0@@ -0,0 +1,45 @@ +Battery CharacteristicsMaybe add something like
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +2
-0+Required Properties: + - compatible: Must be "fixed-battery"
Quoted 9 lines
Quoted 2 lines
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..
Quoted 63 lines
Quoted 16 lines
Quoted 7 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 9
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+Optional Properties: + - voltage-min-design-microvolt: drained battery voltage + - energy-full-design-microwatt-hours: battery design energy + - charge-full-design-microamp-hours: battery design capacityLooks fine to me.
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 15
Quoted 5 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-0+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.
Quoted 8 lines
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 andpower_supply_propertyto 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.
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 19
Quoted 3 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +3
-0+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.
Quoted 8 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 24
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+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.cThis 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 toDocumentation/power/power_supply_class.txtinstead.Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +15
-0+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>; + ... + }; +
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-1+ 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 [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
Quoted 62 lines · Andrew F. Davis
Quoted 51 lines · Sebastian Reichel
Hi,
Quoted 3 lines · Liam Breck
Hey Sebastian, welcome back :-)
I've taken over work on this patchset from Matt.
Ok.
Quoted 42 lines · Sebastian Reichel
Quoted 31 lines
Hi Liam & Matt,
Sorry for my absence in the discussion. I skipped the previous iterations for now and start with this version.
Quoted 21 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txtDocumentation/devicetree/bindings/power/supply/battery.txt new file +0
-0Documentation/devicetree/bindings/power/supply/battery.txt line 1
Quoted 1 line
Documentation/devicetree/bindings/power/supply/battery.txt new file +1
-0@@ -0,0 +1,45 @@ +Battery CharacteristicsMaybe add something like
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +2
-0+Required Properties: + - compatible: Must be "fixed-battery"Quoted 9 lines
Quoted 2 lines
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.
Quoted 6 lines
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.
Quoted 2 lines
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.
Quoted 71 lines
Quoted 71 lines
Quoted 16 lines
Quoted 7 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 9
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+Optional Properties: + - voltage-min-design-microvolt: drained battery voltage + - energy-full-design-microwatt-hours: battery design energy + - charge-full-design-microamp-hours: battery design capacityLooks fine to me.
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 15
Quoted 5 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-0+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.
Quoted 8 lines
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 andpower_supply_propertyto 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.
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 19
Quoted 3 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +3
-0+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.
Quoted 8 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 24
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+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.cThis 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 toDocumentation/power/power_supply_class.txtinstead.Quoted 23 lines
Quoted 23 lines
Quoted 23 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +20
-1+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
Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
Quoted 70 lines · Liam Breck
Quoted 62 lines · Andrew F. Davis
Quoted 51 lines · Sebastian Reichel
Hi,
Quoted 3 lines · Liam Breck
Hey Sebastian, welcome back :-)
I've taken over work on this patchset from Matt.
Ok.
Quoted 42 lines · Sebastian Reichel
Quoted 31 lines
Hi Liam & Matt,
Sorry for my absence in the discussion. I skipped the previous iterations for now and start with this version.
Quoted 21 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txtDocumentation/devicetree/bindings/power/supply/battery.txt new file +0
-0Documentation/devicetree/bindings/power/supply/battery.txt line 1
Quoted 1 line
Documentation/devicetree/bindings/power/supply/battery.txt new file +1
-0@@ -0,0 +1,45 @@ +Battery CharacteristicsMaybe add something like
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +2
-0+Required Properties: + - compatible: Must be "fixed-battery"Quoted 9 lines
Quoted 2 lines
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.
Quoted 6 lines
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.
Quoted 3 lines
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.
Quoted 6 lines
Quoted 2 lines
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?
Quoted 76 lines
Quoted 63 lines
Quoted 63 lines
Quoted 16 lines
Quoted 7 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 9
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+Optional Properties: + - voltage-min-design-microvolt: drained battery voltage + - energy-full-design-microwatt-hours: battery design energy + - charge-full-design-microamp-hours: battery design capacityLooks fine to me.
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 15
Quoted 5 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-0+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.
Quoted 8 lines
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 andpower_supply_propertyto 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.
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 19
Quoted 3 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +3
-0+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.
Quoted 8 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 24
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+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.cThis 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 toDocumentation/power/power_supply_class.txtinstead.Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +15
-0+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>; + ... + }; +Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-1+ 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
Quoted 75 lines · Andrew F. Davis
Quoted 70 lines · Liam Breck
Quoted 62 lines · Andrew F. Davis
Quoted 51 lines · Sebastian Reichel
Hi,
Quoted 3 lines · Liam Breck
Hey Sebastian, welcome back :-)
I've taken over work on this patchset from Matt.
Ok.
Quoted 42 lines · Sebastian Reichel
Quoted 31 lines
Hi Liam & Matt,
Sorry for my absence in the discussion. I skipped the previous iterations for now and start with this version.
Quoted 21 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txtDocumentation/devicetree/bindings/power/supply/battery.txt new file +0
-0Documentation/devicetree/bindings/power/supply/battery.txt line 1
Quoted 1 line
Documentation/devicetree/bindings/power/supply/battery.txt new file +1
-0@@ -0,0 +1,45 @@ +Battery CharacteristicsMaybe add something like
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +2
-0+Required Properties: + - compatible: Must be "fixed-battery"Quoted 9 lines
Quoted 2 lines
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.
Quoted 6 lines
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.
Quoted 3 lines
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.
Quoted 5 lines
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.
Quoted 9 lines
Quoted 6 lines
Quoted 2 lines
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)...
Quoted 76 lines
Quoted 76 lines
Quoted 63 lines
Quoted 63 lines
Quoted 16 lines
Quoted 7 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 7
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+Optional Properties: + - voltage-min-design-microvolt: drained battery voltage + - energy-full-design-microwatt-hours: battery design energy + - charge-full-design-microamp-hours: battery design capacityLooks fine to me.
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 12
Quoted 5 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-0+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.
Quoted 8 lines
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 andpower_supply_propertyto 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.
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 15
Quoted 3 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +3
-0+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.
Quoted 8 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 19
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+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.cThis 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 toDocumentation/power/power_supply_class.txtinstead.Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +15
-0+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>; + ... + }; +Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-1+ 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): CAKvHMgS92WFoJa=imfAFiEEc0VyiSsDBbuYi4yzZ=LEa7__yKA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
Quoted 82 lines · Liam Breck
Quoted 75 lines · Andrew F. Davis
Quoted 70 lines · Liam Breck
Quoted 62 lines · Andrew F. Davis
Quoted 51 lines · Sebastian Reichel
Hi,
Quoted 3 lines · Liam Breck
Hey Sebastian, welcome back :-)
I've taken over work on this patchset from Matt.
Ok.
Quoted 42 lines · Sebastian Reichel
Quoted 31 lines
Hi Liam & Matt,
Sorry for my absence in the discussion. I skipped the previous iterations for now and start with this version.
Quoted 21 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txtDocumentation/devicetree/bindings/power/supply/battery.txt new file +0
-0Documentation/devicetree/bindings/power/supply/battery.txt line 1
Quoted 1 line
Documentation/devicetree/bindings/power/supply/battery.txt new file +1
-0@@ -0,0 +1,45 @@ +Battery CharacteristicsMaybe add something like
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +2
-0+Required Properties: + - compatible: Must be "fixed-battery"Quoted 9 lines
Quoted 2 lines
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.
Quoted 6 lines
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.
Quoted 3 lines
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.
Quoted 5 lines
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.
Quoted 5 lines
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?
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
Quoted 2 lines
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.
Quoted 8 lines
Quoted 2 lines
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.
Quoted 68 lines
Quoted 68 lines
Quoted 68 lines
Quoted 68 lines
Quoted 68 lines
Quoted 16 lines
Quoted 7 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 7
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+Optional Properties: + - voltage-min-design-microvolt: drained battery voltage + - energy-full-design-microwatt-hours: battery design energy + - charge-full-design-microamp-hours: battery design capacityLooks fine to me.
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 12
Quoted 5 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-0+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.
Quoted 8 lines
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 andpower_supply_propertyto 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.
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 15
Quoted 3 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +3
-0+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.
Quoted 8 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 19
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+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.cThis 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 toDocumentation/power/power_supply_class.txtinstead.Quoted 20 lines
Quoted 20 lines
Quoted 20 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +20
-0+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>; + ... + };
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
--
2.9.3--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] 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 [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v10 1/8] devicetree: power: Add battery.txt
Quoted 89 lines · Andrew F. Davis
Quoted 82 lines · Liam Breck
Quoted 75 lines · Andrew F. Davis
Quoted 70 lines · Liam Breck
Quoted 62 lines · Andrew F. Davis
Quoted 51 lines · Sebastian Reichel
Hi,
Quoted 3 lines · Liam Breck
Hey Sebastian, welcome back :-)
I've taken over work on this patchset from Matt.
Ok.
Quoted 42 lines · Sebastian Reichel
Quoted 31 lines
Hi Liam & Matt,
Sorry for my absence in the discussion. I skipped the previous iterations for now and start with this version.
Quoted 21 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- .../devicetree/bindings/power/supply/battery.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txtDocumentation/devicetree/bindings/power/supply/battery.txt new file +0
-0Documentation/devicetree/bindings/power/supply/battery.txt line 1
Quoted 1 line
Documentation/devicetree/bindings/power/supply/battery.txt new file +1
-0@@ -0,0 +1,45 @@ +Battery CharacteristicsMaybe add something like
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +2
-0+Required Properties: + - compatible: Must be "fixed-battery"Quoted 9 lines
Quoted 2 lines
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.
Quoted 6 lines
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.
Quoted 3 lines
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.
Quoted 5 lines
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.
Quoted 5 lines
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.
Quoted 4 lines
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 :-)
Quoted 23 lines
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
Quoted 2 lines
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.
Quoted 8 lines
Quoted 2 lines
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 -
Quoted 8 lines
| |-> 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.
Quoted 76 lines
Quoted 76 lines
Quoted 76 lines
Quoted 76 lines
Quoted 63 lines
Quoted 63 lines
Quoted 16 lines
Quoted 7 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 7
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+Optional Properties: + - voltage-min-design-microvolt: drained battery voltage + - energy-full-design-microwatt-hours: battery design energy + - charge-full-design-microamp-hours: battery design capacityLooks fine to me.
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 12
Quoted 5 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-0+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.
Quoted 8 lines
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 andpower_supply_propertyto 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.
Quoted 6 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 15
Quoted 3 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +3
-0+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.
Quoted 8 lines
Quoted 6 lines
Documentation/devicetree/bindings/power/supply/battery.txt line 19
Quoted 4 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +4
-0+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.cThis 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 toDocumentation/power/power_supply_class.txtinstead.Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +15
-0+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>; + ... + }; +Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Documentation/devicetree/bindings/power/supply/battery.txt new file +5
-1+ 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v10 3/8 devicetree: power: bq27xxx: Add monitored-battery documentation
In reply to a message not in the archiveFrom: Liam Breck <[email protected]>
Document monitored-battery = <&battery_node>
--- Documentation/devicetree/bindings/power/supply/bq27xxx.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/power/supply/bq27xxx.txt +10 -1
@@ -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>; };
Signature · 6 lines
2.9.3 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 20170315192653.26799-4-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org
Sebastian Reichel
Acked-byRe: [PATCH v10 3/8] devicetree: power: bq27xxx: Add monitored-battery documentation
Quoted 9 lines · Liam Breck
From: Liam Breck <[email protected]>
Document monitored-battery = <
&battery_node>Cc Rob Herring <[email protected]>Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>Acked-by Rob Herring <[email protected]>
-- Sebastian
Quoted 31 lines
--- Documentation/devicetree/bindings/power/supply/bq27xxx.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)Documentation/devicetree/bindings/power/supply/bq27xxx.txt +10
-1@@ -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>; };Signature · 1 line
2.9.3
PATCH v10 2/8 devicetree: property-units: Add uWh and uAh units
In reply to Liam BreckFrom: Matt Ranostay <[email protected]>
Add entries for microwatt-hours and microamp-hours.
--- Documentation/devicetree/bindings/property-units.txt | 2 ++ 1 file changed, 2 insertions(+)
Documentation/devicetree/bindings/property-units.txt +2 -0
@@ -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
Signature · 1 line
2.9.3
PATCH v10 4/8 power: power_supply: Add power_supply_battery_info and API
In reply to Liam BreckFrom: Liam Breck <[email protected]>
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.
--- drivers/power/supply/power_supply_core.c | 40 ++++++++++++++++++++++++++++++++ include/linux/power_supply.h | 18 ++++++++++++++ 2 files changed, 58 insertions(+)
drivers/power/supply/power_supply_core.c +40 -0
@@ -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)
include/linux/power_supply.h +18 -0
@@ -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);
Signature · 1 line
2.9.3
Re: [PATCH v10 4/8] power: power_supply: Add power_supply_battery_info and API
Hi,
Quoted 9 lines · Liam Breck
From: Liam Breck <[email protected]>
power_supply_get_battery_info()reads battery data from devicetree. structpower_supply_battery_infoprovides battery data to drivers. Drivers may surface battery data in sysfs via corresponding POWER_SUPPLY_PROP_* fields.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>
-- Sebastian
Quoted 102 lines
--- drivers/power/supply/power_supply_core.c | 40 ++++++++++++++++++++++++++++++++ include/linux/power_supply.h | 18 ++++++++++++++ 2 files changed, 58 insertions(+)drivers/power/supply/power_supply_core.c +40
-0@@ -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)include/linux/power_supply.h +18
-0@@ -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);Signature · 1 line
2.9.3
PATCH v10 5/8 power: bq27xxx_battery: Define access methods to write chip registers
In reply to Liam BreckFrom: Matt Ranostay <[email protected]>
write(), read_bulk(), write_bulk() support setting chip registers, e.g. with data obtained from power_supply_battery_info.
--- include/linux/power/bq27xxx_battery.h | 3 +++ 1 file changed, 3 insertions(+)
include/linux/power/bq27xxx_battery.h +3 -0
@@ -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 {
Signature · 1 line
2.9.3
PATCH v10 6/8 power: bq27xxx_battery: Keep track of specific chip id
In reply to Liam BreckFrom: Liam Breck <[email protected]>
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.
--- 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(-)
drivers/power/supply/bq27xxx_battery.c +19 -0
@@ -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];
drivers/power/supply/bq27xxx_battery_i2c.c +8 -8
@@ -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);
include/linux/power/bq27xxx_battery.h +18 -7
@@ -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 , };/**
Signature · 1 line
2.9.3
Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
Quoted 8 lines · Liam Breck
From: Liam Breck <[email protected]>
Pass actual chip ID into
_setup(), which translates it to a group ID, to allow support for all chips by thepower_supply_battery_infocode. There are no functional changes to the driver.Signed-off-by Liam Breck <[email protected]>---
What is this patch based on, it doesn't apply to v4.11-rc1 for me.
Quoted 12 lines
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(-)drivers/power/supply/bq27xxx_battery.c +0
-0@@ -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, };
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1031
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +9
-0+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?
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1039
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +8
-0+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.
Quoted 60 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ } +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); di->regs = bq27xxx_regs[di->chip];drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -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);include/linux/power/bq27xxx_battery.h +8
-7@@ -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 */
include/linux/power/bq27xxx_battery.h line 23
Quoted 10 lines
include/linux/power/bq27xxx_battery.h +10
-0+ +/* 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.
Quoted 4 lines
include/linux/power/bq27xxx_battery.h +0
-0};/**
Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
Quoted 11 lines · Andrew F. Davis
Quoted 8 lines · Liam Breck
From: Liam Breck <[email protected]>
Pass actual chip ID into
_setup(), which translates it to a group ID, to allow support for all chips by thepower_supply_battery_infocode. There are no functional changes to the driver.Signed-off-by Liam Breck <[email protected]>---
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
Quoted 13 lines
Quoted 13 lines
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(-)drivers/power/supply/bq27xxx_battery.c +0
-0@@ -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, };
Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1031
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c +9
-0+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.
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1039
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +8
-0+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 ;
Quoted 3 lines
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.
Quoted 65 lines
Quoted 65 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ } +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); di->regs = bq27xxx_regs[di->chip];drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -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);include/linux/power/bq27xxx_battery.h +13
-7@@ -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 ,
Quoted 8 lines
include/linux/power/bq27xxx_battery.h line 23
Quoted 5 lines
include/linux/power/bq27xxx_battery.h +5
-0+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.
Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
Quoted 11 lines · Liam Breck
Quoted 10 lines · Andrew F. Davis
Quoted 8 lines · Liam Breck
From: Liam Breck <[email protected]>
Pass actual chip ID into
_setup(), which translates it to a group ID, to allow support for all chips by thepower_supply_battery_infocode. There are no functional changes to the driver.Signed-off-by Liam Breck <[email protected]>---
Quoted 7 lines
Quoted 1 line
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?
Quoted 122 lines
Quoted 13 lines
Quoted 13 lines
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(-)drivers/power/supply/bq27xxx_battery.c +0
-0@@ -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, };Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1031
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c +9
-0+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.
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1039
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +8
-0+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 ;Quoted 3 lines
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.
Quoted 65 lines
Quoted 65 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ } +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); di->regs = bq27xxx_regs[di->chip];drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -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);include/linux/power/bq27xxx_battery.h +13
-7@@ -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 ,Quoted 8 lines
include/linux/power/bq27xxx_battery.h line 23
Quoted 5 lines
include/linux/power/bq27xxx_battery.h +5
-0+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.
Quoted 4 lines
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.
Quoted 4 lines
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.
Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
Quoted 14 lines · Andrew F. Davis
Quoted 13 lines · Liam Breck
Quoted 11 lines · Andrew F. Davis
Quoted 8 lines · Liam Breck
From: Liam Breck <[email protected]>
Pass actual chip ID into
_setup(), which translates it to a group ID, to allow support for all chips by thepower_supply_battery_infocode. There are no functional changes to the driver.Signed-off-by Liam Breck <[email protected]>---
What is this patch based on, it doesn't apply to v4.11-rc1 for me.
Quoted 7 lines
Quoted 5 lines
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.mboxWho are you asking?
You, if I may impose...
Quoted 122 lines
Quoted 122 lines
Quoted 13 lines
Quoted 13 lines
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(-)drivers/power/supply/bq27xxx_battery.c +0
-0@@ -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, };Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1031
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c +9
-0+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.
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1039
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +8
-0+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 ;Quoted 3 lines
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.
Quoted 73 lines
Quoted 60 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ } +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); di->regs = bq27xxx_regs[di->chip];drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -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);include/linux/power/bq27xxx_battery.h +8
-7@@ -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 */ include/linux/power/bq27xxx_battery.h line 23
Quoted 10 lines
include/linux/power/bq27xxx_battery.h +10
-0+ +/* 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.
Quoted 6 lines
Quoted 4 lines
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.
Quoted 4 lines
Quoted 4 lines
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.
Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
Quoted 21 lines · Liam Breck
Quoted 20 lines · Andrew F. Davis
Quoted 18 lines · Liam Breck
Quoted 11 lines · Andrew F. Davis
Quoted 8 lines · Liam Breck
From: Liam Breck <[email protected]>
Pass actual chip ID into
_setup(), which translates it to a group ID, to allow support for all chips by thepower_supply_battery_infocode. There are no functional changes to the driver.Signed-off-by Liam Breck <[email protected]>---
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
Quoted 4 lines
Quoted 1 line
Who are you asking?
You, if I may impose...
Just rebase on v4.11-rc1...
Quoted 127 lines
Quoted 127 lines
Quoted 126 lines
Quoted 13 lines
Quoted 13 lines
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(-)drivers/power/supply/bq27xxx_battery.c +0
-0@@ -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, };Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1031
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c +9
-0+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.
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1039
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +8
-0+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 ;Quoted 3 lines
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.
Quoted 65 lines
Quoted 65 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ } +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); di->regs = bq27xxx_regs[di->chip];drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -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);include/linux/power/bq27xxx_battery.h +13
-7@@ -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 ,Quoted 8 lines
include/linux/power/bq27xxx_battery.h line 23
Quoted 5 lines
include/linux/power/bq27xxx_battery.h +5
-0+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.
Quoted 5 lines
Quoted 1 line
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.
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
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.
Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
Quoted 156 lines · Andrew F. Davis
Quoted 21 lines · Liam Breck
Quoted 20 lines · Andrew F. Davis
Quoted 18 lines · Liam Breck
Quoted 11 lines · Andrew F. Davis
Quoted 8 lines · Liam Breck
From: Liam Breck <[email protected]>
Pass actual chip ID into
_setup(), which translates it to a group ID, to allow support for all chips by thepower_supply_battery_infocode. There are no functional changes to the driver.Signed-off-by Liam Breck <[email protected]>---
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.mboxQuoted 4 lines
Quoted 1 line
Who are you asking?
You, if I may impose...
Just rebase on v4.11-rc1...
Quoted 127 lines
Quoted 127 lines
Quoted 126 lines
Quoted 13 lines
Quoted 13 lines
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(-)drivers/power/supply/bq27xxx_battery.c +0
-0@@ -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, };Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1031
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c +9
-0+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.
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1039
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +8
-0+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 ;Quoted 3 lines
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.
Quoted 65 lines
Quoted 65 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ } +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); di->regs = bq27xxx_regs[di->chip];drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -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);include/linux/power/bq27xxx_battery.h +13
-7@@ -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 ,Quoted 8 lines
include/linux/power/bq27xxx_battery.h line 23
Quoted 5 lines
include/linux/power/bq27xxx_battery.h +5
-0+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.
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
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?
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
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.
Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
Quoted 159 lines · Liam Breck
Quoted 158 lines · Andrew F. Davis
Quoted 21 lines · Liam Breck
Quoted 20 lines · Andrew F. Davis
Quoted 18 lines · Liam Breck
Quoted 11 lines · Andrew F. Davis
Quoted 8 lines · Liam Breck
From: Liam Breck <[email protected]>
Pass actual chip ID into
_setup(), which translates it to a group ID, to allow support for all chips by thepower_supply_battery_infocode. There are no functional changes to the driver.Signed-off-by Liam Breck <[email protected]>---
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.mboxQuoted 4 lines
Quoted 1 line
Who are you asking?
You, if I may impose...
Just rebase on v4.11-rc1...
Quoted 129 lines
Quoted 128 lines
Quoted 122 lines
Quoted 13 lines
Quoted 13 lines
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(-)drivers/power/supply/bq27xxx_battery.c +0
-0@@ -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, };Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1031
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c +9
-0+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.
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1039
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +8
-0+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 ;Quoted 3 lines
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.
Quoted 65 lines
Quoted 65 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ } +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); di->regs = bq27xxx_regs[di->chip];drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -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);include/linux/power/bq27xxx_battery.h +13
-7@@ -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 ,Quoted 8 lines
include/linux/power/bq27xxx_battery.h line 23
Quoted 5 lines
include/linux/power/bq27xxx_battery.h +5
-0+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.
Quoted 4 lines
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.
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
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_chipenum?
Right now it just assumes the chip is a BQ27000, see line 45 of drivers/w1/slaves/w1_bq27000.c
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
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.
Re: [PATCH v10 6/8] power: bq27xxx_battery: Keep track of specific chip id
Quoted 164 lines · Andrew F. Davis
Quoted 163 lines · Liam Breck
Quoted 162 lines · Andrew F. Davis
Quoted 21 lines · Liam Breck
Quoted 20 lines · Andrew F. Davis
Quoted 18 lines · Liam Breck
Quoted 11 lines · Andrew F. Davis
Quoted 8 lines · Liam Breck
From: Liam Breck <[email protected]>
Pass actual chip ID into
_setup(), which translates it to a group ID, to allow support for all chips by thepower_supply_battery_infocode. There are no functional changes to the driver.Signed-off-by Liam Breck <[email protected]>---
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.mboxQuoted 4 lines
Quoted 1 line
Who are you asking?
You, if I may impose...
Just rebase on v4.11-rc1...
Quoted 132 lines
Quoted 122 lines
Quoted 122 lines
Quoted 13 lines
Quoted 13 lines
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(-)drivers/power/supply/bq27xxx_battery.c +0
-0@@ -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, };Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1031
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c +9
-0+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.
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1039
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +8
-0+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 ;Quoted 3 lines
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.
Quoted 73 lines
Quoted 60 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ } +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); di->regs = bq27xxx_regs[di->chip];drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -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);include/linux/power/bq27xxx_battery.h +8
-7@@ -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 */ include/linux/power/bq27xxx_battery.h line 23
Quoted 10 lines
include/linux/power/bq27xxx_battery.h +10
-0+ +/* 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.
Quoted 6 lines
Quoted 4 lines
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.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
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_chipenum?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[].
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
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.
PATCH v10 7/8 power: bq27xxx_battery: Add power_supply_battery_info support
In reply to Liam BreckFrom: Liam Breck <[email protected]>
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.
--- drivers/power/supply/bq27xxx_battery.c | 478 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 2 files changed, 468 insertions(+), 12 deletions(-)
drivers/power/supply/bq27xxx_battery.c +466 -12
@@ -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);
include/linux/power/bq27xxx_battery.h +2 -0
@@ -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;
Signature · 1 line
2.9.3
Re: [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support
Quoted 242 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 478 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 2 files changed, 468 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +128
-1@@ -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;
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 612
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +7
-0@@ -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.
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 623
Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c +11
-0+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?
Quoted 43 lines
drivers/power/supply/bq27xxx_battery.c +43
-0+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)) {
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 676
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ 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.
Quoted 28 lines
drivers/power/supply/bq27xxx_battery.c +28
-0+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 ;
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 714
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ } + +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.
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+{ +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 {
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 734
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+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.
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 736
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ +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.
Quoted 168 lines
drivers/power/supply/bq27xxx_battery.c +168
-0+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 ; + }
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 914
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ +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.
Quoted 89 lines
drivers/power/supply/bq27xxx_battery.c +29
-11+} +/* * 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);include/linux/power/bq27xxx_battery.h +2
-0@@ -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;
Re: [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support
Quoted 246 lines · Andrew F. Davis
Quoted 245 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 478 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 2 files changed, 468 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +128
-1@@ -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); }
Quoted 13 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 612
Quoted 7 lines
drivers/power/supply/bq27xxx_battery.c +7
-0+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.
Quoted 65 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 623
Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c +11
-0+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?
Quoted 49 lines
drivers/power/supply/bq27xxx_battery.c +49
-0+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;
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 676
Quoted 4 lines
drivers/power/supply/bq27xxx_battery.c +4
-0+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.
Quoted 34 lines
Quoted 34 lines
drivers/power/supply/bq27xxx_battery.c +34
-0+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;
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 714
Quoted 4 lines
drivers/power/supply/bq27xxx_battery.c +4
-0+} + +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.
Quoted 14 lines
Quoted 14 lines
drivers/power/supply/bq27xxx_battery.c +14
-0+{ +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;
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 734
Quoted 6 lines
drivers/power/supply/bq27xxx_battery.c +6
-0+ }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.
Quoted 6 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 736
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ +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.
Quoted 172 lines
Quoted 172 lines
drivers/power/supply/bq27xxx_battery.c +172
-0+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 )
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 914
Quoted 6 lines
drivers/power/supply/bq27xxx_battery.c +6
-0+ 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.
Quoted 89 lines
Quoted 89 lines
drivers/power/supply/bq27xxx_battery.c +29
-11+} +/* * 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);include/linux/power/bq27xxx_battery.h +2
-0@@ -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;
Re: [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support
Quoted 261 lines · Liam Breck
Quoted 246 lines · Andrew F. Davis
Quoted 245 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 478 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 2 files changed, 468 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +128
-1@@ -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); }Quoted 13 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 612
Quoted 7 lines
drivers/power/supply/bq27xxx_battery.c +7
-0+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.
Quoted 2 lines
OK. And for bus.{read,write}_bulk() too? They only occur once.
Sure, why not
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c +11
-0+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; + }
Quoted 4 lines
Quoted 4 lines
+space
Has this been run through checkpatch?
Well...
Quoted 58 lines
Quoted 49 lines
Quoted 49 lines
drivers/power/supply/bq27xxx_battery.c +49
-0+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;Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 676
Quoted 4 lines
drivers/power/supply/bq27xxx_battery.c +4
-0+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.
Quoted 1 line
Knowing which bus op failed doesn't help.
Sure it does, knowing which step it fails or locks the chip is useful.
Quoted 47 lines
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.Quoted 34 lines
Quoted 34 lines
drivers/power/supply/bq27xxx_battery.c +34
-0+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;Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 714
Quoted 4 lines
drivers/power/supply/bq27xxx_battery.c +4
-0+} + +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.
Quoted 4 lines
You can enter or exit cfgupdate mode. We do the same for
set_seal_state(). Andbq27xxx_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.
Quoted 23 lines
Quoted 14 lines
Quoted 14 lines
drivers/power/supply/bq27xxx_battery.c +14
-0+{ +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;Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 734
Quoted 6 lines
drivers/power/supply/bq27xxx_battery.c +6
-0+ }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.
Quoted 2 lines
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.
Quoted 9 lines
Quoted 6 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 736
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ +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?
Quoted 272 lines
Quoted 172 lines
Quoted 172 lines
drivers/power/supply/bq27xxx_battery.c +172
-0+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 )Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 914
Quoted 6 lines
drivers/power/supply/bq27xxx_battery.c +6
-0+ 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.
Quoted 89 lines
Quoted 89 lines
drivers/power/supply/bq27xxx_battery.c +29
-11+} +/* * 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);include/linux/power/bq27xxx_battery.h +2
-0@@ -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;
Re: [PATCH v10 7/8] power: bq27xxx_battery: Add power_supply_battery_info support
Quoted 262 lines · Andrew F. Davis
Quoted 261 lines · Liam Breck
Quoted 259 lines · Andrew F. Davis
Quoted 242 lines · Liam Breck
From: Liam Breck <[email protected]>
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 <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 478 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 2 files changed, 468 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +128
-1@@ -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;drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 612
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +7
-0@@ -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.
Quoted 4 lines
Quoted 2 lines
OK. And for bus.{read,write}_bulk() too? They only occur once.
Sure, why not
OK
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines
drivers/power/supply/bq27xxx_battery.c +11
-0+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; + }
Quoted 1 line
Quoted 1 line
Quoted 1 line
+space
Where?
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Has this been run through checkpatch?
Well...
I defer newline formatting if things are in-flux.
Quoted 58 lines
Quoted 58 lines
Quoted 57 lines
Quoted 43 lines
drivers/power/supply/bq27xxx_battery.c +43
-0+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)) {drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 676
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ 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.
Quoted 3 lines
Quoted 1 line
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.
Quoted 47 lines
Quoted 47 lines
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.Quoted 42 lines
Quoted 28 lines
drivers/power/supply/bq27xxx_battery.c +28
-0+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 ;drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 714
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ } + +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.
Quoted 8 lines
Quoted 4 lines
You can enter or exit cfgupdate mode. We do the same for
set_seal_state(). Andbq27xxx_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)
Quoted 23 lines
Quoted 23 lines
Quoted 22 lines
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+{ +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 {drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 734
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+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.
Quoted 6 lines
Quoted 2 lines
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.
Quoted 11 lines
Quoted 9 lines
Quoted 6 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 736
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+ +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?
Quoted 272 lines
Quoted 272 lines
Quoted 172 lines
Quoted 172 lines
drivers/power/supply/bq27xxx_battery.c +172
-0+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 )Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, · line 914
Quoted 6 lines
drivers/power/supply/bq27xxx_battery.c +6
-0+ 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.
Quoted 89 lines
Quoted 89 lines
drivers/power/supply/bq27xxx_battery.c +29
-11+} +/* * 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);include/linux/power/bq27xxx_battery.h +2
-0@@ -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;
PATCH v10 8/8 power: bq27xxx_battery_i2c: Add I2C bulk read/write functions
In reply to Liam BreckFrom: Matt Ranostay <[email protected]>
write(), read_bulk(), write_bulk() are required by bq27xxx_battery power_supply_battery_info code.
--- drivers/power/supply/bq27xxx_battery_i2c.c | 82 +++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-)
drivers/power/supply/bq27xxx_battery_i2c.c +81 -1
@@ -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)
Signature · 1 line
2.9.3
Sebastian Reichel
maintainerRe: [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions
Hi,
Quoted 7 lines · Liam Breck
From: Matt Ranostay <[email protected]>
write(),read_bulk(),write_bulk()are required bybq27xxx_batterypower_supply_battery_infocode.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>
This is required by the previous patch, so your order is not bisect safe. Please just merge it with Patch 5.
-- Sebastian
Quoted 114 lines
drivers/power/supply/bq27xxx_battery_i2c.c | 82 +++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-)drivers/power/supply/bq27xxx_battery_i2c.c +81
-1@@ -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)Signature · 1 line
2.9.3
Re: [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions
Quoted 5 lines · Sebastian Reichel
Hi,
Quoted 2 lines · Liam Breck
From: Matt Ranostay <[email protected]>
Quoted 8 lines
Quoted 5 lines
write(),read_bulk(),write_bulk()are required bybq27xxx_batterypower_supply_battery_infocode.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>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.
Quoted 114 lines
Quoted 114 lines
drivers/power/supply/bq27xxx_battery_i2c.c | 82 +++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-)drivers/power/supply/bq27xxx_battery_i2c.c +81
-2@@ -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
Sebastian Reichel
maintainerRe: [PATCH v10 8/8] power: bq27xxx_battery_i2c: Add I2C bulk read/write functions
Hi,
Quoted 9 lines · Liam Breck
Quoted 8 lines · Sebastian Reichel
Hi,
Quoted 5 lines · Liam Breck
From: Matt Ranostay <[email protected]>
write(),read_bulk(),write_bulk()are required bybq27xxx_batterypower_supply_battery_infocode.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>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_batteryonly uses the functions if available.
ok.
Quoted 2 lines
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