devicetree simple-battery and client in bq27xxx_battery
Subsystems (5)
v13 cover devicetree simple-battery and client in bq27xxx_battery
Overview:
* new devicetree battery node specifies static battery data
* fuel gauge and charger nodes shall use monitored-battery=<&battery_node>
* new power_supply_get_battery_info() reads battery data from devicetree
* new struct power_supply_battery_info provides battery data to drivers
* drivers surface battery data in sysfs via related power_supply_prop_* fields
* bq27xxx driver calls the above and writes battery data to RAM/NVM for params essential to correct operation: energy-full-design-microwatt-hours, charge-full-design-microamp-hours, voltage-min-design-microvolt
Changes in v13:
Doc...bindings/power/supply/*
* add fields in battery.txt, see below * caution about changing battery type in battery.txt * note: Rob acked v11 battery.txt containing URL to Linux header * more detail in bq27xxx.txt
power_supply_core:
* add battery_info fields precharge-current-microamp & charge-term-current-microamp
* new patch for power_supply_prop_precharge_current
bq27xxx_battery:
* add copyright notice * for flash/NVM chips, emit warning instead of doing update * config_battery_bq27xxx_dt_updates_nvm enables update of flash/NVM * module param dt_monitored_battery_updates_nvm lets user disallow update * new patch to flag dupes in bq27xxx_regs[] * drop patch to clean up error reporting * polishing from Andrew's feedback * resolve checkpatch errors * refactor patchset * fix missing static keyword flagged by Colin
Changes in v12: (several partial series posts; see above)
Changes in v11:
power_supply_core:
* switch to compatible = "simple-battery"
* add docs to power_supply_class.txt
Documentation/devicetree/.../battery.txt:
* add description, drop refs to Linux, "simple-battery"
bq27xxx_battery:
* reset flash chips after DM update * add bq27xxx_write/xfer() * polishing from Andrew's feedback * new patch to clean up error reporting * new patch to consolidate duplicate register/property arrays
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 Breck (9):
dt-bindings: power: supply: Add battery.txt with simple-battery binding
power: supply: core: Add power_supply_battery_info and API
power: supply: core: Add power_supply_prop_precharge
dt-bindings: power: supply: bq27xxx: Add monitored-battery documentation
power: supply: bq27xxx_battery: Add chip data memory read/write support
power: supply: bq27xxx_battery: Add power_supply_battery_info support
power: supply: bq27xxx_battery: Enable data memory update for certain chips
power: supply: bq27xxx_battery: Flag identical register maps when in debug mode
power: supply: bq27xxx_battery: Remove duplicate register arrays
Matt Ranostay (2):
devicetree: property-units: Add uWh and uAh units
power: supply: bq27xxx_battery: Add bulk transfer bus methods
.../devicetree/bindings/power/supply/battery.txt | 53 ++ .../devicetree/bindings/power/supply/bq27xxx.txt | 31 +- .../devicetree/bindings/property-units.txt | 2 + Documentation/power/power_supply_class.txt | 31 +- drivers/power/supply/Kconfig | 9 + drivers/power/supply/bq27xxx_battery.c | 750 +++++++++++++++++---- drivers/power/supply/bq27xxx_battery_i2c.c | 98 ++- drivers/power/supply/power_supply_core.c | 51 ++ drivers/power/supply/power_supply_sysfs.c | 1 + include/linux/power/bq27xxx_battery.h | 29 +- include/linux/power_supply.h | 23 + 11 files changed, 920 insertions(+), 158 deletions(-) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
Signature · 1 line
2.9.3
PATCH v13 1/11 devicetree: property-units: Add uWh and uAh units
From: Matt Ranostay <[email protected]>
Add entries for microwatt-hours and microamp-hours.
--- Documentation/devicetree/bindings/property-units.txt | 2 ++ 1 file changed, 2 insertions(+)
Documentation/devicetree/bindings/property-units.txt +2 -0
@@ -25,8 +25,10 @@ Distance Electricity ---------------------------------------- -microamp : micro amps +-microamp-hours : micro amp-hours -ohms : Ohms -micro-ohms : micro Ohms +-microwatt-hours: micro Watt-hours -microvolt : micro volts Temperature
Signature · 6 lines
2.9.3 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v13 2/11 dt-bindings: power: supply: Add battery.txt with simple-battery binding
In reply to Liam BreckFrom: Liam Breck <[email protected]>
Documentation of static battery characteristics that can be defined for batteries that do not embed this data, which are required by fuel-gauge and charger chips for proper handling of the battery.
The following properties are defined:
voltage-min-design-microvolt
charge-full-design-microamp-hours
energy-full-design-microwatt-hours
precharge-current-microamp
charge-term-current-microamp
Property names are derived from corresponding elements in enum power_supply_property from include/linux/power_supply.h
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/power_supply.h
--- .../devicetree/bindings/power/supply/battery.txt | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/battery.txt
Documentation/devicetree/bindings/power/supply/battery.txt new file +53 -0
@@ -0,0 +1,53 @@ +Battery Characteristics + +The devicetree battery node provides static battery characteristics. +In smart batteries, these are typically stored in non-volatile memory +on a fuel gauge chip. The battery node should be used where there is +no appropriate non-volatile memory, or it is unprogrammed/incorrect. + +Upstream dts files should not include battery nodes, unless the battery +represented cannot easily be replaced in the system by one of a +different type. This prevents unpredictable, potentially harmful, +behavior should a replacement that changes the battery type occur +without a corresponding update to the dtb. + +Required Properties: + - compatible: Must be "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 + - precharge-current-microamp: current for pre-charge phase + - charge-term-current-microamp: current for charge termination phase + +Battery properties are named, where possible, for the corresponding +elements in enum power_supply_property, defined in +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/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". + +Example: + + bat: battery { + compatible = "simple-battery"; + voltage-min-design-microvolt = <3200000>; + energy-full-design-microwatt-hours = <5290000>; + charge-full-design-microamp-hours = <1430000>; + precharge-current-microamp = <256000>; + charge-term-current-microamp = <128000>; + }; + + charger: charger@11 { + .... + monitored-battery = <&bat>; + ... + }; + + fuel_gauge: fuel-gauge@22 { + .... + monitored-battery = <&bat>; + ... + };
Signature · 1 line
2.9.3
A message that is not in the archive (sent off-list or not yet received): 20170504061811.18107-1-liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn@public.gmane.org
PATCH v13 5/11 dt-bindings: power: supply: bq27xxx: Add monitored-battery documentation
From: Liam Breck <[email protected]>
Document monitored-battery = <&battery_node>
--- .../devicetree/bindings/power/supply/bq27xxx.txt | 31 +++++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-)
Documentation/devicetree/bindings/power/supply/bq27xxx.txt +24 -7
@@ -1,7 +1,7 @@ -Binding for TI BQ27XXX fuel gauge family +TI BQ27XXX fuel gauge family Required properties: -- compatible: Should contain one of the following: +- compatible: contains one of the following: * "ti,bq27200" - BQ27200 * "ti,bq27210" - BQ27210 * "ti,bq27500" - deprecated, use revision specific property below
@@ -26,11 +26,28 @@ Required properties: * "ti,bq27425" - BQ27425 * "ti,bq27441" - BQ27441 * "ti,bq27621" - BQ27621 -- reg: integer, i2c address of the device. +- reg: integer, I2C address of the fuel gauge. + +Optional properties: +- monitored-battery: phandle of battery characteristics node + The fuel gauge uses the following battery properties: + + energy-full-design-microwatt-hours + + charge-full-design-microamp-hours + + voltage-min-design-microvolt + Both or neither of the *-full-design-*-hours properties must be set. + See Documentation/devicetree/bindings/power/supply/battery.txt Example: -bq27510g3 { - compatible = "ti,bq27510g3"; - reg = <0x55>; -}; + bat: battery { + compatible = "simple-battery"; + voltage-min-design-microvolt = <3200000>; + energy-full-design-microwatt-hours = <5290000>; + charge-full-design-microamp-hours = <1430000>; + }; + + bq27510g3: fuel-gauge@55 { + compatible = "ti,bq27510g3"; + reg = <0x55>; + monitored-battery = <&bat>; + };
Signature · 6 lines
2.9.3 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v13 3/11 power: supply: core: Add power_supply_battery_info and API
In reply to Liam BreckFrom: Liam Breck <[email protected]>
power_supply_get_battery_info() reads battery data from devicetree. struct power_supply_battery_info provides battery data to drivers. Its fields correspond to elements in enum power_supply_property. Drivers may surface battery data in sysfs via corresponding POWER_SUPPLY_PROP_* fields.
--- Documentation/power/power_supply_class.txt | 12 +++++++ drivers/power/supply/power_supply_core.c | 51 ++++++++++++++++++++++++++++++ include/linux/power_supply.h | 20 ++++++++++++ 3 files changed, 83 insertions(+)
Documentation/power/power_supply_class.txt +12 -0
@@ -174,6 +174,18 @@ issued by external power supply will notify supplicants via external_power_changed callback. +Devicetree battery characteristics +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Drivers should call power_supply_get_battery_info() to obtain battery +characteristics from a devicetree battery node, defined in +Documentation/devicetree/bindings/power/supply/battery.txt. This is +implemented in drivers/power/supply/bq27xxx_battery.c. + +Properties in struct power_supply_battery_info and their counterparts in the +battery node have names corresponding to elements in enum power_supply_property, +for naming consistency between sysfs attributes and battery node properties. + + QA ~~ Q: Where is POWER_SUPPLY_PROP_XYZ attribute?
drivers/power/supply/power_supply_core.c +51 -0
63 lines not on this page · raw message
include/linux/power_supply.h +20 -0
@@ -288,6 +288,23 @@ 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 */ +int precharge_current_ua;/* microAmps */ +int charge_term_current_ua;/* microAmps */ +}; +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 +323,9 @@ static inline struct power_supply * devm_power_supply_get_by_phandle(struct device *dev, const char *property) {return NULL ; }#endif /* CONFIG_OF */ + +extern int power_supply_get_battery_info (struct power_supply *psy, +struct power_supply_battery_info *info);extern void power_supply_changed (struct power_supply *psy);extern int power_supply_am_i_supplied (struct power_supply *psy);extern int power_supply_set_battery_charged (struct power_supply *psy);
Signature · 1 line
2.9.3
PATCH v13 4/11 power: supply: core: Add power_supply_prop_precharge
In reply to Liam BreckFrom: Liam Breck <[email protected]>
Battery chargers use POWER_SUPPLY_PROP_PRECHARGE_CURRENT Clarify related item POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT
--- Documentation/power/power_supply_class.txt | 19 ++++++++++++------- drivers/power/supply/power_supply_sysfs.c | 1 + include/linux/power_supply.h | 3 +++ 3 files changed, 16 insertions(+), 7 deletions(-)
Documentation/power/power_supply_class.txt +12 -7
@@ -115,28 +115,33 @@ of charge when battery became full/empty". It also could mean "value of charge when battery considered full/empty at given conditions (temperature, age)". I.e. these attributes represents real thresholds, not design values. +ENERGY_FULL, ENERGY_EMPTY - same as above but for energy. + CHARGE_COUNTER - the current charge counter (in µAh). This could easily be negative; there is no empty or full value. It is only useful for relative, time-based measurements. +PRECHARGE_CURRENT - the maximum charge current during precharge phase +of charge cycle (typically 20% of battery capacity). +CHARGE_TERM_CURRENT - Charge termination current. The charge cycle +terminates when battery voltage is above recharge threshold, and charge +current is below this setting (typically 10% of battery capacity). + CONSTANT_CHARGE_CURRENT - constant charge current programmed by charger. CONSTANT_CHARGE_CURRENT_MAX - maximum charge current supported by the power supply object. -INPUT_CURRENT_LIMIT - input current limit programmed by charger. Indicates -the current drawn from a charging source. -CHARGE_TERM_CURRENT - Charge termination current used to detect the end of charge -condition. - -CALIBRATE - battery or coulomb counter calibration status CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger. CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the power supply object. +INPUT_CURRENT_LIMIT - input current limit programmed by charger. Indicates +the current drawn from a charging source. + CHARGE_CONTROL_LIMIT - current charge control limit setting CHARGE_CONTROL_LIMIT_MAX - maximum charge control limit setting -ENERGY_FULL, ENERGY_EMPTY - same as above but for energy. +CALIBRATE - battery or coulomb counter calibration status CAPACITY - capacity in percents. CAPACITY_ALERT_MIN - minimum capacity alert value in percents.
drivers/power/supply/power_supply_sysfs.c +1 -0
@@ -196,6 +196,7 @@ static struct device_attribute power_supply_attrs[] = {POWER_SUPPLY_ATTR (time_to_full_avg),POWER_SUPPLY_ATTR (type),POWER_SUPPLY_ATTR (scope), +POWER_SUPPLY_ATTR (precharge_current),POWER_SUPPLY_ATTR (charge_term_current), POWER_SUPPLY_ATTR(calibrate),/* Properties of type `const char *' */
include/linux/power_supply.h +3 -0
@@ -146,6 +146,7 @@ enum power_supply_property {POWER_SUPPLY_PROP_TIME_TO_FULL_AVG ,POWER_SUPPLY_PROP_TYPE ,/* use power_supply.type instead */ POWER_SUPPLY_PROP_SCOPE , +POWER_SUPPLY_PROP_PRECHARGE_CURRENT ,POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT , POWER_SUPPLY_PROP_CALIBRATE,/* Properties of type `const char *' */
@@ -379,6 +380,8 @@ static inline bool power_supply_is_amp_property(enum power_supply_property psp)case POWER_SUPPLY_PROP_CHARGE_NOW :case POWER_SUPPLY_PROP_CHARGE_AVG :case POWER_SUPPLY_PROP_CHARGE_COUNTER : +case POWER_SUPPLY_PROP_PRECHARGE_CURRENT : +case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT :case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT :case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX :case POWER_SUPPLY_PROP_CURRENT_MAX :
Signature · 1 line
2.9.3
PATCH v13 6/11 power: supply: bq27xxx_battery: Add bulk transfer bus methods
In reply to Liam BreckFrom: Matt Ranostay <[email protected]>
Declare bus.write/read_bulk/write_bulk().
Add I2C write/read_bulk/write_bulk() to implement the above. Add bq27xxx_write/read_block/write_block() helpers to call the above.
--- drivers/power/supply/bq27xxx_battery.c | 67 +++++++++++++++++++++++- drivers/power/supply/bq27xxx_battery_i2c.c | 82 +++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 3 ++ 3 files changed, 149 insertions(+), 3 deletions(-)
drivers/power/supply/bq27xxx_battery.c +65 -2
@@ -794,11 +794,74 @@ MODULE_PARM_DESC(poll_interval,static inline int bq27xxx_read (struct bq27xxx_device_info *di,int reg_index,bool single) { -/* Reports EINVAL for invalid/missing registers */ +int ret; +if (!di || di->regs[reg_index] ==INVALID_REG_ADDR )return -EINVAL ; -return di->bus.read (di, di->regs[reg_index], single); + ret = di->bus.read (di, di->regs[reg_index], single); +if (ret <0 ) +dev_dbg (di->dev,"failed to read register 0x%02x (index %d)\n" , + di->regs[reg_index], reg_index); + +return ret; +} + +static inline int bq27xxx_write (struct bq27xxx_device_info *di,int reg_index, +u16 value,bool single) +{ +int ret; + +if (!di || di->regs[reg_index] ==INVALID_REG_ADDR ) +return -EINVAL ; + +if (!di->bus.write) +return -EPERM ; + + ret = di->bus.write (di, di->regs[reg_index], value, single); +if (ret <0 ) +dev_dbg (di->dev,"failed to write register 0x%02x (index %d)\n" , + di->regs[reg_index], reg_index); + +return ret; +} + +static inline int bq27xxx_read_block (struct bq27xxx_device_info *di,int reg_index, +u8 *data,int len) +{ +int ret; + +if (!di || di->regs[reg_index] ==INVALID_REG_ADDR ) +return -EINVAL ; + +if (!di->bus.read_bulk) +return -EPERM ; + + ret = di->bus.read_bulk (di, di->regs[reg_index], data, len); +if (ret <0 ) +dev_dbg (di->dev,"failed to read_bulk register 0x%02x (index %d)\n" , + di->regs[reg_index], reg_index); + +return ret; +} + +static inline int bq27xxx_write_block (struct bq27xxx_device_info *di,int reg_index, +u8 *data,int len) +{ +int ret; + +if (!di || di->regs[reg_index] ==INVALID_REG_ADDR ) +return -EINVAL ; + +if (!di->bus.write_bulk) +return -EPERM ; + + ret = di->bus.write_bulk (di, di->regs[reg_index], data, len); +if (ret <0 ) +dev_dbg (di->dev,"failed to write_bulk register 0x%02x (index %d)\n" , + di->regs[reg_index], reg_index); + +return ret; }/*
drivers/power/supply/bq27xxx_battery_i2c.c +81 -1
101 lines not on this page · raw message
include/linux/power/bq27xxx_battery.h +3 -0
@@ -40,6 +40,9 @@ struct bq27xxx_platform_data {struct bq27xxx_device_info ;struct bq27xxx_access_methods {int (*read)(struct bq27xxx_device_info *di,u8 reg,bool single); +int (*write)(struct bq27xxx_device_info *di,u8 reg,int value,bool single); +int (*read_bulk)(struct bq27xxx_device_info *di,u8 reg,u8 *data,int len); +int (*write_bulk)(struct bq27xxx_device_info *di,u8 reg,u8 *data,int len); };struct bq27xxx_reg_cache {
Signature · 1 line
2.9.3
PATCH v13 7/11 power: supply: bq27xxx_battery: Add chip data memory read/write support
In reply to Liam BreckFrom: Liam Breck <[email protected]>
Add these to enable read/write of chip data memory RAM/NVM/flash:
bq27xxx_battery_seal()
bq27xxx_battery_unseal() bq27xxx_battery_set_cfgupdate() bq27xxx_battery_read_dm_block() bq27xxx_battery_write_dm_block() bq27xxx_battery_checksum_dm_block()
--- drivers/power/supply/bq27xxx_battery.c | 253 +++++++++++++++++++++++++++++++++ include/linux/power/bq27xxx_battery.h | 1 + 2 files changed, 254 insertions(+)
drivers/power/supply/bq27xxx_battery.c +253 -0
@@ -5,6 +5,7 @@* Copyright (C) 2008 Eurotech S.p.A. <[email protected]> * Copyright (C) 2010-2011 Lars-Peter Clausen <[email protected]> * Copyright (C) 2011 Pali Rohár <[email protected]> +* Copyright (C) 2017 Liam Breck <[email protected]> * * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. *
@@ -65,6 +66,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)
@@ -78,6 +80,12 @@#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_RESET 0x41 +#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 */
@@ -108,9 +116,21 @@ enum bq27xxx_reg_index {BQ27XXX_REG_SOC ,/* State-of-Charge */ BQ27XXX_REG_DCAP ,/* Design Capacity */ BQ27XXX_REG_AP ,/* Average Power */ +BQ27XXX_DM_CTRL ,/* Block Data Control */ +BQ27XXX_DM_CLASS ,/* Data Class */ +BQ27XXX_DM_BLOCK ,/* Data Block */ +BQ27XXX_DM_DATA ,/* Block Data */ +BQ27XXX_DM_CKSUM ,/* Block Data Checksum */ BQ27XXX_REG_MAX, /* sentinel */ }; +#define BQ27XXX_DM_REG_ROWS \ + [BQ27XXX_DM_CTRL] = 0x61, \ + [BQ27XXX_DM_CLASS] = 0x3e, \ + [BQ27XXX_DM_BLOCK] = 0x3f, \ + [BQ27XXX_DM_DATA] = 0x40, \ + [BQ27XXX_DM_CKSUM] = 0x60 +/* Register mappings */ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { [BQ27000 ] = {
@@ -131,6 +151,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 ,
@@ -150,6 +175,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 , }, [BQ2750X] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -169,6 +199,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ2751X] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -188,6 +219,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27500] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -207,6 +239,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -226,6 +259,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -245,6 +279,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -264,6 +299,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -283,6 +319,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -302,6 +339,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -321,6 +359,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G4] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -340,6 +379,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27530] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -359,6 +399,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27541] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -378,6 +419,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27545] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -397,6 +439,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27421] = { [BQ27XXX_REG_CTRL ] =0x00 ,
@@ -416,6 +459,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x1c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP] = 0x18, + BQ27XXX_DM_REG_ROWS, }, };
@@ -757,6 +801,28 @@ static struct {static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices); +#define BQ27XXX_MSLEEP (i) usleep_range((i)*1000, (i)*1000+500) + +#define BQ27XXX_DM_SZ 32 + +/** +* struct bq27xxx_dm_buf - chip data memory buffer +* @class: data memory subclass_id +* @block: data memory block number +* @data: data from/for the block +* @has_data: true if data has been filled by read +* @dirty: true if data has changed since last read/write +* +* Encapsulates info required to manage chip data memory blocks. +*/ +struct bq27xxx_dm_buf { +u8 class; +u8 block; +u8 data[BQ27XXX_DM_SZ ]; +bool has_data, dirty; +}; + +static int poll_interval_param_set (const char *val,const struct kernel_param *kp) {struct bq27xxx_device_info *di;
@@ -864,6 +930,193 @@ static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_inreturn ret; } +static int bq27xxx_battery_seal (struct bq27xxx_device_info *di) +{ +int ret; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL ,BQ27XXX_SEALED , false); +if (ret <0 ) { +dev_err (di->dev,"bus error on seal: %d\n" , ret); +return ret; + } + +return 0 ; +} + +static int bq27xxx_battery_unseal (struct bq27xxx_device_info *di) +{ +int ret; + +if (di->unseal_key ==0 ) { +dev_err (di->dev,"unseal failed due to missing key\n" ); +return -EINVAL ; + } + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16)(di->unseal_key >>16 ), false); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16 )di->unseal_key, false); +if (ret <0 ) + goto out; + +return 0 ; + +out: +dev_err (di->dev,"bus error on unseal: %d\n" , 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->data[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; + + buf->has_data = false; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_read_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret =bq27xxx_read (di,BQ27XXX_DM_CKSUM , true); +if (ret <0 ) + goto out; + +if ((u8 )ret !=bq27xxx_battery_checksum_dm_block (buf)) { + ret = -EINVAL ; + goto out; + } + + buf->has_data = true; + buf->dirty = false; + +return 0 ; + +out: +dev_err (di->dev,"bus error reading chip memory: %d\n" , ret); +return ret; +} + +static int bq27xxx_battery_set_cfgupdate (struct bq27xxx_device_info *di,u16 state) +{ +const int limit =100 ; +int ret, try = limit; + + ret =bq27xxx_write (di,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 (limit-try >3 ) +dev_warn (di->dev,"cfgupdate %d, retries %d\n" , !!state, limit-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->dirty) +return 0 ; + +if (cfgup) { + ret =bq27xxx_battery_set_cfgupdate (di,BQ27XXX_FLAG_CFGUP ); +if (ret <0 ) +return ret; + } + + ret =bq27xxx_write (di,BQ27XXX_DM_CTRL ,0 , true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_write_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_CKSUM , +bq27xxx_battery_checksum_dm_block (buf), true); +if (ret <0 ) + goto out; + +/* DO NOT read BQ27XXX_DM_CKSUM here to verify it! That may cause NVM +* corruption on the '425 chip (and perhaps others), which can damage +* the chip. See TI bqtool for what not to do: +* http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328 +*/ + +if (cfgup) { +BQ27XXX_MSLEEP (1 ); + ret =bq27xxx_battery_set_cfgupdate (di,0 ); +if (ret <0 ) +return ret; + }else { +BQ27XXX_MSLEEP (100 );/* flash DM updates in <100ms */ + } + + buf->dirty = false; + +return 0 ; + +out: +if (cfgup) +bq27xxx_battery_set_cfgupdate (di,0 ); + +dev_err (di->dev,"bus error writing chip memory: %d\n" , ret); +return ret; +} +/* * Return the battery State-of-Charge * Or < 0 if something fails.
include/linux/power/bq27xxx_battery.h +1 -0
@@ -64,6 +64,7 @@ struct bq27xxx_device_info {int id;enum bq27xxx_chip chip;const char *name; +u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;int charge_design_full;
Signature · 1 line
2.9.3
Re: [PATCH v13 07/11] power: supply: bq27xxx_battery: Add chip data memory read/write support
Quoted 321 lines · Liam Breck
From: Liam Breck <[email protected]>
Add these to enable read/write of chip data memory RAM/NVM/flash:
bq27xxx_battery_seal()
bq27xxx_battery_unseal()bq27xxx_battery_set_cfgupdate()bq27xxx_battery_read_dm_block()bq27xxx_battery_write_dm_block()bq27xxx_battery_checksum_dm_block()Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 253 +++++++++++++++++++++++++++++++++ include/linux/power/bq27xxx_battery.h | 1 + 2 files changed, 254 insertions(+)drivers/power/supply/bq27xxx_battery.c +146
-0@@ -5,6 +5,7 @@* Copyright (C) 2008 Eurotech S.p.A. <[email protected]> * Copyright (C) 2010-2011 Lars-Peter Clausen <[email protected]> * Copyright (C) 2011 Pali Rohár <[email protected]> +* Copyright (C) 2017 Liam Breck <[email protected]> * * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. * @@ -65,6 +66,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)@@ -78,6 +80,12 @@#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_RESET 0x41 +#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 */ @@ -108,9 +116,21 @@ enum bq27xxx_reg_index {BQ27XXX_REG_SOC ,/* State-of-Charge */ BQ27XXX_REG_DCAP ,/* Design Capacity */ BQ27XXX_REG_AP ,/* Average Power */ +BQ27XXX_DM_CTRL ,/* Block Data Control */ +BQ27XXX_DM_CLASS ,/* Data Class */ +BQ27XXX_DM_BLOCK ,/* Data Block */ +BQ27XXX_DM_DATA ,/* Block Data */ +BQ27XXX_DM_CKSUM ,/* Block Data Checksum */ BQ27XXX_REG_MAX, /* sentinel */ }; +#define BQ27XXX_DM_REG_ROWS \ + [BQ27XXX_DM_CTRL] = 0x61, \ + [BQ27XXX_DM_CLASS] = 0x3e, \ + [BQ27XXX_DM_BLOCK] = 0x3f, \ + [BQ27XXX_DM_DATA] = 0x40, \ + [BQ27XXX_DM_CKSUM] = 0x60 +/* Register mappings */ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { [BQ27000 ] = {@@ -131,6 +151,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 ,@@ -150,6 +175,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 , }, [BQ2750X] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -169,6 +199,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ2751X] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -188,6 +219,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27500] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -207,6 +239,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -226,6 +259,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -245,6 +279,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -264,6 +299,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -283,6 +319,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -302,6 +339,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -321,6 +359,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G4] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -340,6 +379,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27530] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -359,6 +399,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27541] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -378,6 +419,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27545] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -397,6 +439,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27421] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -416,6 +459,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x1c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP] = 0x18, + BQ27XXX_DM_REG_ROWS, }, };@@ -757,6 +801,28 @@ static struct {static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices); +#define BQ27XXX_MSLEEP (i) usleep_range((i)*1000, (i)*1000+500) + +#define BQ27XXX_DM_SZ 32 + +/** +* struct bq27xxx_dm_buf - chip data memory buffer +* @class: data memory subclass_id +* @block: data memory block number +* @data: data from/for the block +* @has_data: true if data has been filled by read +* @dirty: true if data has changed since last read/write +* +* Encapsulates info required to manage chip data memory blocks. +*/ +struct bq27xxx_dm_buf { +u8 class; +u8 block; +u8 data[BQ27XXX_DM_SZ ]; +bool has_data, dirty; +}; + +static int poll_interval_param_set (const char *val,const struct kernel_param *kp) {struct bq27xxx_device_info *di;@@ -864,6 +930,193 @@ static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_inreturn ret; } +static int bq27xxx_battery_seal (struct bq27xxx_device_info *di) +{ +int ret; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL ,BQ27XXX_SEALED , false); +if (ret <0 ) { +dev_err (di->dev,"bus error on seal: %d\n" , ret); +return ret; + } + +return 0 ; +} + +static int bq27xxx_battery_unseal (struct bq27xxx_device_info *di) +{ +int ret; + +if (di->unseal_key ==0 ) { +dev_err (di->dev,"unseal failed due to missing key\n" ); +return -EINVAL ; + } + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16)(di->unseal_key >>16 ), false); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16 )di->unseal_key, false); +if (ret <0 ) + goto out; + +return 0 ; + +out: +dev_err (di->dev,"bus error on unseal: %d\n" , 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->data[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; + + buf->has_data = false; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_read_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret =bq27xxx_read (di,BQ27XXX_DM_CKSUM , true); +if (ret <0 ) + goto out; + +if ((u8 )ret !=bq27xxx_battery_checksum_dm_block (buf)) { + ret = -EINVAL ; + goto out; + } + + buf->has_data = true;
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1022
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ buf->dirty = false; + +return 0 ; + +out: +dev_err (di->dev,"bus error reading chip memory: %d\n" , ret); +return ret; +} + +static int bq27xxx_battery_set_cfgupdate (struct bq27xxx_device_info *di,u16 state)
Why do you pass in a flag but treat it like a bool? This whole function needs to be re-factored.
Quoted 26 lines
drivers/power/supply/bq27xxx_battery.c +26
-0+{ +const int limit =100 ; +int ret, try = limit; + + ret =bq27xxx_write (di,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 (limit-try >3 ) +dev_warn (di->dev,"cfgupdate %d, retries %d\n" , !!state, limit-try); + +return 0 ;
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1058
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-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 */
Group? This is a single chip ID.
Quoted 30 lines
drivers/power/supply/bq27xxx_battery.c +30
-0+int ret; + +if (!buf->dirty) +return 0 ; + +if (cfgup) { + ret =bq27xxx_battery_set_cfgupdate (di,BQ27XXX_FLAG_CFGUP ); +if (ret <0 ) +return ret; + } + + ret =bq27xxx_write (di,BQ27XXX_DM_CTRL ,0 , true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_write_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret = bq27xxx_write(di, BQ27XXX_DM_CKSUM,
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1098
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ bq27xxx_battery_checksum_dm_block(buf), true); +if (ret <0 ) + goto out; + +/* DO NOT read BQ27XXX_DM_CKSUM here to verify it! That may cause NVM +* corruption on the '425 chip (and perhaps others), which can damage +* the chip. See TI bqtool for what not to do: +* http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328 +*/ +
Again, this is not needed, I'm sorry you fried your chip somehow but this program is not incorrect, it is used by our customers all the time and does not fry chips, drop this comment.
Quoted 37 lines
drivers/power/supply/bq27xxx_battery.c +21
-0+if (cfgup) { +BQ27XXX_MSLEEP (1 ); + ret =bq27xxx_battery_set_cfgupdate (di,0 ); +if (ret <0 ) +return ret; + }else { +BQ27XXX_MSLEEP (100 );/* flash DM updates in <100ms */ + } + + buf->dirty = false; + +return 0 ; + +out: +if (cfgup) +bq27xxx_battery_set_cfgupdate (di,0 ); + +dev_err (di->dev,"bus error writing chip memory: %d\n" , ret); +return ret; +} +/* * Return the battery State-of-Charge * Or < 0 if something fails. include/linux/power/bq27xxx_battery.h +1
-0@@ -64,6 +64,7 @@ struct bq27xxx_device_info {int id;enum bq27xxx_chip chip;const char *name; +u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;int charge_design_full;
Re: [PATCH v13 07/11] power: supply: bq27xxx_battery: Add chip data memory read/write support
Quoted 327 lines · Andrew F. Davis
Quoted 326 lines · Liam Breck
From: Liam Breck <[email protected]>
Add these to enable read/write of chip data memory RAM/NVM/flash:
bq27xxx_battery_seal()
bq27xxx_battery_unseal()bq27xxx_battery_set_cfgupdate()bq27xxx_battery_read_dm_block()bq27xxx_battery_write_dm_block()bq27xxx_battery_checksum_dm_block()Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 253 +++++++++++++++++++++++++++++++++ include/linux/power/bq27xxx_battery.h | 1 + 2 files changed, 254 insertions(+)drivers/power/supply/bq27xxx_battery.c +151
-0@@ -5,6 +5,7 @@* Copyright (C) 2008 Eurotech S.p.A. <[email protected]> * Copyright (C) 2010-2011 Lars-Peter Clausen <[email protected]> * Copyright (C) 2011 Pali Rohár <[email protected]> +* Copyright (C) 2017 Liam Breck <[email protected]> * * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. * @@ -65,6 +66,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)@@ -78,6 +80,12 @@#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_RESET 0x41 +#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 */ @@ -108,9 +116,21 @@ enum bq27xxx_reg_index {BQ27XXX_REG_SOC ,/* State-of-Charge */ BQ27XXX_REG_DCAP ,/* Design Capacity */ BQ27XXX_REG_AP ,/* Average Power */ +BQ27XXX_DM_CTRL ,/* Block Data Control */ +BQ27XXX_DM_CLASS ,/* Data Class */ +BQ27XXX_DM_BLOCK ,/* Data Block */ +BQ27XXX_DM_DATA ,/* Block Data */ +BQ27XXX_DM_CKSUM ,/* Block Data Checksum */ BQ27XXX_REG_MAX, /* sentinel */ }; +#define BQ27XXX_DM_REG_ROWS \ + [BQ27XXX_DM_CTRL] = 0x61, \ + [BQ27XXX_DM_CLASS] = 0x3e, \ + [BQ27XXX_DM_BLOCK] = 0x3f, \ + [BQ27XXX_DM_DATA] = 0x40, \ + [BQ27XXX_DM_CKSUM] = 0x60 +/* Register mappings */ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { [BQ27000 ] = {@@ -131,6 +151,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 ,@@ -150,6 +175,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 , }, [BQ2750X] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -169,6 +199,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ2751X] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -188,6 +219,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27500] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -207,6 +239,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -226,6 +259,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -245,6 +279,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -264,6 +299,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -283,6 +319,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -302,6 +339,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -321,6 +359,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G4] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -340,6 +379,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27530] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -359,6 +399,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27541] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -378,6 +419,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27545] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -397,6 +439,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27421] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -416,6 +459,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x1c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP] = 0x18, + BQ27XXX_DM_REG_ROWS, }, };@@ -757,6 +801,28 @@ static struct {static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices); +#define BQ27XXX_MSLEEP (i) usleep_range((i)*1000, (i)*1000+500) + +#define BQ27XXX_DM_SZ 32 + +/** +* struct bq27xxx_dm_buf - chip data memory buffer +* @class: data memory subclass_id +* @block: data memory block number +* @data: data from/for the block +* @has_data: true if data has been filled by read +* @dirty: true if data has changed since last read/write +* +* Encapsulates info required to manage chip data memory blocks. +*/ +struct bq27xxx_dm_buf { +u8 class; +u8 block; +u8 data[BQ27XXX_DM_SZ ]; +bool has_data, dirty; +}; + +static int poll_interval_param_set (const char *val,const struct kernel_param *kp) {struct bq27xxx_device_info *di;@@ -864,6 +930,193 @@ static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_inreturn ret; } +static int bq27xxx_battery_seal (struct bq27xxx_device_info *di) +{ +int ret; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL ,BQ27XXX_SEALED , false); +if (ret <0 ) { +dev_err (di->dev,"bus error on seal: %d\n" , ret); +return ret; + } + +return 0 ; +} + +static int bq27xxx_battery_unseal (struct bq27xxx_device_info *di) +{ +int ret; + +if (di->unseal_key ==0 ) { +dev_err (di->dev,"unseal failed due to missing key\n" ); +return -EINVAL ; + } + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16)(di->unseal_key >>16 ), false); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16 )di->unseal_key, false); +if (ret <0 ) + goto out; + +return 0 ; + +out: +dev_err (di->dev,"bus error on unseal: %d\n" , 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->data[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; + + buf->has_data = false; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_read_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret =bq27xxx_read (di,BQ27XXX_DM_CKSUM , true); +if (ret <0 ) + goto out; + +if ((u8 )ret !=bq27xxx_battery_checksum_dm_block (buf)) { + ret = -EINVAL ; + goto out; + } + + buf->has_data = true; + buf->dirty = false; + +return 0 ; + +out:
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1022
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+dev_err (di->dev,"bus error reading chip memory: %d\n" , ret); +return ret; +} + +static int bq27xxx_battery_set_cfgupdate (struct bq27xxx_device_info *di,u16 state)Why do you pass in a flag but treat it like a bool? This whole function needs to be re-factored.
I will rename this cfgupdate_priv() and add apis set_cfgupdate() and soft_reset() to call it.
Quoted 30 lines
Quoted 30 lines
drivers/power/supply/bq27xxx_battery.c +30
-0+{ +const int limit =100 ; +int ret, try = limit; + + ret =bq27xxx_write (di,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 (limit-try >3 ) +dev_warn (di->dev,"cfgupdate %d, retries %d\n" , !!state, limit-try); + +return 0 ; + +out: +dev_err (di->dev,"bus error on %s: %d\n" , state ?"set_cfgupdate" :"soft_reset" , ret); +return ret;
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1058
Quoted 6 lines
drivers/power/supply/bq27xxx_battery.c +6
-0+} + +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 */ Group? This is a single chip ID.
Many of the "single" chip IDs represent several chips. That predates this patchset. I will change "group" to "class".
Quoted 36 lines
Quoted 36 lines
drivers/power/supply/bq27xxx_battery.c +36
-0+int ret; + +if (!buf->dirty) +return 0 ; + +if (cfgup) { + ret =bq27xxx_battery_set_cfgupdate (di,BQ27XXX_FLAG_CFGUP ); +if (ret <0 ) +return ret; + } + + ret =bq27xxx_write (di,BQ27XXX_DM_CTRL ,0 , true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_write_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_CKSUM , +bq27xxx_battery_checksum_dm_block (buf), true); +if (ret <0 ) + goto out; + +/* DO NOT read BQ27XXX_DM_CKSUM here to verify it! That may cause NVM +* corruption on the '425 chip (and perhaps others), which can damage
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1098
Quoted 4 lines
drivers/power/supply/bq27xxx_battery.c +4
-0+* the chip. See TI bqtool for what not to do: +* http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328 +*/ +Again, this is not needed, I'm sorry you fried your chip somehow but this program is not incorrect, it is used by our customers all the time and does not fry chips, drop this comment.
Bqtool works because it has a long-enough initial delay, but it implies that the delay is flexible, because on failure it delays again and retries. I read that and assumed we could use a shorter delay, which ruined a chip. The datasheet does not indicate a required delay after checksum write.
I will take out the link to bqtool, but we need to leave the comment in to prevent others making that mistake.
Quoted 37 lines
Quoted 37 lines
drivers/power/supply/bq27xxx_battery.c +21
-0+if (cfgup) { +BQ27XXX_MSLEEP (1 ); + ret =bq27xxx_battery_set_cfgupdate (di,0 ); +if (ret <0 ) +return ret; + }else { +BQ27XXX_MSLEEP (100 );/* flash DM updates in <100ms */ + } + + buf->dirty = false; + +return 0 ; + +out: +if (cfgup) +bq27xxx_battery_set_cfgupdate (di,0 ); + +dev_err (di->dev,"bus error writing chip memory: %d\n" , ret); +return ret; +} +/* * Return the battery State-of-Charge * Or < 0 if something fails. include/linux/power/bq27xxx_battery.h +1
-0@@ -64,6 +64,7 @@ struct bq27xxx_device_info {int id;enum bq27xxx_chip chip;const char *name; +u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;int charge_design_full;
Re: [PATCH v13 07/11] power: supply: bq27xxx_battery: Add chip data memory read/write support
In reply to Andrew F. DavisQuoted 327 lines · Andrew F. Davis
Quoted 326 lines · Liam Breck
From: Liam Breck <[email protected]>
Add these to enable read/write of chip data memory RAM/NVM/flash:
bq27xxx_battery_seal()
bq27xxx_battery_unseal()bq27xxx_battery_set_cfgupdate()bq27xxx_battery_read_dm_block()bq27xxx_battery_write_dm_block()bq27xxx_battery_checksum_dm_block()Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 253 +++++++++++++++++++++++++++++++++ include/linux/power/bq27xxx_battery.h | 1 + 2 files changed, 254 insertions(+)drivers/power/supply/bq27xxx_battery.c +151
-0@@ -5,6 +5,7 @@* Copyright (C) 2008 Eurotech S.p.A. <[email protected]> * Copyright (C) 2010-2011 Lars-Peter Clausen <[email protected]> * Copyright (C) 2011 Pali Rohár <[email protected]> +* Copyright (C) 2017 Liam Breck <[email protected]> * * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. * @@ -65,6 +66,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)@@ -78,6 +80,12 @@#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_RESET 0x41 +#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 */ @@ -108,9 +116,21 @@ enum bq27xxx_reg_index {BQ27XXX_REG_SOC ,/* State-of-Charge */ BQ27XXX_REG_DCAP ,/* Design Capacity */ BQ27XXX_REG_AP ,/* Average Power */ +BQ27XXX_DM_CTRL ,/* Block Data Control */ +BQ27XXX_DM_CLASS ,/* Data Class */ +BQ27XXX_DM_BLOCK ,/* Data Block */ +BQ27XXX_DM_DATA ,/* Block Data */ +BQ27XXX_DM_CKSUM ,/* Block Data Checksum */ BQ27XXX_REG_MAX, /* sentinel */ }; +#define BQ27XXX_DM_REG_ROWS \ + [BQ27XXX_DM_CTRL] = 0x61, \ + [BQ27XXX_DM_CLASS] = 0x3e, \ + [BQ27XXX_DM_BLOCK] = 0x3f, \ + [BQ27XXX_DM_DATA] = 0x40, \ + [BQ27XXX_DM_CKSUM] = 0x60 +/* Register mappings */ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { [BQ27000 ] = {@@ -131,6 +151,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 ,@@ -150,6 +175,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 , }, [BQ2750X] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -169,6 +199,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ2751X] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -188,6 +219,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27500] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -207,6 +239,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -226,6 +259,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -245,6 +279,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -264,6 +299,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -283,6 +319,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -302,6 +339,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -321,6 +359,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G4] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -340,6 +379,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27530] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -359,6 +399,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27541] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -378,6 +419,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27545] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -397,6 +439,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27421] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -416,6 +459,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x1c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP] = 0x18, + BQ27XXX_DM_REG_ROWS, }, };@@ -757,6 +801,28 @@ static struct {static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices); +#define BQ27XXX_MSLEEP (i) usleep_range((i)*1000, (i)*1000+500) + +#define BQ27XXX_DM_SZ 32 + +/** +* struct bq27xxx_dm_buf - chip data memory buffer +* @class: data memory subclass_id +* @block: data memory block number +* @data: data from/for the block +* @has_data: true if data has been filled by read +* @dirty: true if data has changed since last read/write +* +* Encapsulates info required to manage chip data memory blocks. +*/ +struct bq27xxx_dm_buf { +u8 class; +u8 block; +u8 data[BQ27XXX_DM_SZ ]; +bool has_data, dirty; +}; + +static int poll_interval_param_set (const char *val,const struct kernel_param *kp) {struct bq27xxx_device_info *di;@@ -864,6 +930,193 @@ static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_inreturn ret; } +static int bq27xxx_battery_seal (struct bq27xxx_device_info *di) +{ +int ret; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL ,BQ27XXX_SEALED , false); +if (ret <0 ) { +dev_err (di->dev,"bus error on seal: %d\n" , ret); +return ret; + } + +return 0 ; +} + +static int bq27xxx_battery_unseal (struct bq27xxx_device_info *di) +{ +int ret; + +if (di->unseal_key ==0 ) { +dev_err (di->dev,"unseal failed due to missing key\n" ); +return -EINVAL ; + } + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16)(di->unseal_key >>16 ), false); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16 )di->unseal_key, false); +if (ret <0 ) + goto out; + +return 0 ; + +out: +dev_err (di->dev,"bus error on unseal: %d\n" , 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->data[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; + + buf->has_data = false; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_read_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret =bq27xxx_read (di,BQ27XXX_DM_CKSUM , true); +if (ret <0 ) + goto out; + +if ((u8 )ret !=bq27xxx_battery_checksum_dm_block (buf)) { + ret = -EINVAL ; + goto out; + } + + buf->has_data = true; + buf->dirty = false; + +return 0 ; + +out:
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1022
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+dev_err (di->dev,"bus error reading chip memory: %d\n" , ret); +return ret; +} + +static int bq27xxx_battery_set_cfgupdate (struct bq27xxx_device_info *di,u16 state)Why do you pass in a flag but treat it like a bool? This whole function needs to be re-factored.
How's this look?
static int bq27xxx_battery_cfgupdate_priv(struct bq27xxx_device_info *di, bool active)
{
const int limit = 100;
int ret, try = limit;
ret = bq27xxx_write(di, BQ27XXX_REG_CTRL,
active ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET,
false);
if (ret < 0)
return ret;
do {
BQ27XXX_MSLEEP(25);
ret = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
if (ret < 0)
return ret;
} while (!!(ret & BQ27XXX_FLAG_CFGUP) != active && --try);
if (!try) {
dev_err(di->dev, "timed out waiting for cfgupdate flag
%d\n", active);
return -EINVAL;
}
if (limit - try > 3)
dev_warn(di->dev, "cfgupdate %d, retries %d\n",active, limit - try);
return 0; }
static inline int bq27xxx_battery_set_cfgupdate(struct bq27xxx_device_info *di)
{
int ret = bq27xxx_battery_cfgupdate_priv(di, true);
if (ret < 0 && ret != -EINVAL)
dev_err(di->dev, "bus error on set_cfgupdate: %d\n", ret);
return ret;
}static inline int bq27xxx_battery_soft_reset(struct bq27xxx_device_info *di)
{
int ret = bq27xxx_battery_cfgupdate_priv(di, false);
if (ret < 0 && ret != -EINVAL)
dev_err(di->dev, "bus error on soft_reset: %d\n", ret);
return ret;
}Quoted 121 lines
Quoted 26 lines
drivers/power/supply/bq27xxx_battery.c +26
-0+{ +const int limit =100 ; +int ret, try = limit; + + ret =bq27xxx_write (di,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 (limit-try >3 ) +dev_warn (di->dev,"cfgupdate %d, retries %d\n" , !!state, limit-try); + +return 0 ;drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1058
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-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 */ Group? This is a single chip ID.
Quoted 30 lines
drivers/power/supply/bq27xxx_battery.c +30
-0+int ret; + +if (!buf->dirty) +return 0 ; + +if (cfgup) { + ret =bq27xxx_battery_set_cfgupdate (di,BQ27XXX_FLAG_CFGUP ); +if (ret <0 ) +return ret; + } + + ret =bq27xxx_write (di,BQ27XXX_DM_CTRL ,0 , true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_write_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret = bq27xxx_write(di, BQ27XXX_DM_CKSUM,drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1098
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ bq27xxx_battery_checksum_dm_block(buf), true); +if (ret <0 ) + goto out; + +/* DO NOT read BQ27XXX_DM_CKSUM here to verify it! That may cause NVM +* corruption on the '425 chip (and perhaps others), which can damage +* the chip. See TI bqtool for what not to do: +* http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328 +*/ +Again, this is not needed, I'm sorry you fried your chip somehow but this program is not incorrect, it is used by our customers all the time and does not fry chips, drop this comment.
Quoted 37 lines
drivers/power/supply/bq27xxx_battery.c +21
-0+if (cfgup) { +BQ27XXX_MSLEEP (1 ); + ret =bq27xxx_battery_set_cfgupdate (di,0 ); +if (ret <0 ) +return ret; + }else { +BQ27XXX_MSLEEP (100 );/* flash DM updates in <100ms */ + } + + buf->dirty = false; + +return 0 ; + +out: +if (cfgup) +bq27xxx_battery_set_cfgupdate (di,0 ); + +dev_err (di->dev,"bus error writing chip memory: %d\n" , ret); +return ret; +} +/* * Return the battery State-of-Charge * Or < 0 if something fails. include/linux/power/bq27xxx_battery.h +1
-0@@ -64,6 +64,7 @@ struct bq27xxx_device_info {int id;enum bq27xxx_chip chip;const char *name; +u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;int charge_design_full;
Re: [PATCH v13 07/11] power: supply: bq27xxx_battery: Add chip data memory read/write support
Quoted 337 lines · Liam Breck
Quoted 327 lines · Andrew F. Davis
Quoted 326 lines · Liam Breck
From: Liam Breck <[email protected]>
Add these to enable read/write of chip data memory RAM/NVM/flash:
bq27xxx_battery_seal()
bq27xxx_battery_unseal()bq27xxx_battery_set_cfgupdate()bq27xxx_battery_read_dm_block()bq27xxx_battery_write_dm_block()bq27xxx_battery_checksum_dm_block()Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 253 +++++++++++++++++++++++++++++++++ include/linux/power/bq27xxx_battery.h | 1 + 2 files changed, 254 insertions(+)drivers/power/supply/bq27xxx_battery.c +151
-0@@ -5,6 +5,7 @@* Copyright (C) 2008 Eurotech S.p.A. <[email protected]> * Copyright (C) 2010-2011 Lars-Peter Clausen <[email protected]> * Copyright (C) 2011 Pali Rohár <[email protected]> +* Copyright (C) 2017 Liam Breck <[email protected]> * * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. * @@ -65,6 +66,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)@@ -78,6 +80,12 @@#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_RESET 0x41 +#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 */ @@ -108,9 +116,21 @@ enum bq27xxx_reg_index {BQ27XXX_REG_SOC ,/* State-of-Charge */ BQ27XXX_REG_DCAP ,/* Design Capacity */ BQ27XXX_REG_AP ,/* Average Power */ +BQ27XXX_DM_CTRL ,/* Block Data Control */ +BQ27XXX_DM_CLASS ,/* Data Class */ +BQ27XXX_DM_BLOCK ,/* Data Block */ +BQ27XXX_DM_DATA ,/* Block Data */ +BQ27XXX_DM_CKSUM ,/* Block Data Checksum */ BQ27XXX_REG_MAX, /* sentinel */ }; +#define BQ27XXX_DM_REG_ROWS \ + [BQ27XXX_DM_CTRL] = 0x61, \ + [BQ27XXX_DM_CLASS] = 0x3e, \ + [BQ27XXX_DM_BLOCK] = 0x3f, \ + [BQ27XXX_DM_DATA] = 0x40, \ + [BQ27XXX_DM_CKSUM] = 0x60 +/* Register mappings */ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { [BQ27000 ] = {@@ -131,6 +151,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 ,@@ -150,6 +175,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 , }, [BQ2750X] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -169,6 +199,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ2751X] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -188,6 +219,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27500] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -207,6 +239,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -226,6 +259,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -245,6 +279,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -264,6 +299,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -283,6 +319,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -302,6 +339,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -321,6 +359,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G4] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -340,6 +379,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27530] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -359,6 +399,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27541] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -378,6 +419,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27545] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -397,6 +439,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27421] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -416,6 +459,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x1c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP] = 0x18, + BQ27XXX_DM_REG_ROWS, }, };@@ -757,6 +801,28 @@ static struct {static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices); +#define BQ27XXX_MSLEEP (i) usleep_range((i)*1000, (i)*1000+500) + +#define BQ27XXX_DM_SZ 32 + +/** +* struct bq27xxx_dm_buf - chip data memory buffer +* @class: data memory subclass_id +* @block: data memory block number +* @data: data from/for the block +* @has_data: true if data has been filled by read +* @dirty: true if data has changed since last read/write +* +* Encapsulates info required to manage chip data memory blocks. +*/ +struct bq27xxx_dm_buf { +u8 class; +u8 block; +u8 data[BQ27XXX_DM_SZ ]; +bool has_data, dirty; +}; + +static int poll_interval_param_set (const char *val,const struct kernel_param *kp) {struct bq27xxx_device_info *di;@@ -864,6 +930,193 @@ static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_inreturn ret; } +static int bq27xxx_battery_seal (struct bq27xxx_device_info *di) +{ +int ret; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL ,BQ27XXX_SEALED , false); +if (ret <0 ) { +dev_err (di->dev,"bus error on seal: %d\n" , ret); +return ret; + } + +return 0 ; +} + +static int bq27xxx_battery_unseal (struct bq27xxx_device_info *di) +{ +int ret; + +if (di->unseal_key ==0 ) { +dev_err (di->dev,"unseal failed due to missing key\n" ); +return -EINVAL ; + } + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16)(di->unseal_key >>16 ), false); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16 )di->unseal_key, false); +if (ret <0 ) + goto out; + +return 0 ; + +out: +dev_err (di->dev,"bus error on unseal: %d\n" , 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->data[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; + + buf->has_data = false; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_read_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret =bq27xxx_read (di,BQ27XXX_DM_CKSUM , true); +if (ret <0 ) + goto out; + +if ((u8 )ret !=bq27xxx_battery_checksum_dm_block (buf)) { + ret = -EINVAL ; + goto out; + } + + buf->has_data = true; + buf->dirty = false; + +return 0 ; + +out:Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1022
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+dev_err (di->dev,"bus error reading chip memory: %d\n" , ret); +return ret; +} + +static int bq27xxx_battery_set_cfgupdate (struct bq27xxx_device_info *di,u16 state)Why do you pass in a flag but treat it like a bool? This whole function needs to be re-factored.
Quoted 2 lines
How's this look?
Better, how about we store the mask at the start, might improve readability, something like this would be nice:
static int bq27xxx_battery_cfgupdate_priv(struct bq27xxx_device_info *di, bool active)
{
const int limit = 100;
int ret, try = 0;
u16 command = active ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET;
ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, command, false);
if (ret < 0)
return ret;
do {
BQ27XXX_MSLEEP(25);
ret = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
if (ret < 0)
return ret;
if (try++ > limit) {
dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", active);
return -EINVAL;
}
} while (!!(ret & BQ27XXX_FLAG_CFGUP) != active);
return 0;
}Quoted 173 lines
static int
bq27xxx_battery_cfgupdate_priv(struct bq27xxx_device_info *di, bool active){ const int limit = 100; int ret, try = limit; ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, active ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET, false); if (ret < 0) return ret; do { BQ27XXX_MSLEEP(25); ret = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false); if (ret < 0) return ret; } while (!!(ret & BQ27XXX_FLAG_CFGUP) != active && --try); if (!try) { dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", active); return -EINVAL; } if (limit - try > 3) dev_warn(di->dev, "cfgupdate %d, retries %d\n",active, limit - try);
return 0; }static inline int
bq27xxx_battery_set_cfgupdate(struct bq27xxx_device_info *di){ int ret = bq27xxx_battery_cfgupdate_priv(di, true); if (ret < 0 && ret != -EINVAL) dev_err(di->dev, "bus error on set_cfgupdate: %d\n", ret); return ret; }static inline int
bq27xxx_battery_soft_reset(struct bq27xxx_device_info *di){ int ret = bq27xxx_battery_cfgupdate_priv(di, false); if (ret < 0 && ret != -EINVAL) dev_err(di->dev, "bus error on soft_reset: %d\n", ret); return ret; }Quoted 121 lines
Quoted 26 lines
drivers/power/supply/bq27xxx_battery.c +26
-0+{ +const int limit =100 ; +int ret, try = limit; + + ret =bq27xxx_write (di,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 (limit-try >3 ) +dev_warn (di->dev,"cfgupdate %d, retries %d\n" , !!state, limit-try); + +return 0 ;drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1058
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-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 */ Group? This is a single chip ID.
Quoted 30 lines
drivers/power/supply/bq27xxx_battery.c +30
-0+int ret; + +if (!buf->dirty) +return 0 ; + +if (cfgup) { + ret =bq27xxx_battery_set_cfgupdate (di,BQ27XXX_FLAG_CFGUP ); +if (ret <0 ) +return ret; + } + + ret =bq27xxx_write (di,BQ27XXX_DM_CTRL ,0 , true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_write_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret = bq27xxx_write(di, BQ27XXX_DM_CKSUM,drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1098
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ bq27xxx_battery_checksum_dm_block(buf), true); +if (ret <0 ) + goto out; + +/* DO NOT read BQ27XXX_DM_CKSUM here to verify it! That may cause NVM +* corruption on the '425 chip (and perhaps others), which can damage +* the chip. See TI bqtool for what not to do: +* http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328 +*/ +Again, this is not needed, I'm sorry you fried your chip somehow but this program is not incorrect, it is used by our customers all the time and does not fry chips, drop this comment.
Quoted 37 lines
drivers/power/supply/bq27xxx_battery.c +21
-0+if (cfgup) { +BQ27XXX_MSLEEP (1 ); + ret =bq27xxx_battery_set_cfgupdate (di,0 ); +if (ret <0 ) +return ret; + }else { +BQ27XXX_MSLEEP (100 );/* flash DM updates in <100ms */ + } + + buf->dirty = false; + +return 0 ; + +out: +if (cfgup) +bq27xxx_battery_set_cfgupdate (di,0 ); + +dev_err (di->dev,"bus error writing chip memory: %d\n" , ret); +return ret; +} +/* * Return the battery State-of-Charge * Or < 0 if something fails. include/linux/power/bq27xxx_battery.h +1
-0@@ -64,6 +64,7 @@ struct bq27xxx_device_info {int id;enum bq27xxx_chip chip;const char *name; +u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;int charge_design_full;
Re: [PATCH v13 07/11] power: supply: bq27xxx_battery: Add chip data memory read/write support
Quoted 338 lines · Andrew F. Davis
Quoted 337 lines · Liam Breck
Quoted 335 lines · Andrew F. Davis
Quoted 321 lines · Liam Breck
From: Liam Breck <[email protected]>
Add these to enable read/write of chip data memory RAM/NVM/flash:
bq27xxx_battery_seal()
bq27xxx_battery_unseal()bq27xxx_battery_set_cfgupdate()bq27xxx_battery_read_dm_block()bq27xxx_battery_write_dm_block()bq27xxx_battery_checksum_dm_block()Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 253 +++++++++++++++++++++++++++++++++ include/linux/power/bq27xxx_battery.h | 1 + 2 files changed, 254 insertions(+)drivers/power/supply/bq27xxx_battery.c +146
-0@@ -5,6 +5,7 @@* Copyright (C) 2008 Eurotech S.p.A. <[email protected]> * Copyright (C) 2010-2011 Lars-Peter Clausen <[email protected]> * Copyright (C) 2011 Pali Rohár <[email protected]> +* Copyright (C) 2017 Liam Breck <[email protected]> * * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. * @@ -65,6 +66,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)@@ -78,6 +80,12 @@#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_RESET 0x41 +#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 */ @@ -108,9 +116,21 @@ enum bq27xxx_reg_index {BQ27XXX_REG_SOC ,/* State-of-Charge */ BQ27XXX_REG_DCAP ,/* Design Capacity */ BQ27XXX_REG_AP ,/* Average Power */ +BQ27XXX_DM_CTRL ,/* Block Data Control */ +BQ27XXX_DM_CLASS ,/* Data Class */ +BQ27XXX_DM_BLOCK ,/* Data Block */ +BQ27XXX_DM_DATA ,/* Block Data */ +BQ27XXX_DM_CKSUM ,/* Block Data Checksum */ BQ27XXX_REG_MAX, /* sentinel */ }; +#define BQ27XXX_DM_REG_ROWS \ + [BQ27XXX_DM_CTRL] = 0x61, \ + [BQ27XXX_DM_CLASS] = 0x3e, \ + [BQ27XXX_DM_BLOCK] = 0x3f, \ + [BQ27XXX_DM_DATA] = 0x40, \ + [BQ27XXX_DM_CKSUM] = 0x60 +/* Register mappings */ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { [BQ27000 ] = {@@ -131,6 +151,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 ,@@ -150,6 +175,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 , }, [BQ2750X] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -169,6 +199,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ2751X] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -188,6 +219,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27500] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -207,6 +239,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -226,6 +259,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -245,6 +279,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27510G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -264,6 +299,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = 0x2e, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G1] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -283,6 +319,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G2] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -302,6 +339,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G3] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -321,6 +359,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27520G4] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -340,6 +379,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x20, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , +BQ27XXX_DM_REG_ROWS , }, [BQ27530] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -359,6 +399,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27541] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -378,6 +419,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27545] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -397,6 +439,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, [BQ27XXX_REG_AP ] =0x24 , +BQ27XXX_DM_REG_ROWS , }, [BQ27421] = { [BQ27XXX_REG_CTRL ] =0x00 ,@@ -416,6 +459,7 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_SOC] = 0x1c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP] = 0x18, + BQ27XXX_DM_REG_ROWS, }, };@@ -757,6 +801,28 @@ static struct {static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices); +#define BQ27XXX_MSLEEP (i) usleep_range((i)*1000, (i)*1000+500) + +#define BQ27XXX_DM_SZ 32 + +/** +* struct bq27xxx_dm_buf - chip data memory buffer +* @class: data memory subclass_id +* @block: data memory block number +* @data: data from/for the block +* @has_data: true if data has been filled by read +* @dirty: true if data has changed since last read/write +* +* Encapsulates info required to manage chip data memory blocks. +*/ +struct bq27xxx_dm_buf { +u8 class; +u8 block; +u8 data[BQ27XXX_DM_SZ ]; +bool has_data, dirty; +}; + +static int poll_interval_param_set (const char *val,const struct kernel_param *kp) {struct bq27xxx_device_info *di;@@ -864,6 +930,193 @@ static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_inreturn ret; } +static int bq27xxx_battery_seal (struct bq27xxx_device_info *di) +{ +int ret; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL ,BQ27XXX_SEALED , false); +if (ret <0 ) { +dev_err (di->dev,"bus error on seal: %d\n" , ret); +return ret; + } + +return 0 ; +} + +static int bq27xxx_battery_unseal (struct bq27xxx_device_info *di) +{ +int ret; + +if (di->unseal_key ==0 ) { +dev_err (di->dev,"unseal failed due to missing key\n" ); +return -EINVAL ; + } + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16)(di->unseal_key >>16 ), false); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_REG_CTRL , (u16 )di->unseal_key, false); +if (ret <0 ) + goto out; + +return 0 ; + +out: +dev_err (di->dev,"bus error on unseal: %d\n" , 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->data[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; + + buf->has_data = false; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_read_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret =bq27xxx_read (di,BQ27XXX_DM_CKSUM , true); +if (ret <0 ) + goto out; + +if ((u8 )ret !=bq27xxx_battery_checksum_dm_block (buf)) { + ret = -EINVAL ; + goto out; + } + + buf->has_data = true;drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1022
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ buf->dirty = false; + +return 0 ; + +out: +dev_err (di->dev,"bus error reading chip memory: %d\n" , ret); +return ret; +} + +static int bq27xxx_battery_set_cfgupdate (struct bq27xxx_device_info *di,u16 state)Why do you pass in a flag but treat it like a bool? This whole function needs to be re-factored.
Quoted 5 lines
Quoted 2 lines
How's this look?
Better, how about we store the mask at the start, might improve readability, something like this would be nice:
Sure, will do.
Quoted 199 lines
static int
bq27xxx_battery_cfgupdate_priv(struct bq27xxx_device_info *di, bool active){ const int limit = 100; int ret, try = 0; u16 command = active ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET; ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, command, false); if (ret < 0) return ret; do { BQ27XXX_MSLEEP(25); ret = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false); if (ret < 0) return ret; if (try++ > limit) { dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", active); return -EINVAL; } } while (!!(ret & BQ27XXX_FLAG_CFGUP) != active); return 0; }Quoted 173 lines
static int
bq27xxx_battery_cfgupdate_priv(struct bq27xxx_device_info *di, bool active){ const int limit = 100; int ret, try = limit; ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, active ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET, false); if (ret < 0) return ret; do { BQ27XXX_MSLEEP(25); ret = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false); if (ret < 0) return ret; } while (!!(ret & BQ27XXX_FLAG_CFGUP) != active && --try); if (!try) { dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", active); return -EINVAL; } if (limit - try > 3) dev_warn(di->dev, "cfgupdate %d, retries %d\n",active, limit - try);
return 0; }static inline int
bq27xxx_battery_set_cfgupdate(struct bq27xxx_device_info *di){ int ret = bq27xxx_battery_cfgupdate_priv(di, true); if (ret < 0 && ret != -EINVAL) dev_err(di->dev, "bus error on set_cfgupdate: %d\n", ret); return ret; }static inline int
bq27xxx_battery_soft_reset(struct bq27xxx_device_info *di){ int ret = bq27xxx_battery_cfgupdate_priv(di, false); if (ret < 0 && ret != -EINVAL) dev_err(di->dev, "bus error on soft_reset: %d\n", ret); return ret; }Quoted 121 lines
Quoted 26 lines
drivers/power/supply/bq27xxx_battery.c +26
-0+{ +const int limit =100 ; +int ret, try = limit; + + ret =bq27xxx_write (di,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 (limit-try >3 ) +dev_warn (di->dev,"cfgupdate %d, retries %d\n" , !!state, limit-try); + +return 0 ;drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1058
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-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 */ Group? This is a single chip ID.
Quoted 30 lines
drivers/power/supply/bq27xxx_battery.c +30
-0+int ret; + +if (!buf->dirty) +return 0 ; + +if (cfgup) { + ret =bq27xxx_battery_set_cfgupdate (di,BQ27XXX_FLAG_CFGUP ); +if (ret <0 ) +return ret; + } + + ret =bq27xxx_write (di,BQ27XXX_DM_CTRL ,0 , true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_CLASS , buf->class, true); +if (ret <0 ) + goto out; + + ret =bq27xxx_write (di,BQ27XXX_DM_BLOCK , buf->block, true); +if (ret <0 ) + goto out; + +BQ27XXX_MSLEEP (1 ); + + ret =bq27xxx_write_block (di,BQ27XXX_DM_DATA , buf->data,BQ27XXX_DM_SZ ); +if (ret <0 ) + goto out; + + ret = bq27xxx_write(di, BQ27XXX_DM_CKSUM,drivers/power/supply/bq27xxx_battery.c static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_in · line 1098
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ bq27xxx_battery_checksum_dm_block(buf), true); +if (ret <0 ) + goto out; + +/* DO NOT read BQ27XXX_DM_CKSUM here to verify it! That may cause NVM +* corruption on the '425 chip (and perhaps others), which can damage +* the chip. See TI bqtool for what not to do: +* http://git.ti.com/bms-linux/bqtool/blobs/master/gauge.c#line328 +*/ +Again, this is not needed, I'm sorry you fried your chip somehow but this program is not incorrect, it is used by our customers all the time and does not fry chips, drop this comment.
Quoted 37 lines
drivers/power/supply/bq27xxx_battery.c +21
-0+if (cfgup) { +BQ27XXX_MSLEEP (1 ); + ret =bq27xxx_battery_set_cfgupdate (di,0 ); +if (ret <0 ) +return ret; + }else { +BQ27XXX_MSLEEP (100 );/* flash DM updates in <100ms */ + } + + buf->dirty = false; + +return 0 ; + +out: +if (cfgup) +bq27xxx_battery_set_cfgupdate (di,0 ); + +dev_err (di->dev,"bus error writing chip memory: %d\n" , ret); +return ret; +} +/* * Return the battery State-of-Charge * Or < 0 if something fails. include/linux/power/bq27xxx_battery.h +1
-0@@ -64,6 +64,7 @@ struct bq27xxx_device_info {int id;enum bq27xxx_chip chip;const char *name; +u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;int charge_design_full;
PATCH v13 8/11 power: supply: bq27xxx_battery: Add power_supply_battery_info support
In reply to Liam BreckFrom: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM is defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now call power_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is a dm_regs table for the chip.
--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)
drivers/power/supply/Kconfig +9 -0
@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903X
drivers/power/supply/bq27xxx_battery.c +198 -1
241 lines not on this page · raw message
include/linux/power/bq27xxx_battery.h +2 -0
@@ -63,7 +63,9 @@ struct bq27xxx_device_info {struct device *dev;int id;enum bq27xxx_chip chip; +bool ram_chip;const char *name; +struct bq27xxx_dm_reg *dm_regs;u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;
Signature · 1 line
2.9.3
Re: [PATCH v13 08/11] power: supply: bq27xxx_battery: Add power_supply_battery_info support
Quoted 85 lines · Liam Breck
From: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVMis defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now callpower_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is adm_regstable for the chip.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)drivers/power/supply/Kconfig +9
-0@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903Xdrivers/power/supply/bq27xxx_battery.c +31
-0@@ -805,6 +805,13 @@ static LIST_HEAD(bq27xxx_battery_devices);#define BQ27XXX_DM_SZ 32 +struct bq27xxx_dm_reg { +u8 subclass_id; +u8 offset; +u8 bytes; +u16 min, max; +}; +/** * struct bq27xxx_dm_buf - chip data memory buffer * @class: data memory subclass_id @@ -822,6 +829,43 @@ struct bq27xxx_dm_buf {bool has_data, dirty; }; +#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->data + 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 *const bq27xxx_dm_reg_name[] = { + [BQ27XXX_DM_DESIGN_CAPACITY ] ="design-capacity" , + [BQ27XXX_DM_DESIGN_ENERGY ] ="design-energy" ,
drivers/power/supply/bq27xxx_battery.c struct bq27xxx_dm_buf { · line 865
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ [BQ27XXX_DM_TERMINATE_VOLTAGE] = "terminate-voltage", +}; + + +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM +static bool bq27xxx_dt_to_nvm = true; + +module_param_named (dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool,0444 ); +MODULE_PARM_DESC (dt_monitored_battery_updates_nvm, +"Devicetree monitored-battery config updates NVM/flash data memory, if present. Default is 1/y." );
As before, the default should not be y, this is a rare case and I can't see it being useful or wanted by anyone but device manufacturers. I don't want everyones chip's factory programmed NVM overwritten by accident when someone compiles and ships a kernel with BATTERY_BQ27XXX_DT_UPDATES_NVM=y
Quoted 211 lines
drivers/power/supply/bq27xxx_battery.c +157
-1+#else +static bool bq27xxx_dt_to_nvm = false; +#endif static int poll_interval_param_set (const char *val,const struct kernel_param *kp) {@@ -1019,6 +1063,51 @@ static int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di,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->has_data) +return ; + +if (be16_to_cpup (prev) == val) { +dev_info (di->dev,"%s has %u\n" , str, val); +return ; + } + +if (!di->ram_chip && !bq27xxx_dt_to_nvm) { +/* devicetree and NVM differ; defer to NVM */ + dev_warn(di->dev, "%s has %u; update to %u disallowed " +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM + "by dt_monitored_battery_updates_nvm=0" +#else +"for flash/NVM data memory" +#endif +"\n" , str,be16_to_cpup (prev), val); +return ; + } + +dev_info (di->dev,"update %s to %u\n" , str, val); + + *prev =cpu_to_be16 (val); + buf->dirty = true; +} +static int bq27xxx_battery_set_cfgupdate (struct bq27xxx_device_info *di,u16 state) {const int limit =100 ;@@ -1117,6 +1206,103 @@ static int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di,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 ); +bool updated; + +if (bq27xxx_battery_unseal (di) <0 ) +return ; + +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 ); + } + + updated = bd.dirty || bt.dirty; + +bq27xxx_battery_write_dm_block (di, &bd); +bq27xxx_battery_write_dm_block (di, &bt); + +bq27xxx_battery_seal (di); + +if (updated && di->chip !=BQ27421 ) {/* not a cfgupdate chip, so reset */ +bq27xxx_write (di,BQ27XXX_REG_CTRL ,BQ27XXX_RESET , false); +BQ27XXX_MSLEEP (300 );/* reset time is not documented */ + } +/* assume bq27xxx_battery_update() is called hereafter */ +} + +static void bq27xxx_battery_settings (struct bq27xxx_device_info *di) +{ +struct power_supply_battery_info info = {}; +unsigned int min, max; + +if (power_supply_get_battery_info (di->bat, &info) <0 ) +return ; + +if (!di->dm_regs) { +dev_warn (di->dev,"data memory update not supported for chip\n" ); +return ; + } + +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 ) +bq27xxx_battery_set_config (di, &info); +} +/* * Return the battery State-of-Charge * Or < 0 if something fails. @@ -1634,6 +1820,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 ;@@ -1667,7 +1860,10 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)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, + };INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock);@@ -1692,6 +1888,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)dev_info (di->dev,"support ver. %s enabled\n" ,DRIVER_VERSION ); +bq27xxx_battery_settings (di);bq27xxx_battery_update (di);mutex_lock (&bq27xxx_list_lock);include/linux/power/bq27xxx_battery.h +2
-0@@ -63,7 +63,9 @@ struct bq27xxx_device_info {struct device *dev;int id;enum bq27xxx_chip chip; +bool ram_chip;const char *name; +struct bq27xxx_dm_reg *dm_regs;u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;
Re: [PATCH v13 08/11] power: supply: bq27xxx_battery: Add power_supply_battery_info support
Quoted 94 lines · Andrew F. Davis
Quoted 93 lines · Liam Breck
From: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVMis defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now callpower_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is adm_regstable for the chip.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)drivers/power/supply/Kconfig +9
-0@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903Xdrivers/power/supply/bq27xxx_battery.c +39
-0@@ -805,6 +805,13 @@ static LIST_HEAD(bq27xxx_battery_devices);#define BQ27XXX_DM_SZ 32 +struct bq27xxx_dm_reg { +u8 subclass_id; +u8 offset; +u8 bytes; +u16 min, max; +}; +/** * struct bq27xxx_dm_buf - chip data memory buffer * @class: data memory subclass_id @@ -822,6 +829,43 @@ struct bq27xxx_dm_buf {bool has_data, dirty; }; +#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->data + 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 *const bq27xxx_dm_reg_name[] = { + [BQ27XXX_DM_DESIGN_CAPACITY ] ="design-capacity" , + [BQ27XXX_DM_DESIGN_ENERGY ] ="design-energy" , + [BQ27XXX_DM_TERMINATE_VOLTAGE ] ="terminate-voltage" , +}; + + +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM +static bool bq27xxx_dt_to_nvm = true; + +module_param_named (dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool,0444 );
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c struct bq27xxx_dm_buf { · line 865
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+MODULE_PARM_DESC (dt_monitored_battery_updates_nvm, +"Devicetree monitored-battery config updates NVM/flash data memory, if present. Default is 1/y." );As before, the default should not be y, this is a rare case and I can't see it being useful or wanted by anyone but device manufacturers. I don't want everyones chip's factory programmed NVM overwritten by accident when someone compiles and ships a kernel with BATTERY_BQ27XXX_DT_UPDATES_NVM=y
Right, the point of the config option is to let a device vendor ship a kernel + dtb which can field-upgrade NVM. (Setting the option does nothing absent the necessary dtb.)
Module params are for end-user config; we can't require a device vendor to ship /etc/modprobe.d/xyz. And we certainly don't want a kernel package update to defeat the end-user config of dt_monitored_battery_updates_nvm=0 !!
I believe Sebastian agrees, given that he queued this patch :-)
Quoted 211 lines
Quoted 211 lines
drivers/power/supply/bq27xxx_battery.c +157
-1+#else +static bool bq27xxx_dt_to_nvm = false; +#endif static int poll_interval_param_set (const char *val,const struct kernel_param *kp) {@@ -1019,6 +1063,51 @@ static int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di,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->has_data) +return ; + +if (be16_to_cpup (prev) == val) { +dev_info (di->dev,"%s has %u\n" , str, val); +return ; + } + +if (!di->ram_chip && !bq27xxx_dt_to_nvm) { +/* devicetree and NVM differ; defer to NVM */ + dev_warn(di->dev, "%s has %u; update to %u disallowed " +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM + "by dt_monitored_battery_updates_nvm=0" +#else +"for flash/NVM data memory" +#endif +"\n" , str,be16_to_cpup (prev), val); +return ; + } + +dev_info (di->dev,"update %s to %u\n" , str, val); + + *prev =cpu_to_be16 (val); + buf->dirty = true; +} +static int bq27xxx_battery_set_cfgupdate (struct bq27xxx_device_info *di,u16 state) {const int limit =100 ;@@ -1117,6 +1206,103 @@ static int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di,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 ); +bool updated; + +if (bq27xxx_battery_unseal (di) <0 ) +return ; + +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 ); + } + + updated = bd.dirty || bt.dirty; + +bq27xxx_battery_write_dm_block (di, &bd); +bq27xxx_battery_write_dm_block (di, &bt); + +bq27xxx_battery_seal (di); + +if (updated && di->chip !=BQ27421 ) {/* not a cfgupdate chip, so reset */ +bq27xxx_write (di,BQ27XXX_REG_CTRL ,BQ27XXX_RESET , false); +BQ27XXX_MSLEEP (300 );/* reset time is not documented */ + } +/* assume bq27xxx_battery_update() is called hereafter */ +} + +static void bq27xxx_battery_settings (struct bq27xxx_device_info *di) +{ +struct power_supply_battery_info info = {}; +unsigned int min, max; + +if (power_supply_get_battery_info (di->bat, &info) <0 ) +return ; + +if (!di->dm_regs) { +dev_warn (di->dev,"data memory update not supported for chip\n" ); +return ; + } + +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 ) +bq27xxx_battery_set_config (di, &info); +} +/* * Return the battery State-of-Charge * Or < 0 if something fails. @@ -1634,6 +1820,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 ;@@ -1667,7 +1860,10 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)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, + };INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock);@@ -1692,6 +1888,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)dev_info (di->dev,"support ver. %s enabled\n" ,DRIVER_VERSION ); +bq27xxx_battery_settings (di);bq27xxx_battery_update (di);mutex_lock (&bq27xxx_list_lock);include/linux/power/bq27xxx_battery.h +2
-0@@ -63,7 +63,9 @@ struct bq27xxx_device_info {struct device *dev;int id;enum bq27xxx_chip chip; +bool ram_chip;const char *name; +struct bq27xxx_dm_reg *dm_regs;u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;
Re: [PATCH v13 08/11] power: supply: bq27xxx_battery: Add power_supply_battery_info support
Quoted 108 lines · Liam Breck
Quoted 94 lines · Andrew F. Davis
Quoted 93 lines · Liam Breck
From: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVMis defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now callpower_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is adm_regstable for the chip.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)drivers/power/supply/Kconfig +9
-0@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903Xdrivers/power/supply/bq27xxx_battery.c +39
-0@@ -805,6 +805,13 @@ static LIST_HEAD(bq27xxx_battery_devices);#define BQ27XXX_DM_SZ 32 +struct bq27xxx_dm_reg { +u8 subclass_id; +u8 offset; +u8 bytes; +u16 min, max; +}; +/** * struct bq27xxx_dm_buf - chip data memory buffer * @class: data memory subclass_id @@ -822,6 +829,43 @@ struct bq27xxx_dm_buf {bool has_data, dirty; }; +#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->data + 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 *const bq27xxx_dm_reg_name[] = { + [BQ27XXX_DM_DESIGN_CAPACITY ] ="design-capacity" , + [BQ27XXX_DM_DESIGN_ENERGY ] ="design-energy" , + [BQ27XXX_DM_TERMINATE_VOLTAGE ] ="terminate-voltage" , +}; + + +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM +static bool bq27xxx_dt_to_nvm = true; + +module_param_named (dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool,0444 );Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c struct bq27xxx_dm_buf { · line 865
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+MODULE_PARM_DESC (dt_monitored_battery_updates_nvm, +"Devicetree monitored-battery config updates NVM/flash data memory, if present. Default is 1/y." );As before, the default should not be y, this is a rare case and I can't see it being useful or wanted by anyone but device manufacturers. I don't want everyones chip's factory programmed NVM overwritten by accident when someone compiles and ships a kernel with BATTERY_BQ27XXX_DT_UPDATES_NVM=y
Right, the point of the config option is to let a device vendor ship a kernel + dtb which can field-upgrade NVM. (Setting the option does nothing absent the necessary dtb.)
Quoted 6 lines
Module params are for end-user config; we can't require a device vendor to ship
/etc/modprobe.d/xyz. And we certainly don't want a kernel package update to defeat the end-user config of dt_monitored_battery_updates_nvm=0 !!I believe Sebastian agrees, given that he queued this patch :-)
I clarified the rationale for module param default =1 above; could you ack?
That prevents this scenario:
1) user changes battery type, sets dt_monitored_battery_updates_nvm=0
2) vendor ships kernel package with dtb update and dt_monitored_battery_updates_nvm=1
3) gauge stops working correctly
Quoted 211 lines
Quoted 211 lines
Quoted 211 lines
drivers/power/supply/bq27xxx_battery.c +157
-1+#else +static bool bq27xxx_dt_to_nvm = false; +#endif static int poll_interval_param_set (const char *val,const struct kernel_param *kp) {@@ -1019,6 +1063,51 @@ static int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di,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->has_data) +return ; + +if (be16_to_cpup (prev) == val) { +dev_info (di->dev,"%s has %u\n" , str, val); +return ; + } + +if (!di->ram_chip && !bq27xxx_dt_to_nvm) { +/* devicetree and NVM differ; defer to NVM */ + dev_warn(di->dev, "%s has %u; update to %u disallowed " +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM + "by dt_monitored_battery_updates_nvm=0" +#else +"for flash/NVM data memory" +#endif +"\n" , str,be16_to_cpup (prev), val); +return ; + } + +dev_info (di->dev,"update %s to %u\n" , str, val); + + *prev =cpu_to_be16 (val); + buf->dirty = true; +} +static int bq27xxx_battery_set_cfgupdate (struct bq27xxx_device_info *di,u16 state) {const int limit =100 ;@@ -1117,6 +1206,103 @@ static int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di,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 ); +bool updated; + +if (bq27xxx_battery_unseal (di) <0 ) +return ; + +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 ); + } + + updated = bd.dirty || bt.dirty; + +bq27xxx_battery_write_dm_block (di, &bd); +bq27xxx_battery_write_dm_block (di, &bt); + +bq27xxx_battery_seal (di); + +if (updated && di->chip !=BQ27421 ) {/* not a cfgupdate chip, so reset */ +bq27xxx_write (di,BQ27XXX_REG_CTRL ,BQ27XXX_RESET , false); +BQ27XXX_MSLEEP (300 );/* reset time is not documented */ + } +/* assume bq27xxx_battery_update() is called hereafter */ +} + +static void bq27xxx_battery_settings (struct bq27xxx_device_info *di) +{ +struct power_supply_battery_info info = {}; +unsigned int min, max; + +if (power_supply_get_battery_info (di->bat, &info) <0 ) +return ; + +if (!di->dm_regs) { +dev_warn (di->dev,"data memory update not supported for chip\n" ); +return ; + } + +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 ) +bq27xxx_battery_set_config (di, &info); +} +/* * Return the battery State-of-Charge * Or < 0 if something fails. @@ -1634,6 +1820,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 ;@@ -1667,7 +1860,10 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)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, + };INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock);@@ -1692,6 +1888,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)dev_info (di->dev,"support ver. %s enabled\n" ,DRIVER_VERSION ); +bq27xxx_battery_settings (di);bq27xxx_battery_update (di);mutex_lock (&bq27xxx_list_lock);include/linux/power/bq27xxx_battery.h +2
-0@@ -63,7 +63,9 @@ struct bq27xxx_device_info {struct device *dev;int id;enum bq27xxx_chip chip; +bool ram_chip;const char *name; +struct bq27xxx_dm_reg *dm_regs;u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;
Re: [PATCH v13 08/11] power: supply: bq27xxx_battery: Add power_supply_battery_info support
Quoted 116 lines · Liam Breck
Quoted 108 lines · Liam Breck
Quoted 94 lines · Andrew F. Davis
Quoted 93 lines · Liam Breck
From: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVMis defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now callpower_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is adm_regstable for the chip.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)drivers/power/supply/Kconfig +9
-0@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903Xdrivers/power/supply/bq27xxx_battery.c +39
-0@@ -805,6 +805,13 @@ static LIST_HEAD(bq27xxx_battery_devices);#define BQ27XXX_DM_SZ 32 +struct bq27xxx_dm_reg { +u8 subclass_id; +u8 offset; +u8 bytes; +u16 min, max; +}; +/** * struct bq27xxx_dm_buf - chip data memory buffer * @class: data memory subclass_id @@ -822,6 +829,43 @@ struct bq27xxx_dm_buf {bool has_data, dirty; }; +#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->data + 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 *const bq27xxx_dm_reg_name[] = { + [BQ27XXX_DM_DESIGN_CAPACITY ] ="design-capacity" , + [BQ27XXX_DM_DESIGN_ENERGY ] ="design-energy" , + [BQ27XXX_DM_TERMINATE_VOLTAGE ] ="terminate-voltage" , +}; + + +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM +static bool bq27xxx_dt_to_nvm = true; + +module_param_named (dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool,0444 );Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c struct bq27xxx_dm_buf { · line 865
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+MODULE_PARM_DESC (dt_monitored_battery_updates_nvm, +"Devicetree monitored-battery config updates NVM/flash data memory, if present. Default is 1/y." );As before, the default should not be y, this is a rare case and I can't see it being useful or wanted by anyone but device manufacturers. I don't want everyones chip's factory programmed NVM overwritten by accident when someone compiles and ships a kernel with BATTERY_BQ27XXX_DT_UPDATES_NVM=y
Right, the point of the config option is to let a device vendor ship a kernel + dtb which can field-upgrade NVM. (Setting the option does nothing absent the necessary dtb.)
Quoted 6 lines
Module params are for end-user config; we can't require a device vendor to ship
/etc/modprobe.d/xyz. And we certainly don't want a kernel package update to defeat the end-user config of dt_monitored_battery_updates_nvm=0 !!I believe Sebastian agrees, given that he queued this patch :-)
Quoted 8 lines
I clarified the rationale for module param default =1 above; could you ack?
That prevents this scenario:
1) user changes battery type, sets dt_monitored_battery_updates_nvm=0
2) vendor ships kernel package with dtb update and dt_monitored_battery_updates_nvm=1
3) gauge stops working correctly
Leaving it =1 will encourage this situation, not prevent it. Updating NVM is a non-standard operation for these parts. It should only be done once ideally. It is nice being able to update the NVM, and we have user-space tools for this, but this is a dangerous operation, improperly programming can brick the chip, as you have found out.
If you want to add this function into the kernel driver that is fine, but you *cannot* have this be the default, it needs to be a hidden away option for people who know what they are doing, else you will end up accidentally causing damage to countless users' hardware.
Quoted 212 lines
Quoted 212 lines
Quoted 212 lines
Quoted 212 lines
drivers/power/supply/bq27xxx_battery.c +157
-1+#else +static bool bq27xxx_dt_to_nvm = false; +#endif static int poll_interval_param_set (const char *val,const struct kernel_param *kp) {@@ -1019,6 +1063,51 @@ static int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di,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->has_data) +return ; + +if (be16_to_cpup (prev) == val) { +dev_info (di->dev,"%s has %u\n" , str, val); +return ; + } + +if (!di->ram_chip && !bq27xxx_dt_to_nvm) { +/* devicetree and NVM differ; defer to NVM */ + dev_warn(di->dev, "%s has %u; update to %u disallowed " +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM + "by dt_monitored_battery_updates_nvm=0" +#else +"for flash/NVM data memory" +#endif +"\n" , str,be16_to_cpup (prev), val); +return ; + } + +dev_info (di->dev,"update %s to %u\n" , str, val); + + *prev =cpu_to_be16 (val); + buf->dirty = true; +} +static int bq27xxx_battery_set_cfgupdate (struct bq27xxx_device_info *di,u16 state) {const int limit =100 ;@@ -1117,6 +1206,103 @@ static int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di,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 ); +bool updated; + +if (bq27xxx_battery_unseal (di) <0 ) +return ; + +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 ); + } + + updated = bd.dirty || bt.dirty; + +bq27xxx_battery_write_dm_block (di, &bd); +bq27xxx_battery_write_dm_block (di, &bt); + +bq27xxx_battery_seal (di); + +if (updated && di->chip !=BQ27421 ) {/* not a cfgupdate chip, so reset */ +bq27xxx_write (di,BQ27XXX_REG_CTRL ,BQ27XXX_RESET , false); +BQ27XXX_MSLEEP (300 );/* reset time is not documented */ + } +/* assume bq27xxx_battery_update() is called hereafter */ +} + +static void bq27xxx_battery_settings (struct bq27xxx_device_info *di) +{ +struct power_supply_battery_info info = {}; +unsigned int min, max; + +if (power_supply_get_battery_info (di->bat, &info) <0 ) +return ; + +if (!di->dm_regs) { +dev_warn (di->dev,"data memory update not supported for chip\n" ); +return ; + } + +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 ) +bq27xxx_battery_set_config (di, &info); +} +/* * Return the battery State-of-Charge * Or < 0 if something fails. @@ -1634,6 +1820,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 ;@@ -1667,7 +1860,10 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)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, + };INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock);@@ -1692,6 +1888,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)dev_info (di->dev,"support ver. %s enabled\n" ,DRIVER_VERSION ); +bq27xxx_battery_settings (di);bq27xxx_battery_update (di);mutex_lock (&bq27xxx_list_lock);include/linux/power/bq27xxx_battery.h +2
-0@@ -63,7 +63,9 @@ struct bq27xxx_device_info {struct device *dev;int id;enum bq27xxx_chip chip; +bool ram_chip;const char *name; +struct bq27xxx_dm_reg *dm_regs;u32 unseal_key;struct bq27xxx_access_methods bus;struct bq27xxx_reg_cache cache;
Re: [PATCH v13 08/11] power: supply: bq27xxx_battery: Add power_supply_battery_info support
Quoted 132 lines · Andrew F. Davis
Quoted 116 lines · Liam Breck
Quoted 108 lines · Liam Breck
Quoted 94 lines · Andrew F. Davis
Quoted 93 lines · Liam Breck
From: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVMis defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now callpower_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is adm_regstable for the chip.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)drivers/power/supply/Kconfig +9
-0@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903Xdrivers/power/supply/bq27xxx_battery.c +39
-0@@ -805,6 +805,13 @@ static LIST_HEAD(bq27xxx_battery_devices);#define BQ27XXX_DM_SZ 32 +struct bq27xxx_dm_reg { +u8 subclass_id; +u8 offset; +u8 bytes; +u16 min, max; +}; +/** * struct bq27xxx_dm_buf - chip data memory buffer * @class: data memory subclass_id @@ -822,6 +829,43 @@ struct bq27xxx_dm_buf {bool has_data, dirty; }; +#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->data + 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 *const bq27xxx_dm_reg_name[] = { + [BQ27XXX_DM_DESIGN_CAPACITY ] ="design-capacity" , + [BQ27XXX_DM_DESIGN_ENERGY ] ="design-energy" , + [BQ27XXX_DM_TERMINATE_VOLTAGE ] ="terminate-voltage" , +}; + + +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM +static bool bq27xxx_dt_to_nvm = true; + +module_param_named (dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool,0444 );Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c struct bq27xxx_dm_buf { · line 865
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+MODULE_PARM_DESC (dt_monitored_battery_updates_nvm, +"Devicetree monitored-battery config updates NVM/flash data memory, if present. Default is 1/y." );As before, the default should not be y, this is a rare case and I can't see it being useful or wanted by anyone but device manufacturers. I don't want everyones chip's factory programmed NVM overwritten by accident when someone compiles and ships a kernel with BATTERY_BQ27XXX_DT_UPDATES_NVM=y
Right, the point of the config option is to let a device vendor ship a kernel + dtb which can field-upgrade NVM. (Setting the option does nothing absent the necessary dtb.)
Quoted 6 lines
Module params are for end-user config; we can't require a device vendor to ship
/etc/modprobe.d/xyz. And we certainly don't want a kernel package update to defeat the end-user config of dt_monitored_battery_updates_nvm=0 !!I believe Sebastian agrees, given that he queued this patch :-)
Quoted 8 lines
I clarified the rationale for module param default =1 above; could you ack?
That prevents this scenario:
1) user changes battery type, sets dt_monitored_battery_updates_nvm=0
2) vendor ships kernel package with dtb update and dt_monitored_battery_updates_nvm=1
3) gauge stops working correctlyLeaving it =1 will encourage this situation, not prevent it. Updating NVM is a non-standard operation for these parts. It should only be done once ideally. It is nice being able to update the NVM, and we have user-space tools for this, but this is a dangerous operation, improperly programming can brick the chip, as you have found out.
Quoted 4 lines
If you want to add this function into the kernel driver that is fine, but you *cannot* have this be the default, it needs to be a hidden away option for people who know what they are doing, else you will end up accidentally causing damage to countless users' hardware.
I don't think you followed my logic.... It *is* hidden behind a dedicated kernel config option which only device vendors (and tinkerers :-) would use. A kernel package with that option and suitable dtb has to perform the update without manipulation of the module param. The module param is to let the user prevent any future update by such a kernel package, since only he knows that he changed the battery type.
What is your evidence for the assertion of "encourage this situation"?
Re: [PATCH v13 08/11] power: supply: bq27xxx_battery: Add power_supply_battery_info support
Quoted 146 lines · Liam Breck
Quoted 132 lines · Andrew F. Davis
Quoted 116 lines · Liam Breck
Quoted 108 lines · Liam Breck
Quoted 94 lines · Andrew F. Davis
Quoted 93 lines · Liam Breck
From: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVMis defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now callpower_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is adm_regstable for the chip.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)drivers/power/supply/Kconfig +9
-0@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903Xdrivers/power/supply/bq27xxx_battery.c +39
-0@@ -805,6 +805,13 @@ static LIST_HEAD(bq27xxx_battery_devices);#define BQ27XXX_DM_SZ 32 +struct bq27xxx_dm_reg { +u8 subclass_id; +u8 offset; +u8 bytes; +u16 min, max; +}; +/** * struct bq27xxx_dm_buf - chip data memory buffer * @class: data memory subclass_id @@ -822,6 +829,43 @@ struct bq27xxx_dm_buf {bool has_data, dirty; }; +#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->data + 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 *const bq27xxx_dm_reg_name[] = { + [BQ27XXX_DM_DESIGN_CAPACITY ] ="design-capacity" , + [BQ27XXX_DM_DESIGN_ENERGY ] ="design-energy" , + [BQ27XXX_DM_TERMINATE_VOLTAGE ] ="terminate-voltage" , +}; + + +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM +static bool bq27xxx_dt_to_nvm = true; + +module_param_named (dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool,0444 );Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c struct bq27xxx_dm_buf { · line 865
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+MODULE_PARM_DESC (dt_monitored_battery_updates_nvm, +"Devicetree monitored-battery config updates NVM/flash data memory, if present. Default is 1/y." );As before, the default should not be y, this is a rare case and I can't see it being useful or wanted by anyone but device manufacturers. I don't want everyones chip's factory programmed NVM overwritten by accident when someone compiles and ships a kernel with BATTERY_BQ27XXX_DT_UPDATES_NVM=y
Right, the point of the config option is to let a device vendor ship a kernel + dtb which can field-upgrade NVM. (Setting the option does nothing absent the necessary dtb.)
Quoted 6 lines
Module params are for end-user config; we can't require a device vendor to ship
/etc/modprobe.d/xyz. And we certainly don't want a kernel package update to defeat the end-user config of dt_monitored_battery_updates_nvm=0 !!I believe Sebastian agrees, given that he queued this patch :-)
Quoted 8 lines
I clarified the rationale for module param default =1 above; could you ack?
That prevents this scenario:
1) user changes battery type, sets dt_monitored_battery_updates_nvm=0
2) vendor ships kernel package with dtb update and dt_monitored_battery_updates_nvm=1
3) gauge stops working correctlyLeaving it =1 will encourage this situation, not prevent it. Updating NVM is a non-standard operation for these parts. It should only be done once ideally. It is nice being able to update the NVM, and we have user-space tools for this, but this is a dangerous operation, improperly programming can brick the chip, as you have found out.
Quoted 4 lines
If you want to add this function into the kernel driver that is fine, but you *cannot* have this be the default, it needs to be a hidden away option for people who know what they are doing, else you will end up accidentally causing damage to countless users' hardware.
I don't think you followed my logic.... It *is* hidden behind a dedicated kernel config option which only device vendors (and tinkerers :-) would use. A kernel package with that option and suitable dtb has to perform the update without manipulation of the module param. The module param is to let the user prevent any future update by such a kernel package, since only he knows that he changed the battery type.
Quoted 2 lines
What is your evidence for the assertion of "encourage this situation"?
It is the default value, what more evidence do you want? Someone should have to enable the functionality in Kconfig *and* enable it as a module_param. Leaving either on by default will cause it to be accidentally left enabled.
Re: [PATCH v13 08/11] power: supply: bq27xxx_battery: Add power_supply_battery_info support
Quoted 147 lines · Andrew F. Davis
Quoted 146 lines · Liam Breck
Quoted 132 lines · Andrew F. Davis
Quoted 116 lines · Liam Breck
Quoted 108 lines · Liam Breck
Quoted 94 lines · Andrew F. Davis
Quoted 93 lines · Liam Breck
From: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVMis defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now callpower_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is adm_regstable for the chip.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)drivers/power/supply/Kconfig +9
-0@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903Xdrivers/power/supply/bq27xxx_battery.c +39
-0@@ -805,6 +805,13 @@ static LIST_HEAD(bq27xxx_battery_devices);#define BQ27XXX_DM_SZ 32 +struct bq27xxx_dm_reg { +u8 subclass_id; +u8 offset; +u8 bytes; +u16 min, max; +}; +/** * struct bq27xxx_dm_buf - chip data memory buffer * @class: data memory subclass_id @@ -822,6 +829,43 @@ struct bq27xxx_dm_buf {bool has_data, dirty; }; +#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->data + 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 *const bq27xxx_dm_reg_name[] = { + [BQ27XXX_DM_DESIGN_CAPACITY ] ="design-capacity" , + [BQ27XXX_DM_DESIGN_ENERGY ] ="design-energy" , + [BQ27XXX_DM_TERMINATE_VOLTAGE ] ="terminate-voltage" , +}; + + +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM +static bool bq27xxx_dt_to_nvm = true; + +module_param_named (dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool,0444 );Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c struct bq27xxx_dm_buf { · line 865
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+MODULE_PARM_DESC (dt_monitored_battery_updates_nvm, +"Devicetree monitored-battery config updates NVM/flash data memory, if present. Default is 1/y." );As before, the default should not be y, this is a rare case and I can't see it being useful or wanted by anyone but device manufacturers. I don't want everyones chip's factory programmed NVM overwritten by accident when someone compiles and ships a kernel with BATTERY_BQ27XXX_DT_UPDATES_NVM=y
Right, the point of the config option is to let a device vendor ship a kernel + dtb which can field-upgrade NVM. (Setting the option does nothing absent the necessary dtb.)
Quoted 6 lines
Module params are for end-user config; we can't require a device vendor to ship
/etc/modprobe.d/xyz. And we certainly don't want a kernel package update to defeat the end-user config of dt_monitored_battery_updates_nvm=0 !!I believe Sebastian agrees, given that he queued this patch :-)
Quoted 8 lines
I clarified the rationale for module param default =1 above; could you ack?
That prevents this scenario:
1) user changes battery type, sets dt_monitored_battery_updates_nvm=0
2) vendor ships kernel package with dtb update and dt_monitored_battery_updates_nvm=1
3) gauge stops working correctlyLeaving it =1 will encourage this situation, not prevent it. Updating NVM is a non-standard operation for these parts. It should only be done once ideally. It is nice being able to update the NVM, and we have user-space tools for this, but this is a dangerous operation, improperly programming can brick the chip, as you have found out.
Quoted 4 lines
If you want to add this function into the kernel driver that is fine, but you *cannot* have this be the default, it needs to be a hidden away option for people who know what they are doing, else you will end up accidentally causing damage to countless users' hardware.
I don't think you followed my logic.... It *is* hidden behind a dedicated kernel config option which only device vendors (and tinkerers :-) would use. A kernel package with that option and suitable dtb has to perform the update without manipulation of the module param. The module param is to let the user prevent any future update by such a kernel package, since only he knows that he changed the battery type.
Quoted 7 lines
Quoted 2 lines
What is your evidence for the assertion of "encourage this situation"?
It is the default value, what more evidence do you want? Someone should have to enable the functionality in
Kconfig*and* enable it as amodule_param. Leaving either on by default will cause it to be accidentally left enabled.
We could add a second config option to eliminate the possibility of the first one being set by mistake.
You can't trivially enable a config option. If you set it, you'd obviously set the module param if that were necessary, so that's no extra protection against "accidentally left enabled". (And the config option does nothing without a suitable dtb.)
My scenario is a clear and likely threat. You haven't described a threat scenario.
The docs for the config option describe its correct use, and I will mention the risk of overwriting a smart battery. No general purpose distro will enable it.
Re: [PATCH v13 08/11] power: supply: bq27xxx_battery: Add power_supply_battery_info support
Quoted 156 lines · Liam Breck
Quoted 147 lines · Andrew F. Davis
Quoted 146 lines · Liam Breck
Quoted 132 lines · Andrew F. Davis
Quoted 116 lines · Liam Breck
Quoted 108 lines · Liam Breck
Quoted 94 lines · Andrew F. Davis
Quoted 93 lines · Liam Breck
From: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVMis defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now callpower_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is adm_regstable for the chip.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)drivers/power/supply/Kconfig +9
-0@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903Xdrivers/power/supply/bq27xxx_battery.c +39
-0@@ -805,6 +805,13 @@ static LIST_HEAD(bq27xxx_battery_devices);#define BQ27XXX_DM_SZ 32 +struct bq27xxx_dm_reg { +u8 subclass_id; +u8 offset; +u8 bytes; +u16 min, max; +}; +/** * struct bq27xxx_dm_buf - chip data memory buffer * @class: data memory subclass_id @@ -822,6 +829,43 @@ struct bq27xxx_dm_buf {bool has_data, dirty; }; +#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->data + 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 *const bq27xxx_dm_reg_name[] = { + [BQ27XXX_DM_DESIGN_CAPACITY ] ="design-capacity" , + [BQ27XXX_DM_DESIGN_ENERGY ] ="design-energy" , + [BQ27XXX_DM_TERMINATE_VOLTAGE ] ="terminate-voltage" , +}; + + +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM +static bool bq27xxx_dt_to_nvm = true; + +module_param_named (dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool,0444 );Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c struct bq27xxx_dm_buf { · line 865
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+MODULE_PARM_DESC (dt_monitored_battery_updates_nvm, +"Devicetree monitored-battery config updates NVM/flash data memory, if present. Default is 1/y." );As before, the default should not be y, this is a rare case and I can't see it being useful or wanted by anyone but device manufacturers. I don't want everyones chip's factory programmed NVM overwritten by accident when someone compiles and ships a kernel with BATTERY_BQ27XXX_DT_UPDATES_NVM=y
Right, the point of the config option is to let a device vendor ship a kernel + dtb which can field-upgrade NVM. (Setting the option does nothing absent the necessary dtb.)
Quoted 6 lines
Module params are for end-user config; we can't require a device vendor to ship
/etc/modprobe.d/xyz. And we certainly don't want a kernel package update to defeat the end-user config of dt_monitored_battery_updates_nvm=0 !!I believe Sebastian agrees, given that he queued this patch :-)
Quoted 8 lines
I clarified the rationale for module param default =1 above; could you ack?
That prevents this scenario:
1) user changes battery type, sets dt_monitored_battery_updates_nvm=0
2) vendor ships kernel package with dtb update and dt_monitored_battery_updates_nvm=1
3) gauge stops working correctlyLeaving it =1 will encourage this situation, not prevent it. Updating NVM is a non-standard operation for these parts. It should only be done once ideally. It is nice being able to update the NVM, and we have user-space tools for this, but this is a dangerous operation, improperly programming can brick the chip, as you have found out.
Quoted 4 lines
If you want to add this function into the kernel driver that is fine, but you *cannot* have this be the default, it needs to be a hidden away option for people who know what they are doing, else you will end up accidentally causing damage to countless users' hardware.
I don't think you followed my logic.... It *is* hidden behind a dedicated kernel config option which only device vendors (and tinkerers :-) would use. A kernel package with that option and suitable dtb has to perform the update without manipulation of the module param. The module param is to let the user prevent any future update by such a kernel package, since only he knows that he changed the battery type.
Quoted 7 lines
Quoted 2 lines
What is your evidence for the assertion of "encourage this situation"?
It is the default value, what more evidence do you want? Someone should have to enable the functionality in
Kconfig*and* enable it as amodule_param. Leaving either on by default will cause it to be accidentally left enabled.
Quoted 8 lines
We could add a second config option to eliminate the possibility of the first one being set by mistake.
You can't trivially enable a config option. If you set it, you'd obviously set the module param if that were necessary, so that's no extra protection against "accidentally left enabled". (And the config option does nothing without a suitable dtb.)
Why would you "obviously set the module param"? If this config option is enabled then you still have to set the module param to make this write to your device's NVM, that is two things vs one. The people who use kernels often don't build them. Both should need to be set to update the devices NVM.
Quoted 3 lines
My scenario is a clear and likely threat. You haven't described a threat scenario.
Easy, kernel is built with the config option enabled and their DT has invalid option for their battery. Now everyone bricks their hardware.
Vs. your three step situation that the two people who will ever use this will never actually find themselves in, that results in a minor inconvenience as they have to turn a module param back off.
Lets take the safe route and leave this default off.
Quoted 4 lines
The docs for the config option describe its correct use, and I will mention the risk of overwriting a smart battery. No general purpose distro will enable it.
How can you know this, I'm pretty sure Ubuntu ships with a randconfig kernel :)
Re: [PATCH v13 08/11] power: supply: bq27xxx_battery: Add power_supply_battery_info support
Quoted 166 lines · Andrew F. Davis
Quoted 156 lines · Liam Breck
Quoted 147 lines · Andrew F. Davis
Quoted 146 lines · Liam Breck
Quoted 132 lines · Andrew F. Davis
Quoted 116 lines · Liam Breck
Quoted 108 lines · Liam Breck
Quoted 94 lines · Andrew F. Davis
Quoted 93 lines · Liam Breck
From: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVMis defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now callpower_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is adm_regstable for the chip.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)drivers/power/supply/Kconfig +9
-0@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903Xdrivers/power/supply/bq27xxx_battery.c +39
-0@@ -805,6 +805,13 @@ static LIST_HEAD(bq27xxx_battery_devices);#define BQ27XXX_DM_SZ 32 +struct bq27xxx_dm_reg { +u8 subclass_id; +u8 offset; +u8 bytes; +u16 min, max; +}; +/** * struct bq27xxx_dm_buf - chip data memory buffer * @class: data memory subclass_id @@ -822,6 +829,43 @@ struct bq27xxx_dm_buf {bool has_data, dirty; }; +#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->data + 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 *const bq27xxx_dm_reg_name[] = { + [BQ27XXX_DM_DESIGN_CAPACITY ] ="design-capacity" , + [BQ27XXX_DM_DESIGN_ENERGY ] ="design-energy" , + [BQ27XXX_DM_TERMINATE_VOLTAGE ] ="terminate-voltage" , +}; + + +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM +static bool bq27xxx_dt_to_nvm = true; + +module_param_named (dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool,0444 );Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c struct bq27xxx_dm_buf { · line 865
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+MODULE_PARM_DESC (dt_monitored_battery_updates_nvm, +"Devicetree monitored-battery config updates NVM/flash data memory, if present. Default is 1/y." );As before, the default should not be y, this is a rare case and I can't see it being useful or wanted by anyone but device manufacturers. I don't want everyones chip's factory programmed NVM overwritten by accident when someone compiles and ships a kernel with BATTERY_BQ27XXX_DT_UPDATES_NVM=y
Right, the point of the config option is to let a device vendor ship a kernel + dtb which can field-upgrade NVM. (Setting the option does nothing absent the necessary dtb.)
Quoted 6 lines
Module params are for end-user config; we can't require a device vendor to ship
/etc/modprobe.d/xyz. And we certainly don't want a kernel package update to defeat the end-user config of dt_monitored_battery_updates_nvm=0 !!I believe Sebastian agrees, given that he queued this patch :-)
Quoted 8 lines
I clarified the rationale for module param default =1 above; could you ack?
That prevents this scenario:
1) user changes battery type, sets dt_monitored_battery_updates_nvm=0
2) vendor ships kernel package with dtb update and dt_monitored_battery_updates_nvm=1
3) gauge stops working correctlyLeaving it =1 will encourage this situation, not prevent it. Updating NVM is a non-standard operation for these parts. It should only be done once ideally. It is nice being able to update the NVM, and we have user-space tools for this, but this is a dangerous operation, improperly programming can brick the chip, as you have found out.
Quoted 4 lines
If you want to add this function into the kernel driver that is fine, but you *cannot* have this be the default, it needs to be a hidden away option for people who know what they are doing, else you will end up accidentally causing damage to countless users' hardware.
I don't think you followed my logic.... It *is* hidden behind a dedicated kernel config option which only device vendors (and tinkerers :-) would use. A kernel package with that option and suitable dtb has to perform the update without manipulation of the module param. The module param is to let the user prevent any future update by such a kernel package, since only he knows that he changed the battery type.
Quoted 7 lines
Quoted 2 lines
What is your evidence for the assertion of "encourage this situation"?
It is the default value, what more evidence do you want? Someone should have to enable the functionality in
Kconfig*and* enable it as amodule_param. Leaving either on by default will cause it to be accidentally left enabled.Quoted 8 lines
We could add a second config option to eliminate the possibility of the first one being set by mistake.
You can't trivially enable a config option. If you set it, you'd obviously set the module param if that were necessary, so that's no extra protection against "accidentally left enabled". (And the config option does nothing without a suitable dtb.)
Quoted 5 lines
Why would you "obviously set the module param"? If this config option is enabled then you still have to set the module param to make this write to your device's NVM, that is two things vs one. The people who use kernels often don't build them. Both should need to be set to update the devices NVM.
The target of this config option is device vendors. They would obviously set the module param when setting the config option to field-upgrade NVM.
Quoted 6 lines
Quoted 3 lines
My scenario is a clear and likely threat. You haven't described a threat scenario.
Easy, kernel is built with the config option enabled and their DT has invalid option for their battery. Now everyone bricks their hardware.
A device vendor could misconfigure their hw, sure. They would also fix it in an update. That's not a threat. In what scenario does someone other than the vendor or tinkering user misconfigure the gauge?
Quoted 3 lines
Vs. your three step situation that the two people who will ever use this will never actually find themselves in, that results in a minor inconvenience as they have to turn a module param back off.
I don't think you followed the scenario. User resetting the param =0 after a vendor update sets =1 would not fix the NVM misconfig caused by the update! The whole point of user setting =0 is to prevent that update.
Quoted 1 line
Lets take the safe route and leave this default off.
I offered you a safe route: two config options.
Quoted 7 lines
Quoted 4 lines
The docs for the config option describe its correct use, and I will mention the risk of overwriting a smart battery. No general purpose distro will enable it.
How can you know this, I'm pretty sure Ubuntu ships with a randconfig kernel :)
And that includes a rand dtb? :-p
Re: [PATCH v13 08/11] power: supply: bq27xxx_battery: Add power_supply_battery_info support
Quoted 173 lines · Liam Breck
Quoted 166 lines · Andrew F. Davis
Quoted 156 lines · Liam Breck
Quoted 147 lines · Andrew F. Davis
Quoted 146 lines · Liam Breck
Quoted 132 lines · Andrew F. Davis
Quoted 116 lines · Liam Breck
Quoted 108 lines · Liam Breck
Quoted 94 lines · Andrew F. Davis
Quoted 93 lines · Liam Breck
From: Liam Breck <[email protected]>
Previously there was no way to configure these chips in the event that the defaults didn't match the battery in question.
For chips with RAM data memory (and also those with flash/NVM data memory if
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVMis defined and the user has not set module param dt_monitored_battery_updates_nvm=0) we now callpower_supply_get_battery_info(), check its values, and write battery properties to chip data memory if there is adm_regstable for the chip.Signed-off-by Matt Ranostay <[email protected]>Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/bq27xxx_battery.c | 199 ++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 2 + 3 files changed, 209 insertions(+), 1 deletion(-)drivers/power/supply/Kconfig +9
-0@@ -178,6 +178,15 @@ config BATTERY_BQ27XXX_I2C Say Y here to enable support for batteries with BQ27xxx chips connected over an I2C bus. +config BATTERY_BQ27XXX_DT_UPDATES_NVM + bool "BQ27xxx support for update of NVM/flash data memory" + depends on BATTERY_BQ27XXX_I2C + help + Say Y here to enable devicetree monitored-battery config to update + NVM/flash data memory. Only enable this option for devices with a + fuel gauge mounted on the circuit board, and a battery that cannot + be replaced with one of a different type. + config BATTERY_DA9030 tristate "DA9030 battery driver" depends on PMIC_DA903Xdrivers/power/supply/bq27xxx_battery.c +39
-0@@ -805,6 +805,13 @@ static LIST_HEAD(bq27xxx_battery_devices);#define BQ27XXX_DM_SZ 32 +struct bq27xxx_dm_reg { +u8 subclass_id; +u8 offset; +u8 bytes; +u16 min, max; +}; +/** * struct bq27xxx_dm_buf - chip data memory buffer * @class: data memory subclass_id @@ -822,6 +829,43 @@ struct bq27xxx_dm_buf {bool has_data, dirty; }; +#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->data + 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 *const bq27xxx_dm_reg_name[] = { + [BQ27XXX_DM_DESIGN_CAPACITY ] ="design-capacity" , + [BQ27XXX_DM_DESIGN_ENERGY ] ="design-energy" , + [BQ27XXX_DM_TERMINATE_VOLTAGE ] ="terminate-voltage" , +}; + + +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM +static bool bq27xxx_dt_to_nvm = true; + +module_param_named (dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool,0444 );Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c struct bq27xxx_dm_buf { · line 865
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +2
-0+MODULE_PARM_DESC (dt_monitored_battery_updates_nvm, +"Devicetree monitored-battery config updates NVM/flash data memory, if present. Default is 1/y." );As before, the default should not be y, this is a rare case and I can't see it being useful or wanted by anyone but device manufacturers. I don't want everyones chip's factory programmed NVM overwritten by accident when someone compiles and ships a kernel with BATTERY_BQ27XXX_DT_UPDATES_NVM=y
Right, the point of the config option is to let a device vendor ship a kernel + dtb which can field-upgrade NVM. (Setting the option does nothing absent the necessary dtb.)
Quoted 6 lines
Module params are for end-user config; we can't require a device vendor to ship
/etc/modprobe.d/xyz. And we certainly don't want a kernel package update to defeat the end-user config of dt_monitored_battery_updates_nvm=0 !!I believe Sebastian agrees, given that he queued this patch :-)
Quoted 8 lines
I clarified the rationale for module param default =1 above; could you ack?
That prevents this scenario:
1) user changes battery type, sets dt_monitored_battery_updates_nvm=0
2) vendor ships kernel package with dtb update and dt_monitored_battery_updates_nvm=1
3) gauge stops working correctlyLeaving it =1 will encourage this situation, not prevent it. Updating NVM is a non-standard operation for these parts. It should only be done once ideally. It is nice being able to update the NVM, and we have user-space tools for this, but this is a dangerous operation, improperly programming can brick the chip, as you have found out.
Quoted 4 lines
If you want to add this function into the kernel driver that is fine, but you *cannot* have this be the default, it needs to be a hidden away option for people who know what they are doing, else you will end up accidentally causing damage to countless users' hardware.
I don't think you followed my logic.... It *is* hidden behind a dedicated kernel config option which only device vendors (and tinkerers :-) would use. A kernel package with that option and suitable dtb has to perform the update without manipulation of the module param. The module param is to let the user prevent any future update by such a kernel package, since only he knows that he changed the battery type.
Quoted 7 lines
Quoted 2 lines
What is your evidence for the assertion of "encourage this situation"?
It is the default value, what more evidence do you want? Someone should have to enable the functionality in
Kconfig*and* enable it as amodule_param. Leaving either on by default will cause it to be accidentally left enabled.Quoted 8 lines
We could add a second config option to eliminate the possibility of the first one being set by mistake.
You can't trivially enable a config option. If you set it, you'd obviously set the module param if that were necessary, so that's no extra protection against "accidentally left enabled". (And the config option does nothing without a suitable dtb.)
Quoted 5 lines
Why would you "obviously set the module param"? If this config option is enabled then you still have to set the module param to make this write to your device's NVM, that is two things vs one. The people who use kernels often don't build them. Both should need to be set to update the devices NVM.
Quoted 4 lines
The target of this config option is device vendors. They would obviously set the module param when setting the config option to field-upgrade NVM.
Great, they we don't need to have it default =1 if they will obviously set it, problem solved.
Quoted 11 lines
Quoted 6 lines
Quoted 3 lines
My scenario is a clear and likely threat. You haven't described a threat scenario.
Easy, kernel is built with the config option enabled and their DT has invalid option for their battery. Now everyone bricks their hardware.
A device vendor could misconfigure their hw, sure. They would also fix it in an update. That's not a threat. In what scenario does someone other than the vendor or tinkering user misconfigure the gauge?
Quoted 9 lines
Quoted 3 lines
Vs. your three step situation that the two people who will ever use this will never actually find themselves in, that results in a minor inconvenience as they have to turn a module param back off.
I don't think you followed the scenario. User resetting the param =0 after a vendor update sets =1 would not fix the NVM misconfig caused by the update! The whole point of user setting =0 is to prevent that update.
Updates are optional, you shouldn't have to manually prevent an update.
Quoted 4 lines
Quoted 1 line
Lets take the safe route and leave this default off.
I offered you a safe route: two config options.
How about a default off module param so we don't clutter the kconfig.
Quoted 10 lines
Quoted 7 lines
Quoted 4 lines
The docs for the config option describe its correct use, and I will mention the risk of overwriting a smart battery. No general purpose distro will enable it.
How can you know this, I'm pretty sure Ubuntu ships with a randconfig kernel :)
And that includes a rand dtb? :-p
PATCH v13 9/11 power: supply: bq27xxx_battery: Enable data memory update for certain chips
In reply to Liam BreckFrom: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)
drivers/power/supply/bq27xxx_battery.c +86 -4
@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"
@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,
@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),
@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);
@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;
@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip]; + + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)
drivers/power/supply/bq27xxx_battery_i2c.c +8 -8
@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },
@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);
include/linux/power/bq27xxx_battery.h +13 -0
@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */
@@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Signature · 1 line
2.9.3
Andrew F. Davis
NAKRe: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 135 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +5
-0@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];
NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 139 lines · Andrew F. Davis
Quoted 138 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, };
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+ di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
You forget that the original I2C table did this exact translation. This isn't any more hacky than that. I do not see a better alternative. If you do, pls draft a little code to illustrate it.
Quoted 3 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
I have simply replicated the original design, which avoided dupes in the reg & properties tables by translating IDs in the I2C table. It's not a work-around on my part, and I believe it's the correct scheme.
Quoted 1 line
Also fix all the checkpatch --strict warnings.
OK, but some lines are more readable over 80 chars, so I will leave them as is.
Can you take another pass or two to illuminate any remaining issues before my next rev? I'd like it to be the last one :-)
Quoted 78 lines
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
In reply to Andrew F. DavisQuoted 139 lines · Andrew F. Davis
Quoted 138 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, };
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+ di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Quoted 84 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 151 lines · Liam Breck
Quoted 139 lines · Andrew F. Davis
Quoted 138 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, };Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+ di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated.
Quoted 1 line
From the one ID you can then use tables to lookup any other info about
that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = {
[bq27425] = {
.regs = &bq27xxx_regs[bq27425],
.dm_regs = &bq27xxx_dm_regs[bq274xx],
.unseal_key = INVALID_FOR_THIS_DEVICE,
},
[bq27343] = {...
Not sure if that is valid C but I think you can get the idea.
Quoted 85 lines
Quoted 85 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 152 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 149 lines · Andrew F. Davis
Quoted 135 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +5
-0@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 7 lines
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated.
Take a look at bq27xxx_i2c_id_table[] here:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/drivers/power/supply/bq27xxx_battery_i2c.c?h=linux-4.11.y#n148
Notice how this table maps certain chips to the same IDs. I am going to preserve that scheme, as changing it is outside the scope of this series.
So the only question is how to deliver the "real" ID to the driver. In v13, I change the I2C table to deliver real-ID, and replicate the mapping of the orig I2C table in bq27xxx_chips[]. Now I propose to make the I2C table carry two values, chip-ID and real-ID. Then we can drop bq27xxx_chips[].
Hope that clarifies the issue...
Quoted 100 lines
From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {...
Not sure if that is valid C but I think you can get the idea.
Quoted 85 lines
Quoted 85 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 161 lines · Liam Breck
Quoted 152 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 149 lines · Andrew F. Davis
Quoted 135 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +5
-0@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 7 lines
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated.
Quoted 7 lines
Take a look at bq27xxx_i2c_id_table[] here:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/drivers/power/supply/bq27xxx_battery_i2c.c?h=linux-4.11.y#n148Notice how this table maps certain chips to the same IDs. I am going to preserve that scheme, as changing it is outside the scope of this series.
You can't just say doing something the right is "outside the scope of this series" then hack something together...
Fixing this should be trivial anyway, add the new IDs, pass the real IDs in, then add the translation table so you don't have to add any new entries to bq27xxx_regs.
Quoted 108 lines
So the only question is how to deliver the "real" ID to the driver. In v13, I change the I2C table to deliver real-ID, and replicate the mapping of the orig I2C table in bq27xxx_chips[]. Now I propose to make the I2C table carry two values, chip-ID and real-ID. Then we can drop bq27xxx_chips[].
Hope that clarifies the issue...
Quoted 100 lines
From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {...
Not sure if that is valid C but I think you can get the idea.
Quoted 85 lines
Quoted 85 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 170 lines · Andrew F. Davis
Quoted 161 lines · Liam Breck
Quoted 152 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 149 lines · Andrew F. Davis
Quoted 135 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +5
-0@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 7 lines
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated.
Quoted 7 lines
Take a look at bq27xxx_i2c_id_table[] here:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/drivers/power/supply/bq27xxx_battery_i2c.c?h=linux-4.11.y#n148Notice how this table maps certain chips to the same IDs. I am going to preserve that scheme, as changing it is outside the scope of this series.
Quoted 6 lines
You can't just say doing something the right is "outside the scope of this series" then hack something together...
Fixing this should be trivial anyway, add the new IDs, pass the real IDs in, then add the translation table so you don't have to add any new entries to
bq27xxx_regs.
That is *precisely* what I do in v13. Except I don't store real-ID in a di field because there isn't a use for it. Add that later if you need it.
bq27xxx_chips[] is the translation table. However we could unify that with the I2C table by placing two values in its driver_data field, and I think that's cleaner.
Quoted 108 lines
Quoted 108 lines
So the only question is how to deliver the "real" ID to the driver. In v13, I change the I2C table to deliver real-ID, and replicate the mapping of the orig I2C table in bq27xxx_chips[]. Now I propose to make the I2C table carry two values, chip-ID and real-ID. Then we can drop bq27xxx_chips[].
Hope that clarifies the issue...
Quoted 100 lines
From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {...
Not sure if that is valid C but I think you can get the idea.
Quoted 85 lines
Quoted 85 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 174 lines · Liam Breck
Quoted 173 lines · Andrew F. Davis
Quoted 161 lines · Liam Breck
Quoted 152 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 149 lines · Andrew F. Davis
Quoted 135 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +5
-0@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 7 lines
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated.
Quoted 7 lines
Take a look at bq27xxx_i2c_id_table[] here:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/drivers/power/supply/bq27xxx_battery_i2c.c?h=linux-4.11.y#n148Notice how this table maps certain chips to the same IDs. I am going to preserve that scheme, as changing it is outside the scope of this series.
You can't just say doing something the right is "outside the scope of this series" then hack something together...
Quoted 8 lines
Quoted 3 lines
Fixing this should be trivial anyway, add the new IDs, pass the real IDs in, then add the translation table so you don't have to add any new entries to
bq27xxx_regs.That is *precisely* what I do in v13. Except I don't store real-ID in a di field because there isn't a use for it. Add that later if you need it.
The first two yes, but it's the type of translation that doesn't look good, we should go from lookup_table[realID]->whatever_values. With this we are mapping realID -> fakeID then later whatever_values_table[fakeID].
So if you barrow the "struct chip_lookup lookup_table" below then we end up with only two mapping types (table_lookup and values tables) and no translations needed.
Quoted 113 lines
bq27xxx_chips[] is the translation table. However we could unify that with the I2C table by placing two values in its
driver_datafield, and I think that's cleaner.Quoted 108 lines
Quoted 108 lines
So the only question is how to deliver the "real" ID to the driver. In v13, I change the I2C table to deliver real-ID, and replicate the mapping of the orig I2C table in bq27xxx_chips[]. Now I propose to make the I2C table carry two values, chip-ID and real-ID. Then we can drop bq27xxx_chips[].
Hope that clarifies the issue...
Quoted 100 lines
From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {...
Not sure if that is valid C but I think you can get the idea.
Quoted 85 lines
Quoted 85 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 184 lines · Andrew F. Davis
Quoted 174 lines · Liam Breck
Quoted 173 lines · Andrew F. Davis
Quoted 161 lines · Liam Breck
Quoted 152 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 149 lines · Andrew F. Davis
Quoted 135 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +5
-0@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 7 lines
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated.
Quoted 7 lines
Take a look at bq27xxx_i2c_id_table[] here:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/drivers/power/supply/bq27xxx_battery_i2c.c?h=linux-4.11.y#n148Notice how this table maps certain chips to the same IDs. I am going to preserve that scheme, as changing it is outside the scope of this series.
You can't just say doing something the right is "outside the scope of this series" then hack something together...
Quoted 8 lines
Quoted 3 lines
Fixing this should be trivial anyway, add the new IDs, pass the real IDs in, then add the translation table so you don't have to add any new entries to
bq27xxx_regs.That is *precisely* what I do in v13. Except I don't store real-ID in a di field because there isn't a use for it. Add that later if you need it.
Quoted 7 lines
The first two yes, but it's the type of translation that doesn't look good, we should go from lookup_table[realID]->whatever_values. With this we are mapping realID -> fakeID then later whatever_values_table[fakeID].
So if you barrow the "struct
chip_lookuplookup_table" below then we end up with only two mapping types (table_lookupand values tables) and no translations needed.
If we deliver two values in I2C driver_data, the lookup code will be this, and we don't need an extra table:
di->unseal_key = bq27xxx_unseal_keys[di->real_chip];
di->dm_regs = bq27xxx_dm_regs[di->real_chip];
di->regs = bq27xxx_regs[di->chip];Quoted 113 lines
Quoted 113 lines
bq27xxx_chips[] is the translation table. However we could unify that with the I2C table by placing two values in its
driver_datafield, and I think that's cleaner.Quoted 108 lines
Quoted 108 lines
So the only question is how to deliver the "real" ID to the driver. In v13, I change the I2C table to deliver real-ID, and replicate the mapping of the orig I2C table in bq27xxx_chips[]. Now I propose to make the I2C table carry two values, chip-ID and real-ID. Then we can drop bq27xxx_chips[].
Hope that clarifies the issue...
Quoted 100 lines
From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {...
Not sure if that is valid C but I think you can get the idea.
Quoted 85 lines
Quoted 85 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 189 lines · Liam Breck
Quoted 188 lines · Andrew F. Davis
Quoted 174 lines · Liam Breck
Quoted 173 lines · Andrew F. Davis
Quoted 161 lines · Liam Breck
Quoted 152 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 149 lines · Andrew F. Davis
Quoted 135 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +5
-0@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 7 lines
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated.
Quoted 7 lines
Take a look at bq27xxx_i2c_id_table[] here:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/drivers/power/supply/bq27xxx_battery_i2c.c?h=linux-4.11.y#n148Notice how this table maps certain chips to the same IDs. I am going to preserve that scheme, as changing it is outside the scope of this series.
You can't just say doing something the right is "outside the scope of this series" then hack something together...
Quoted 8 lines
Quoted 3 lines
Fixing this should be trivial anyway, add the new IDs, pass the real IDs in, then add the translation table so you don't have to add any new entries to
bq27xxx_regs.That is *precisely* what I do in v13. Except I don't store real-ID in a di field because there isn't a use for it. Add that later if you need it.
The first two yes, but it's the type of translation that doesn't look good, we should go from lookup_table[realID]->whatever_values. With this we are mapping realID -> fakeID then later whatever_values_table[fakeID].
Quoted 7 lines
Quoted 3 lines
So if you barrow the "struct
chip_lookuplookup_table" below then we end up with only two mapping types (table_lookupand values tables) and no translations needed.If we deliver two values in I2C
driver_data, the lookup code will be this, and we don't need an extra table:
Sure, but why should the I2C driver have to know anything about how the core works or what tables it does and does not have index IDs for? It should only pass in the real ID.
Quoted 119 lines
di->unseal_key = bq27xxx_unseal_keys[di->real_chip]; di->dm_regs = bq27xxx_dm_regs[di->real_chip]; di->regs = bq27xxx_regs[di->chip];Quoted 113 lines
Quoted 113 lines
bq27xxx_chips[] is the translation table. However we could unify that with the I2C table by placing two values in its
driver_datafield, and I think that's cleaner.Quoted 108 lines
Quoted 108 lines
So the only question is how to deliver the "real" ID to the driver. In v13, I change the I2C table to deliver real-ID, and replicate the mapping of the orig I2C table in bq27xxx_chips[]. Now I propose to make the I2C table carry two values, chip-ID and real-ID. Then we can drop bq27xxx_chips[].
Hope that clarifies the issue...
Quoted 100 lines
From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {...
Not sure if that is valid C but I think you can get the idea.
Quoted 85 lines
Quoted 85 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 194 lines · Andrew F. Davis
Quoted 193 lines · Liam Breck
Quoted 191 lines · Andrew F. Davis
Quoted 174 lines · Liam Breck
Quoted 173 lines · Andrew F. Davis
Quoted 161 lines · Liam Breck
Quoted 152 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 149 lines · Andrew F. Davis
Quoted 135 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 8 lines
drivers/power/supply/bq27xxx_battery.c +5
-0@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 7 lines
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated.
Quoted 7 lines
Take a look at bq27xxx_i2c_id_table[] here:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/drivers/power/supply/bq27xxx_battery_i2c.c?h=linux-4.11.y#n148Notice how this table maps certain chips to the same IDs. I am going to preserve that scheme, as changing it is outside the scope of this series.
You can't just say doing something the right is "outside the scope of this series" then hack something together...
Quoted 8 lines
Quoted 3 lines
Fixing this should be trivial anyway, add the new IDs, pass the real IDs in, then add the translation table so you don't have to add any new entries to
bq27xxx_regs.That is *precisely* what I do in v13. Except I don't store real-ID in a di field because there isn't a use for it. Add that later if you need it.
The first two yes, but it's the type of translation that doesn't look good, we should go from lookup_table[realID]->whatever_values. With this we are mapping realID -> fakeID then later whatever_values_table[fakeID].
So if you barrow the "struct
chip_lookuplookup_table" below then we end up with only two mapping types (table_lookupand values tables) and no translations needed.
Quoted 7 lines
Quoted 3 lines
If we deliver two values in I2C
driver_data, the lookup code will be this, and we don't need an extra table:Sure, but why should the I2C driver have to know anything about how the core works or what tables it does and does not have index IDs for? It should only pass in the real ID.
It's already mapping certain IDs to others. We need to leave that as is. Remember, IDs are not just table indexes, they also select behavior, so di->chip has to keep its current value.
It's easy to extend it to deliver a real-ID along with the orig value. That will simplify the patch.
Quoted 119 lines
Quoted 119 lines
di->unseal_key = bq27xxx_unseal_keys[di->real_chip]; di->dm_regs = bq27xxx_dm_regs[di->real_chip]; di->regs = bq27xxx_regs[di->chip];Quoted 113 lines
Quoted 113 lines
bq27xxx_chips[] is the translation table. However we could unify that with the I2C table by placing two values in its
driver_datafield, and I think that's cleaner.Quoted 108 lines
Quoted 108 lines
So the only question is how to deliver the "real" ID to the driver. In v13, I change the I2C table to deliver real-ID, and replicate the mapping of the orig I2C table in bq27xxx_chips[]. Now I propose to make the I2C table carry two values, chip-ID and real-ID. Then we can drop bq27xxx_chips[].
Hope that clarifies the issue...
Quoted 100 lines
From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {...
Not sure if that is valid C but I think you can get the idea.
Quoted 85 lines
Quoted 85 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
In reply to Andrew F. DavisQuoted 170 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 139 lines · Andrew F. Davis
Quoted 138 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, };Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+ di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated. From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {
Quoted 3 lines
...
Not sure if that is valid C but I think you can get the idea.
I considered a master lookup_table, but its ref to bq27xxx_regs[fake-ID] duplicates the mapping of real-ID to di->chip. The latter is still necessary as di->chip is used to select conditional behaviors; we can't change its value in this patch.
So instead lets amend the I2C table to carry both its original value (fake-ID) and the real-ID. That looks like:
static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
/* dest. di->real_chip di->chip */
{ "bq27200", (BQ27000 << 16) | BQ27000 },
{ "bq27210", (BQ27010 << 16) | BQ27010 },
...
{ "bq27441", (BQ27441 << 16) | BQ27421 },
{ "bq27621", (BQ27621 << 16) | BQ27421 },
{},
};In probe, retrieve two values:
di->real_chip = id->driver_data >> 16;
di->chip = (u16) id->driver_data;In setup, use two values:
di->unseal_key = bq27xxx_unseal_keys[di->real_chip];
di->dm_regs = bq27xxx_dm_regs[di->real_chip];
di->regs = bq27xxx_regs[di->chip]; // unchanged from orig srcThat yields the most compact implementation of this patch, and you get di->real_chip in the bargain :-)
Quoted 84 lines
Quoted 84 lines
Quoted 84 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Andrew F. Davis
NAKRe: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 173 lines · Liam Breck
Quoted 172 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 139 lines · Andrew F. Davis
Quoted 138 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, };Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+ di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated. From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {...
Quoted 7 lines
Quoted 1 line
Not sure if that is valid C but I think you can get the idea.
I considered a master
lookup_table, but its ref to bq27xxx_regs[fake-ID] duplicates the mapping of real-ID todi->chip. The latter is still necessary asdi->chipis used to select conditional behaviors; we can't change its value in this patch.
Sure we can, in fact you could add the conditional behavior flags to the master lookup_table and cleanup all the current switch-case checks we do now.
Quoted 13 lines
So instead lets amend the I2C table to carry both its original value (fake-ID) and the real-ID. That looks like:
static const struct i2c_device_id bq27xxx_i2c_id_table[] = { /* dest. di->real_chip di->chip */ { "bq27200", (BQ27000 << 16) | BQ27000 }, { "bq27210", (BQ27010 << 16) | BQ27010 }, ... { "bq27441", (BQ27441 << 16) | BQ27421 }, { "bq27621", (BQ27621 << 16) | BQ27421 }, {}, };
Quoted 5 lines
In probe, retrieve two values:
di->real_chip = id->driver_data >> 16; di->chip = (u16) id->driver_data;
NAK, I'm sure you can see how hacky this is right? This doesn't give us anything that the old table didn't. And it fails to correct the issue with the tables: We have two chip IDs still!
Try the lookup_table again, send be what you have and I can help get everything else working if you have any problems with the conditional behavior cleanups.
Quoted 94 lines
In setup, use two values:
di->unseal_key = bq27xxx_unseal_keys[di->real_chip]; di->dm_regs = bq27xxx_dm_regs[di->real_chip]; di->regs = bq27xxx_regs[di->chip]; // unchanged from orig srcThat yields the most compact implementation of this patch, and you get
di->real_chipin the bargain :-)Quoted 84 lines
Quoted 84 lines
Quoted 84 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Quoted 78 lines
drivers/power/supply/bq27xxx_battery.c +3
-1+ + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-0@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/**
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 182 lines · Andrew F. Davis
Quoted 173 lines · Liam Breck
Quoted 172 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 139 lines · Andrew F. Davis
Quoted 138 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, };Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+ di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated. From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {...
Quoted 7 lines
Quoted 1 line
Not sure if that is valid C but I think you can get the idea.
I considered a master
lookup_table, but its ref to bq27xxx_regs[fake-ID] duplicates the mapping of real-ID todi->chip. The latter is still necessary asdi->chipis used to select conditional behaviors; we can't change its value in this patch.
Quoted 3 lines
Sure we can, in fact you could add the conditional behavior flags to the master
lookup_tableand cleanup all the current switch-case checks we do now.
You are proposing a significant change to the ID handling, which is fine, but I don't wish to code that. Accept this minimal patch to enable DM update, and then alter the ID logic when you have time in a future patch.
Quoted 15 lines
Quoted 15 lines
So instead lets amend the I2C table to carry both its original value (fake-ID) and the real-ID. That looks like:
static const struct i2c_device_id bq27xxx_i2c_id_table[] = { /* dest. di->real_chip di->chip */ { "bq27200", (BQ27000 << 16) | BQ27000 }, { "bq27210", (BQ27010 << 16) | BQ27010 }, ... { "bq27441", (BQ27441 << 16) | BQ27421 }, { "bq27621", (BQ27621 << 16) | BQ27421 }, {}, };In probe, retrieve two values:
Quoted 7 lines
Quoted 3 lines
di->real_chip = id->driver_data >> 16; di->chip = (u16) id->driver_data;NAK, I'm sure you can see how hacky this is right? This doesn't give us anything that the old table didn't. And it fails to correct the issue with the tables: We have two chip IDs still!
I'm sorry you don't like the extra ID, but you're the party responsible for (if not the author of) the fake-ID scheme :-)
Quoted 20 lines
Try the
lookup_tableagain, send be what you have and I can help get everything else working if you have any problems with the conditional behavior cleanups.Quoted 16 lines
In setup, use two values:
di->unseal_key = bq27xxx_unseal_keys[di->real_chip]; di->dm_regs = bq27xxx_dm_regs[di->real_chip]; di->regs = bq27xxx_regs[di->chip]; // unchanged from orig srcThat yields the most compact implementation of this patch, and you get
di->real_chipin the bargain :-)Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 183 lines · Liam Breck
Quoted 182 lines · Andrew F. Davis
Quoted 180 lines · Liam Breck
Quoted 170 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 139 lines · Andrew F. Davis
Quoted 138 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, };Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+ di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated. From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {Quoted 3 lines
...
Not sure if that is valid C but I think you can get the idea.
I considered a master
lookup_table, but its ref to bq27xxx_regs[fake-ID] duplicates the mapping of real-ID todi->chip. The latter is still necessary asdi->chipis used to select conditional behaviors; we can't change its value in this patch.
Quoted 9 lines
Quoted 3 lines
Sure we can, in fact you could add the conditional behavior flags to the master
lookup_tableand cleanup all the current switch-case checks we do now.You are proposing a significant change to the ID handling, which is fine, but I don't wish to code that. Accept this minimal patch to enable DM update, and then alter the ID logic when you have time in a future patch.
Doesn't work like that, you can't just hack something together and hope someone else will fix it later. If you want to change something you should make it right the first time. We don't need DM update, but if you would like it then you need to fix the problems it will create.
Quoted 20 lines
Quoted 20 lines
Quoted 19 lines
So instead lets amend the I2C table to carry both its original value (fake-ID) and the real-ID. That looks like:
static const struct i2c_device_id bq27xxx_i2c_id_table[] = { /* dest. di->real_chip di->chip */ { "bq27200", (BQ27000 << 16) | BQ27000 }, { "bq27210", (BQ27010 << 16) | BQ27010 }, ... { "bq27441", (BQ27441 << 16) | BQ27421 }, { "bq27621", (BQ27621 << 16) | BQ27421 }, {}, };In probe, retrieve two values:
di->real_chip = id->driver_data >> 16; di->chip = (u16) id->driver_data;
Quoted 7 lines
Quoted 3 lines
NAK, I'm sure you can see how hacky this is right? This doesn't give us anything that the old table didn't. And it fails to correct the issue with the tables: We have two chip IDs still!
I'm sorry you don't like the extra ID, but you're the party responsible for (if not the author of) the fake-ID scheme :-)
It has worked fine until now, your additions require a different scheme, hacking around the old one is not a workable solution.
Quoted 21 lines
Quoted 21 lines
Try the
lookup_tableagain, send be what you have and I can help get everything else working if you have any problems with the conditional behavior cleanups.Quoted 16 lines
In setup, use two values:
di->unseal_key = bq27xxx_unseal_keys[di->real_chip]; di->dm_regs = bq27xxx_dm_regs[di->real_chip]; di->regs = bq27xxx_regs[di->chip]; // unchanged from orig srcThat yields the most compact implementation of this patch, and you get
di->real_chipin the bargain :-)Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 194 lines · Andrew F. Davis
Quoted 183 lines · Liam Breck
Quoted 182 lines · Andrew F. Davis
Quoted 180 lines · Liam Breck
Quoted 170 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 139 lines · Andrew F. Davis
Quoted 138 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, };Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+ di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated. From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {Quoted 3 lines
...
Not sure if that is valid C but I think you can get the idea.
I considered a master
lookup_table, but its ref to bq27xxx_regs[fake-ID] duplicates the mapping of real-ID todi->chip. The latter is still necessary asdi->chipis used to select conditional behaviors; we can't change its value in this patch.Quoted 9 lines
Quoted 3 lines
Sure we can, in fact you could add the conditional behavior flags to the master
lookup_tableand cleanup all the current switch-case checks we do now.You are proposing a significant change to the ID handling, which is fine, but I don't wish to code that. Accept this minimal patch to enable DM update, and then alter the ID logic when you have time in a future patch.
Quoted 4 lines
Doesn't work like that, you can't just hack something together and hope someone else will fix it later. If you want to change something you should make it right the first time. We don't need DM update, but if you would like it then you need to fix the problems it will create.
You do indeed need DM update for the RAM-only chips; they expect to be configured on boot, as I documented previously.
Adding real-ID to the I2C table and using it in *exactly two lines* of setup() is a minimal workaround for a pre-existing design flaw. You have a concept for fixing it, so you should code it. I gracefully decline.
I have labored on this patchset for some 19 revisions. Sebastian seems to think that's enough, as he queued most of the series last week even tho you hadn't acked it.
Quoted 51 lines
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
So instead lets amend the I2C table to carry both its original value (fake-ID) and the real-ID. That looks like:
static const struct i2c_device_id bq27xxx_i2c_id_table[] = { /* dest. di->real_chip di->chip */ { "bq27200", (BQ27000 << 16) | BQ27000 }, { "bq27210", (BQ27010 << 16) | BQ27010 }, ... { "bq27441", (BQ27441 << 16) | BQ27421 }, { "bq27621", (BQ27621 << 16) | BQ27421 }, {}, };In probe, retrieve two values:
di->real_chip = id->driver_data >> 16; di->chip = (u16) id->driver_data;Quoted 7 lines
Quoted 3 lines
NAK, I'm sure you can see how hacky this is right? This doesn't give us anything that the old table didn't. And it fails to correct the issue with the tables: We have two chip IDs still!
I'm sorry you don't like the extra ID, but you're the party responsible for (if not the author of) the fake-ID scheme :-)
It has worked fine until now, your additions require a different scheme, hacking around the old one is not a workable solution.
Quoted 21 lines
Quoted 21 lines
Try the
lookup_tableagain, send be what you have and I can help get everything else working if you have any problems with the conditional behavior cleanups.Quoted 16 lines
In setup, use two values:
di->unseal_key = bq27xxx_unseal_keys[di->real_chip]; di->dm_regs = bq27xxx_dm_regs[di->real_chip]; di->regs = bq27xxx_regs[di->chip]; // unchanged from orig srcThat yields the most compact implementation of this patch, and you get
di->real_chipin the bargain :-)Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
Quoted 200 lines · Liam Breck
Quoted 194 lines · Andrew F. Davis
Quoted 183 lines · Liam Breck
Quoted 182 lines · Andrew F. Davis
Quoted 180 lines · Liam Breck
Quoted 170 lines · Andrew F. Davis
Quoted 151 lines · Liam Breck
Quoted 139 lines · Andrew F. Davis
Quoted 138 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +78
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [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 struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; + +static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, };Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c int bq27xxx_battery_setup(struct bq27xxx_device_info *di) · line 1947
Quoted 5 lines
drivers/power/supply/bq27xxx_battery.c +5
-0+ di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip];NACK, this is a mess, you should not be using a table to change what chip was passed in, it may be needed later. The chip is still the same, it should have the same one correct ID, use a different index or array if you would like, but this is very hacky.
Quoted 4 lines
The only way I see to make the I2C subsystem deliver multiple IDs for a device is to treat i2c_device_id.driver_data as a u16[2] instead of its normal u32. What do you think of that?
Why would it need multiple IDs for one device? Just pass in the one correct device ID that it is. No reason to make this so complicated. From the one ID you can then use tables to lookup any other info about that device, you don't have to have ever ID populated in every table, you can even have a table of tables if you would like:
static const struct chip_lookup lookup_table = { [bq27425] = { .regs = &bq27xxx_regs[bq27425], .dm_regs = &bq27xxx_dm_regs[bq274xx], .unseal_key = INVALID_FOR_THIS_DEVICE, }, [bq27343] = {Quoted 3 lines
...
Not sure if that is valid C but I think you can get the idea.
I considered a master
lookup_table, but its ref to bq27xxx_regs[fake-ID] duplicates the mapping of real-ID todi->chip. The latter is still necessary asdi->chipis used to select conditional behaviors; we can't change its value in this patch.Quoted 9 lines
Quoted 3 lines
Sure we can, in fact you could add the conditional behavior flags to the master
lookup_tableand cleanup all the current switch-case checks we do now.You are proposing a significant change to the ID handling, which is fine, but I don't wish to code that. Accept this minimal patch to enable DM update, and then alter the ID logic when you have time in a future patch.
Quoted 4 lines
Doesn't work like that, you can't just hack something together and hope someone else will fix it later. If you want to change something you should make it right the first time. We don't need DM update, but if you would like it then you need to fix the problems it will create.
Quoted 8 lines
You do indeed need DM update for the RAM-only chips; they expect to be configured on boot, as I documented previously.
Adding real-ID to the I2C table and using it in *exactly two lines* of
setup()is a minimal workaround for a pre-existing design flaw. You have a concept for fixing it, so you should code it. I gracefully decline.
Just because it was done wrong before doesn't mean it should continue to be done wrong.
Quoted 4 lines
I have labored on this patchset for some 19 revisions. Sebastian seems to think that's enough, as he queued most of the series last week even tho you hadn't acked it.
I know you said v1 came out in Jan, but I've only been looking at this for one cycle, also you wouldn't be at v19 if you didn't push 2 series a week, let each version sit on the list for a while to build up multiple comments. Patch series version number is not a metric of quality or "readiness".
+ queuing patches is not approval, it just sets it up for testing in -next, nothing is final until Linus takes the pull request, and even then there is always revert patches.
I've offered to work with you on this, if you would stop fighting every minor suggestion I give we could get all this in this cycle.
I empathize with you, this is a very difficult driver with a lot of legacy attached and more by-name supported devices than almost any other driver I've seen, we have to get this right or it will negatively effect a lot of people down the road.
Quoted 53 lines
Quoted 53 lines
Quoted 21 lines
Quoted 21 lines
Quoted 20 lines
So instead lets amend the I2C table to carry both its original value (fake-ID) and the real-ID. That looks like:
static const struct i2c_device_id bq27xxx_i2c_id_table[] = { /* dest. di->real_chip di->chip */ { "bq27200", (BQ27000 << 16) | BQ27000 }, { "bq27210", (BQ27010 << 16) | BQ27010 }, ... { "bq27441", (BQ27441 << 16) | BQ27421 }, { "bq27621", (BQ27621 << 16) | BQ27421 }, {}, };In probe, retrieve two values:
di->real_chip = id->driver_data >> 16; di->chip = (u16) id->driver_data;Quoted 7 lines
Quoted 3 lines
NAK, I'm sure you can see how hacky this is right? This doesn't give us anything that the old table didn't. And it fails to correct the issue with the tables: We have two chip IDs still!
I'm sorry you don't like the extra ID, but you're the party responsible for (if not the author of) the fake-ID scheme :-)
It has worked fine until now, your additions require a different scheme, hacking around the old one is not a workable solution.
Quoted 21 lines
Quoted 21 lines
Try the
lookup_tableagain, send be what you have and I can help get everything else working if you have any problems with the conditional behavior cleanups.Quoted 16 lines
In setup, use two values:
di->unseal_key = bq27xxx_unseal_keys[di->real_chip]; di->dm_regs = bq27xxx_dm_regs[di->real_chip]; di->regs = bq27xxx_regs[di->chip]; // unchanged from orig srcThat yields the most compact implementation of this patch, and you get
di->real_chipin the bargain :-)Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Just stop trying to hack around it, add the extra tables, even if they are clones, so we can be done with this series already. I'm sure you want that more than you want this "clever" work-around, right?
Also fix all the checkpatch --strict warnings.
Re: [PATCH v13 09/11] power: supply: bq27xxx_battery: Enable data memory update for certain chips
In reply to Liam BreckHi Andrew,
Quoted 3 lines · Liam Breck
From: Liam Breck <[email protected]>
Support data memory update on BQ27500, 545, 425, 421, 441, 621.
Re testing, I'll comment out code in this patch for chips I can't test. We can let future users test chips they use and re-enable/insert them. No need to make you test everything.
Quoted 76 lines
Create IDs for for previously unID'd chips, to index arrays for unseal keys and data memory register tables.
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 90 ++++++++++++++++++++++++++++-- drivers/power/supply/bq27xxx_battery_i2c.c | 16 +++--- include/linux/power/bq27xxx_battery.h | 13 +++++ 3 files changed, 107 insertions(+), 12 deletions(-)drivers/power/supply/bq27xxx_battery.c +30
-3@@ -58,7 +58,7 @@#include <linux/power/bq27xxx_battery.h> -#define DRIVER_VERSION "1.2.0" +#define DRIVER_VERSION "1.3.0"#define BQ27XXX_MANUFACTURER "Texas Instruments"@@ -132,7 +132,7 @@ enum bq27xxx_reg_index { [BQ27XXX_DM_CKSUM] = 0x60 /* Register mappings */ -static u8 bq27xxx_regs[][BQ27XXX_REG_MAX ] = { +static u8 bq27xxx_regs[BQ27MAX ][BQ27XXX_REG_MAX ] = { [BQ27000 ] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,@@ -779,7 +779,7 @@ static enum power_supply_property bq27421_battery_props[] = {static struct {enum power_supply_property *props;size_t size; -} bq27xxx_battery_props[] = { +} bq27xxx_battery_props[BQ27MAX ] = {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props),@@ -798,6 +798,33 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static enum bq27xxx_chip bq27xxx_chips[] = { + [BQ27000 ] =BQ27000 , + [BQ27010 ] =BQ27010 , + [BQ2750X ] =BQ2750X , + [BQ2751X ] =BQ2751X , + [BQ2752X ] =BQ2751X , + [BQ27500 ] =BQ27500 , + [BQ27510G1 ] =BQ27510G1 , + [BQ27510G2 ] =BQ27510G2 , + [BQ27510G3 ] =BQ27510G3 , + [BQ27520G1 ] =BQ27520G1 , + [BQ27520G2 ] =BQ27520G2 , + [BQ27520G3 ] =BQ27520G3 , + [BQ27520G4 ] =BQ27520G4 , + [BQ27530 ] =BQ27530 , + [BQ27531 ] =BQ27530 , + [BQ27541 ] =BQ27541 , + [BQ27542 ] =BQ27541 , + [BQ27546 ] =BQ27541 , + [BQ27742 ] =BQ27541 , + [BQ27545 ] =BQ27545 , + [BQ27421 ] =BQ27421 , + [BQ27425 ] =BQ27421 , + [BQ27441 ] =BQ27421 , + [BQ27621 ] =BQ27421 , +}; +static DEFINE_MUTEX (bq27xxx_list_lock);static LIST_HEAD (bq27xxx_battery_devices);
drivers/power/supply/bq27xxx_battery.c static const char * const bq27xxx_dm_reg_name[] = { · line 884
Quoted 2 lines
drivers/power/supply/bq27xxx_battery.c +0
-0@@ -856,6 +883,54 @@ static const char * const bq27xxx_dm_reg_name[] = { [BQ27XXX_DM_TERMINATE_VOLTAGE] = "terminate-voltage", };
Specifically...
#ifdef DEBUG here
Quoted 19 lines
drivers/power/supply/bq27xxx_battery.c +19
-0+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[] = {
drivers/power/supply/bq27xxx_battery.c static const char * const bq27xxx_dm_reg_name[] = { · line 914
Quoted 10 lines
drivers/power/supply/bq27xxx_battery.c +10
-0+ [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 }, +};
#endif here, moving one table outside the ifdef.
drivers/power/supply/bq27xxx_battery.c static const char * const bq27xxx_dm_reg_name[] = { · line 924
Quoted 9 lines
drivers/power/supply/bq27xxx_battery.c +9
-0+static struct bq27xxx_dm_reg *bq27xxx_dm_regs[] = { + [BQ27500 ] = bq27500_dm_regs, + [BQ27545 ] = bq27545_dm_regs, + [BQ27421 ] = bq27421_dm_regs, + [BQ27425 ] = bq27425_dm_regs, + [BQ27441 ] = bq27421_dm_regs, + [BQ27621 ] = bq27621_dm_regs, +}; +
And the same inside the above table.
Quoted 101 lines
drivers/power/supply/bq27xxx_battery.c +17
-1+static u32 bq27xxx_unseal_keys[] = { + [BQ27500 ] =0x04143672 , + [BQ27545 ] =0x04143672 , + [BQ27421 ] =0x80008000 , + [BQ27425 ] =0x04143672 , + [BQ27441 ] =0x80008000 , + [BQ27621 ] =0x80008000 , +}; +#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM static bool bq27xxx_dt_to_nvm = true;@@ -1865,9 +1940,16 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; + + di->unseal_key = bq27xxx_unseal_keys[di->chip]; + di->dm_regs = bq27xxx_dm_regs[di->chip]; + di->chip = bq27xxx_chips[di->chip]; + + di->regs = bq27xxx_regs[di->chip]; +INIT_DELAYED_WORK (&di->work, bq27xxx_battery_poll);mutex_init (&di->lock); - di->regs = bq27xxx_regs[di->chip]; psy_desc =devm_kzalloc (di->dev,sizeof (*psy_desc),GFP_KERNEL );if (!psy_desc)drivers/power/supply/bq27xxx_battery_i2c.c +8
-8@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27210", BQ27010 }, { "bq27500", BQ2750X }, { "bq27510", BQ2751X }, - { "bq27520", BQ2751X }, + { "bq27520", BQ2752X }, { "bq27500-1", BQ27500 }, { "bq27510g1", BQ27510G1 }, { "bq27510g2", BQ27510G2 },@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { { "bq27520g3", BQ27520G3 }, { "bq27520g4", BQ27520G4 }, { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, + { "bq27531", BQ27531 }, { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, + { "bq27542", BQ27542 }, + { "bq27546", BQ27546 }, + { "bq27742", BQ27742 }, { "bq27545", BQ27545 }, { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, + { "bq27425", BQ27425 }, + { "bq27441", BQ27441 }, + { "bq27621", BQ27621 }, {}, };MODULE_DEVICE_TABLE (i2c, bq27xxx_i2c_id_table);include/linux/power/bq27xxx_battery.h +13
-1@@ -2,6 +2,8 @@#define __LINUX_BQ27X00_BATTERY_H__enum bq27xxx_chip { +/* these index bq27xxx_regs[] & bq27xxx_battery_props[] */ +/* and map to themselves in bq27xxx_chips[] */ BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ @@ -18,6 +20,17 @@ enum bq27xxx_chip {BQ27541 ,/* bq27541, bq27542, bq27546, bq27742 */ BQ27545 ,/* bq27545 */ BQ27421 ,/* bq27421, bq27425, bq27441, bq27621 */ +BQ27MAX , + +/* these map to above in bq27xxx_chips[] */ +BQ2752X ,/* deprecated alias */ +BQ27531 , +BQ27542 , +BQ27546 , +BQ27742 , +BQ27425 , +BQ27441 , + BQ27621, };/** -- 2.9.3
PATCH v13 10/11 power: supply: bq27xxx_battery: Flag identical register maps when in debug mode
In reply to Liam BreckFrom: Liam Breck <[email protected]>
We tie multiple chips to unique register maps. When supporting a new chip, it's easy to add a duplicate map by mistake.
In debug mode we now scan the register maps for duplicates.
--- drivers/power/supply/bq27xxx_battery.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
drivers/power/supply/bq27xxx_battery.c +21 -0
@@ -1932,6 +1932,25 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)schedule_delayed_work (&di->work,0 ); } +#ifdef DEBUG +static void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) +{ +const size_t max =ARRAY_SIZE (bq27xxx_regs); +int a, b; + +for (a =1 ; a < max-1 ; a++) { +for (b = a+1 ; b < max; b++) { +if (!memcmp (bq27xxx_regs[a], bq27xxx_regs[b], +sizeof (bq27xxx_regs[0 ]))) +dev_warn (di->dev, +"bq27xxx_regs[%d] & [%d] are identical\n" , a, b); + } + } +} +#else +static inline void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) {} +#endif +int bq27xxx_battery_setup (struct bq27xxx_device_info *di) {struct power_supply_desc *psy_desc;
@@ -1940,6 +1959,8 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; +bq27xxx_battery_dbg_regs_dupes (di); + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; di->unseal_key = bq27xxx_unseal_keys[di->chip];
Signature · 1 line
2.9.3
Re: [PATCH v13 10/11] power: supply: bq27xxx_battery: Flag identical register maps when in debug mode
Quoted 7 lines · Liam Breck
From: Liam Breck <[email protected]>
We tie multiple chips to unique register maps. When supporting a new chip, it's easy to add a duplicate map by mistake.
In debug mode we now scan the register maps for duplicates.
Debugging stuff doesn't need to go upstream.
Quoted 45 lines
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)drivers/power/supply/bq27xxx_battery.c +21
-0@@ -1932,6 +1932,25 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)schedule_delayed_work (&di->work,0 ); } +#ifdef DEBUG +static void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) +{ +const size_t max =ARRAY_SIZE (bq27xxx_regs); +int a, b; + +for (a =1 ; a < max-1 ; a++) { +for (b = a+1 ; b < max; b++) { +if (!memcmp (bq27xxx_regs[a], bq27xxx_regs[b], +sizeof (bq27xxx_regs[0 ]))) +dev_warn (di->dev, +"bq27xxx_regs[%d] & [%d] are identical\n" , a, b); + } + } +} +#else +static inline void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) {} +#endif +int bq27xxx_battery_setup (struct bq27xxx_device_info *di) {struct power_supply_desc *psy_desc;@@ -1940,6 +1959,8 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; +bq27xxx_battery_dbg_regs_dupes (di); + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; di->unseal_key = bq27xxx_unseal_keys[di->chip];
Re: [PATCH v13 10/11] power: supply: bq27xxx_battery: Flag identical register maps when in debug mode
Quoted 10 lines · Andrew F. Davis
Quoted 7 lines · Liam Breck
From: Liam Breck <[email protected]>
We tie multiple chips to unique register maps. When supporting a new chip, it's easy to add a duplicate map by mistake.
In debug mode we now scan the register maps for duplicates.
Debugging stuff doesn't need to go upstream.
Since we're keeping a dupeless reg table, please ack this so folks adding chips avoid adding dupes as Chris did.
I don't have to mention there's tons of debug code upstream :-)
Quoted 45 lines
Quoted 45 lines
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)drivers/power/supply/bq27xxx_battery.c +21
-0@@ -1932,6 +1932,25 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)schedule_delayed_work (&di->work,0 ); } +#ifdef DEBUG +static void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) +{ +const size_t max =ARRAY_SIZE (bq27xxx_regs); +int a, b; + +for (a =1 ; a < max-1 ; a++) { +for (b = a+1 ; b < max; b++) { +if (!memcmp (bq27xxx_regs[a], bq27xxx_regs[b], +sizeof (bq27xxx_regs[0 ]))) +dev_warn (di->dev, +"bq27xxx_regs[%d] & [%d] are identical\n" , a, b); + } + } +} +#else +static inline void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) {} +#endif +int bq27xxx_battery_setup (struct bq27xxx_device_info *di) {struct power_supply_desc *psy_desc;@@ -1940,6 +1959,8 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; +bq27xxx_battery_dbg_regs_dupes (di); + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; di->unseal_key = bq27xxx_unseal_keys[di->chip];
Re: [PATCH v13 10/11] power: supply: bq27xxx_battery: Flag identical register maps when in debug mode
Quoted 10 lines · Liam Breck
Quoted 9 lines · Andrew F. Davis
Quoted 7 lines · Liam Breck
From: Liam Breck <[email protected]>
We tie multiple chips to unique register maps. When supporting a new chip, it's easy to add a duplicate map by mistake.
In debug mode we now scan the register maps for duplicates.
Quoted 7 lines
Quoted 1 line
Debugging stuff doesn't need to go upstream.
Since we're keeping a dupeless reg table, please ack this so folks adding chips avoid adding dupes as Chris did.
I don't have to mention there's tons of debug code upstream :-)
If you want it then make it into a tool that can go into scripts/ or tools/, it doesn't need to be inline cluttering up the source.
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)drivers/power/supply/bq27xxx_battery.c +21
-0@@ -1932,6 +1932,25 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)schedule_delayed_work (&di->work,0 ); } +#ifdef DEBUG +static void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) +{ +const size_t max =ARRAY_SIZE (bq27xxx_regs); +int a, b; + +for (a =1 ; a < max-1 ; a++) { +for (b = a+1 ; b < max; b++) { +if (!memcmp (bq27xxx_regs[a], bq27xxx_regs[b], +sizeof (bq27xxx_regs[0 ]))) +dev_warn (di->dev, +"bq27xxx_regs[%d] & [%d] are identical\n" , a, b); + } + } +} +#else +static inline void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) {} +#endif +int bq27xxx_battery_setup (struct bq27xxx_device_info *di) {struct power_supply_desc *psy_desc;@@ -1940,6 +1959,8 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; +bq27xxx_battery_dbg_regs_dupes (di); + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; di->unseal_key = bq27xxx_unseal_keys[di->chip];
Re: [PATCH v13 10/11] power: supply: bq27xxx_battery: Flag identical register maps when in debug mode
Quoted 13 lines · Andrew F. Davis
Quoted 12 lines · Liam Breck
Quoted 10 lines · Andrew F. Davis
Quoted 7 lines · Liam Breck
From: Liam Breck <[email protected]>
We tie multiple chips to unique register maps. When supporting a new chip, it's easy to add a duplicate map by mistake.
In debug mode we now scan the register maps for duplicates.
Debugging stuff doesn't need to go upstream.
Quoted 8 lines
Quoted 5 lines
Since we're keeping a dupeless reg table, please ack this so folks adding chips avoid adding dupes as Chris did.
I don't have to mention there's tons of debug code upstream :-)
If you want it then make it into a tool that can go into
scripts/ortools/, it doesn't need to be inline cluttering up the source.
This code needs to read module static data. How would it work in an external file?
Quoted 45 lines
Quoted 45 lines
Quoted 45 lines
Quoted 45 lines
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)drivers/power/supply/bq27xxx_battery.c +21
-0@@ -1932,6 +1932,25 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)schedule_delayed_work (&di->work,0 ); } +#ifdef DEBUG +static void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) +{ +const size_t max =ARRAY_SIZE (bq27xxx_regs); +int a, b; + +for (a =1 ; a < max-1 ; a++) { +for (b = a+1 ; b < max; b++) { +if (!memcmp (bq27xxx_regs[a], bq27xxx_regs[b], +sizeof (bq27xxx_regs[0 ]))) +dev_warn (di->dev, +"bq27xxx_regs[%d] & [%d] are identical\n" , a, b); + } + } +} +#else +static inline void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) {} +#endif +int bq27xxx_battery_setup (struct bq27xxx_device_info *di) {struct power_supply_desc *psy_desc;@@ -1940,6 +1959,8 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; +bq27xxx_battery_dbg_regs_dupes (di); + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; di->unseal_key = bq27xxx_unseal_keys[di->chip];
Re: [PATCH v13 10/11] power: supply: bq27xxx_battery: Flag identical register maps when in debug mode
Quoted 17 lines · Liam Breck
Quoted 16 lines · Andrew F. Davis
Quoted 15 lines · Liam Breck
Quoted 10 lines · Andrew F. Davis
Quoted 7 lines · Liam Breck
From: Liam Breck <[email protected]>
We tie multiple chips to unique register maps. When supporting a new chip, it's easy to add a duplicate map by mistake.
In debug mode we now scan the register maps for duplicates.
Debugging stuff doesn't need to go upstream.
Since we're keeping a dupeless reg table, please ack this so folks adding chips avoid adding dupes as Chris did.
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
I don't have to mention there's tons of debug code upstream :-)
If you want it then make it into a tool that can go into
scripts/ortools/, it doesn't need to be inline cluttering up the source.This code needs to read module static data. How would it work in an external file?
If you are creating an external checking tool it can just ignore 'static' scope definitions when it is parsing this file.
Quoted 47 lines
Quoted 47 lines
Quoted 47 lines
Quoted 47 lines
Quoted 47 lines
Signed-off-by Liam Breck <[email protected]>--- drivers/power/supply/bq27xxx_battery.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)drivers/power/supply/bq27xxx_battery.c +21
-0@@ -1932,6 +1932,25 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)schedule_delayed_work (&di->work,0 ); } +#ifdef DEBUG +static void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) +{ +const size_t max =ARRAY_SIZE (bq27xxx_regs); +int a, b; + +for (a =1 ; a < max-1 ; a++) { +for (b = a+1 ; b < max; b++) { +if (!memcmp (bq27xxx_regs[a], bq27xxx_regs[b], +sizeof (bq27xxx_regs[0 ]))) +dev_warn (di->dev, +"bq27xxx_regs[%d] & [%d] are identical\n" , a, b); + } + } +} +#else +static inline void bq27xxx_battery_dbg_regs_dupes (struct bq27xxx_device_info *di) {} +#endif +int bq27xxx_battery_setup (struct bq27xxx_device_info *di) {struct power_supply_desc *psy_desc;@@ -1940,6 +1959,8 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) .drv_data = di, }; +bq27xxx_battery_dbg_regs_dupes (di); + di->ram_chip = di->chip ==BQ27421 || di->chip ==BQ27441 || di->chip ==BQ27621 ; di->unseal_key = bq27xxx_unseal_keys[di->chip];
Re: [PATCH v13 10/11] power: supply: bq27xxx_battery: Flag identical register maps when in debug mode
Quoted 24 lines · Andrew F. Davis
Quoted 23 lines · Liam Breck
Quoted 21 lines · Andrew F. Davis
Quoted 10 lines · Liam Breck
Quoted 9 lines · Andrew F. Davis
Quoted 7 lines · Liam Breck
From: Liam Breck <[email protected]>
We tie multiple chips to unique register maps. When supporting a new chip, it's easy to add a duplicate map by mistake.
In debug mode we now scan the register maps for duplicates.
Quoted 7 lines
Quoted 1 line
Debugging stuff doesn't need to go upstream.
Since we're keeping a dupeless reg table, please ack this so folks adding chips avoid adding dupes as Chris did.
I don't have to mention there's tons of debug code upstream :-)
If you want it then make it into a tool that can go into
scripts/ortools/, it doesn't need to be inline cluttering up the source.
Quoted 6 lines
Quoted 3 lines
This code needs to read module static data. How would it work in an external file?
If you are creating an external checking tool it can just ignore 'static' scope definitions when it is parsing this file.
Can you point to an example?
Is it a program with #include .../bq27xxx_battery.c and a main() that runs the dupe check? I won't parse the file since the compiler does that so remarkably well.
PATCH v13 11/11 power: supply: bq27xxx_battery: Remove duplicate register arrays
In reply to Liam BreckFrom: Liam Breck <[email protected]>
BQ2751X & BQ27510G3 are identical. BQ27500 & BQ27510G1 & BQ27510G2 are identical. Make BQ2751X & BQ27510G1/2 aliases. Remove the duplicate arrays, etc.
--- drivers/power/supply/bq27xxx_battery.c | 134 +-------------------------------- include/linux/power/bq27xxx_battery.h | 12 +-- 2 files changed, 10 insertions(+), 136 deletions(-)
drivers/power/supply/bq27xxx_battery.c +4 -130
@@ -201,26 +201,6 @@ static u8 bq27xxx_regs[BQ27MAX][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_AP ] =INVALID_REG_ADDR ,BQ27XXX_DM_REG_ROWS , }, - [BQ2751X] = { - [BQ27XXX_REG_CTRL ] =0x00 , - [BQ27XXX_REG_TEMP ] =0x06 , - [BQ27XXX_REG_INT_TEMP ] =0x28 , - [BQ27XXX_REG_VOLT ] =0x08 , - [BQ27XXX_REG_AI ] =0x14 , - [BQ27XXX_REG_FLAGS ] =0x0a , - [BQ27XXX_REG_TTE ] =0x16 , - [BQ27XXX_REG_TTF ] =INVALID_REG_ADDR , - [BQ27XXX_REG_TTES ] =0x1a , - [BQ27XXX_REG_TTECP ] =INVALID_REG_ADDR , - [BQ27XXX_REG_NAC ] =0x0c , - [BQ27XXX_REG_FCC ] =0x12 , - [BQ27XXX_REG_CYCT ] =0x1e , - [BQ27XXX_REG_AE ] =INVALID_REG_ADDR , - [BQ27XXX_REG_SOC ] =0x20 , - [BQ27XXX_REG_DCAP ] =0x2e , - [BQ27XXX_REG_AP ] =INVALID_REG_ADDR , -BQ27XXX_DM_REG_ROWS , - }, [BQ27500] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,
@@ -241,46 +221,6 @@ static u8 bq27xxx_regs[BQ27MAX][BQ27XXX_REG_MAX] = { [BQ27XXX_REG_AP ] =0x24 ,BQ27XXX_DM_REG_ROWS , }, - [BQ27510G1] = { - [BQ27XXX_REG_CTRL ] =0x00 , - [BQ27XXX_REG_TEMP ] =0x06 , - [BQ27XXX_REG_INT_TEMP ] =INVALID_REG_ADDR , - [BQ27XXX_REG_VOLT ] =0x08 , - [BQ27XXX_REG_AI ] =0x14 , - [BQ27XXX_REG_FLAGS ] =0x0a , - [BQ27XXX_REG_TTE ] =0x16 , - [BQ27XXX_REG_TTF ] =0x18 , - [BQ27XXX_REG_TTES ] =0x1c , - [BQ27XXX_REG_TTECP ] =0x26 , - [BQ27XXX_REG_NAC ] =0x0c , - [BQ27XXX_REG_FCC ] =0x12 , - [BQ27XXX_REG_CYCT ] =0x2a , - [BQ27XXX_REG_AE ] =0x22 , - [BQ27XXX_REG_SOC ] =0x2c , - [BQ27XXX_REG_DCAP ] =0x3c , - [BQ27XXX_REG_AP ] =0x24 , -BQ27XXX_DM_REG_ROWS , - }, - [BQ27510G2 ] = { - [BQ27XXX_REG_CTRL ] =0x00 , - [BQ27XXX_REG_TEMP ] =0x06 , - [BQ27XXX_REG_INT_TEMP ] =INVALID_REG_ADDR , - [BQ27XXX_REG_VOLT ] =0x08 , - [BQ27XXX_REG_AI ] =0x14 , - [BQ27XXX_REG_FLAGS ] =0x0a , - [BQ27XXX_REG_TTE ] =0x16 , - [BQ27XXX_REG_TTF ] =0x18 , - [BQ27XXX_REG_TTES ] =0x1c , - [BQ27XXX_REG_TTECP ] =0x26 , - [BQ27XXX_REG_NAC ] =0x0c , - [BQ27XXX_REG_FCC ] =0x12 , - [BQ27XXX_REG_CYCT ] =0x2a , - [BQ27XXX_REG_AE ] =0x22 , - [BQ27XXX_REG_SOC ] =0x2c , - [BQ27XXX_REG_DCAP ] =0x3c , - [BQ27XXX_REG_AP ] =0x24 , -BQ27XXX_DM_REG_ROWS , - }, [BQ27510G3] = { [BQ27XXX_REG_CTRL ] =0x00 , [BQ27XXX_REG_TEMP ] =0x06 ,
@@ -523,24 +463,6 @@ static enum power_supply_property bq2750x_battery_props[] = { POWER_SUPPLY_PROP_MANUFACTURER, }; -static enum power_supply_property bq2751x_battery_props[] = { -POWER_SUPPLY_PROP_STATUS , -POWER_SUPPLY_PROP_PRESENT , -POWER_SUPPLY_PROP_VOLTAGE_NOW , -POWER_SUPPLY_PROP_CURRENT_NOW , -POWER_SUPPLY_PROP_CAPACITY , -POWER_SUPPLY_PROP_CAPACITY_LEVEL , -POWER_SUPPLY_PROP_TEMP , -POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW , -POWER_SUPPLY_PROP_TECHNOLOGY , -POWER_SUPPLY_PROP_CHARGE_FULL , -POWER_SUPPLY_PROP_CHARGE_NOW , -POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN , -POWER_SUPPLY_PROP_CYCLE_COUNT , -POWER_SUPPLY_PROP_HEALTH , -POWER_SUPPLY_PROP_MANUFACTURER , -}; -static enum power_supply_property bq27500_battery_props[] = {POWER_SUPPLY_PROP_STATUS ,POWER_SUPPLY_PROP_PRESENT ,
@@ -562,48 +484,6 @@ static enum power_supply_property bq27500_battery_props[] = { POWER_SUPPLY_PROP_MANUFACTURER, }; -static enum power_supply_property bq27510g1_battery_props[] = { -POWER_SUPPLY_PROP_STATUS , -POWER_SUPPLY_PROP_PRESENT , -POWER_SUPPLY_PROP_VOLTAGE_NOW , -POWER_SUPPLY_PROP_CURRENT_NOW , -POWER_SUPPLY_PROP_CAPACITY , -POWER_SUPPLY_PROP_CAPACITY_LEVEL , -POWER_SUPPLY_PROP_TEMP , -POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW , -POWER_SUPPLY_PROP_TIME_TO_FULL_NOW , -POWER_SUPPLY_PROP_TECHNOLOGY , -POWER_SUPPLY_PROP_CHARGE_FULL , -POWER_SUPPLY_PROP_CHARGE_NOW , -POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN , -POWER_SUPPLY_PROP_CYCLE_COUNT , -POWER_SUPPLY_PROP_ENERGY_NOW , -POWER_SUPPLY_PROP_POWER_AVG , -POWER_SUPPLY_PROP_HEALTH , -POWER_SUPPLY_PROP_MANUFACTURER , -}; - -static enum power_supply_property bq27510g2_battery_props[] = { -POWER_SUPPLY_PROP_STATUS , -POWER_SUPPLY_PROP_PRESENT , -POWER_SUPPLY_PROP_VOLTAGE_NOW , -POWER_SUPPLY_PROP_CURRENT_NOW , -POWER_SUPPLY_PROP_CAPACITY , -POWER_SUPPLY_PROP_CAPACITY_LEVEL , -POWER_SUPPLY_PROP_TEMP , -POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW , -POWER_SUPPLY_PROP_TIME_TO_FULL_NOW , -POWER_SUPPLY_PROP_TECHNOLOGY , -POWER_SUPPLY_PROP_CHARGE_FULL , -POWER_SUPPLY_PROP_CHARGE_NOW , -POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN , -POWER_SUPPLY_PROP_CYCLE_COUNT , -POWER_SUPPLY_PROP_ENERGY_NOW , -POWER_SUPPLY_PROP_POWER_AVG , -POWER_SUPPLY_PROP_HEALTH , -POWER_SUPPLY_PROP_MANUFACTURER , -}; -static enum power_supply_property bq27510g3_battery_props[] = {POWER_SUPPLY_PROP_STATUS ,POWER_SUPPLY_PROP_PRESENT ,
@@ -783,10 +663,7 @@ static struct {BQ27XXX_PROP (BQ27000 , bq27000_battery_props),BQ27XXX_PROP (BQ27010 , bq27010_battery_props),BQ27XXX_PROP (BQ2750X , bq2750x_battery_props), -BQ27XXX_PROP (BQ2751X , bq2751x_battery_props),BQ27XXX_PROP (BQ27500 , bq27500_battery_props), -BQ27XXX_PROP (BQ27510G1 , bq27510g1_battery_props), -BQ27XXX_PROP (BQ27510G2 , bq27510g2_battery_props),BQ27XXX_PROP (BQ27510G3 , bq27510g3_battery_props),BQ27XXX_PROP (BQ27520G1 , bq27520g1_battery_props), BQ27XXX_PROP(BQ27520G2, bq27520g2_battery_props),
@@ -802,11 +679,11 @@ static enum bq27xxx_chip bq27xxx_chips[] = { [BQ27000] = BQ27000, [BQ27010] = BQ27010, [BQ2750X] = BQ2750X, - [BQ2751X] = BQ2751X, - [BQ2752X] = BQ2751X, + [BQ2751X] = BQ27510G3, + [BQ2752X] = BQ27510G3, [BQ27500] = BQ27500, - [BQ27510G1] = BQ27510G1, - [BQ27510G2] = BQ27510G2, + [BQ27510G1] = BQ27500, + [BQ27510G2] = BQ27500, [BQ27510G3] = BQ27510G3, [BQ27520G1] = BQ27520G1, [BQ27520G2] = BQ27520G2,
@@ -1578,10 +1455,7 @@ static bool bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags) {switch (di->chip) {case BQ2750X : -case BQ2751X :case BQ27500 : -case BQ27510G1 : -case BQ27510G2 :case BQ27510G3 :case BQ27520G1 :case BQ27520G2 :
include/linux/power/bq27xxx_battery.h +6 -6
@@ -7,11 +7,8 @@ enum bq27xxx_chip {BQ27000 =1 ,/* bq27000, bq27200 */ BQ27010 ,/* bq27010, bq27210 */ BQ2750X ,/* bq27500 deprecated alias */ -BQ2751X ,/* bq27510, bq27520 deprecated alias */ -BQ27500 ,/* bq27500/1 */ -BQ27510G1 ,/* bq27510G1 */ -BQ27510G2 ,/* bq27510G2 */ -BQ27510G3 ,/* bq27510G3 */ +BQ27500 ,/* bq27500/1, bq27510G1, bq27510G2 */ +BQ27510G3 ,/* bq27510G3, bq27510, bq27520 */ BQ27520G1 ,/* bq27520G1 */ BQ27520G2 ,/* bq27520G2 */ BQ27520G3, /* bq27520G3 */
@@ -23,7 +20,10 @@ enum bq27xxx_chip {BQ27MAX ,/* these map to above in bq27xxx_chips[] */ -BQ2752X ,/* deprecated alias */ +BQ2751X ,/* bq27510 deprecated alias */ +BQ2752X ,/* bq27520 deprecated alias */ +BQ27510G1 , +BQ27510G2 ,BQ27531 ,BQ27542 , BQ27546,
Signature · 1 line
2.9.3