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