linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/6] Add support for additional bq27xxx devices
@ 2015-08-05 16:05 Andrew F. Davis
  2015-08-05 16:05 ` [PATCH v3 1/6] power: bq27x00_battery: Remove unneeded i2c MODULE_ALIAS Andrew F. Davis
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Andrew F. Davis @ 2015-08-05 16:05 UTC (permalink / raw)
  To: Pali Rohár, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, Dan Murphy
  Cc: linux-pm, linux-kernel, Andrew F. Davis

This series adds support for several additional bq27xxx devices and 
makes a few related fixes. v1 can be found here: [1] v2: [2]

Changes from v2:
 - Fix alignment issue
 - Fix commit message typo
 - Use INVALID_REG_ADDR in register mappings

Changes from v1:
 - Drop first four patches from series as they have been queued
   at git://git.infradead.org/battery-2.6.git
 - Remove MODULE_ALIAS
 - Add comment about State-of-Charge
 - Add additional links to documentation
 - Add device names to id table
 - Add unlikely to if statement
 - Change return types to bool for status check functions

Please note this series depends on the first four patches found in v1.

[1] http://www.spinics.net/lists/kernel/msg2039278.html
[2] http://www.spinics.net/lists/kernel/msg2043759.html

Andrew F. Davis (6):
  power: bq27x00_battery: Remove unneeded i2c MODULE_ALIAS
  power: bq27x00_battery: Renaming for consistency
  power: bq27xxx_battery: Platform initialization must declare a device
  power: bq27xxx_battery: Fix typos and change naming for state of
    charge functions
  power: bq27xxx_battery: Add support for additional bq27xxx family
    devices
  power: bq27xxx_battery: Cleanup health checking

 MAINTAINERS                           |    4 +-
 arch/arm/configs/omap2plus_defconfig  |    2 +-
 arch/unicore32/Kconfig                |    2 +-
 drivers/power/Kconfig                 |   22 +-
 drivers/power/Makefile                |    2 +-
 drivers/power/bq27x00_battery.c       | 1129 ---------------------------
 drivers/power/bq27xxx_battery.c       | 1360 +++++++++++++++++++++++++++++++++
 drivers/w1/slaves/w1_bq27000.c        |    5 +-
 include/linux/power/bq27x00_battery.h |   19 -
 include/linux/power/bq27xxx_battery.h |   31 +
 10 files changed, 1410 insertions(+), 1166 deletions(-)
 delete mode 100644 drivers/power/bq27x00_battery.c
 create mode 100644 drivers/power/bq27xxx_battery.c
 delete mode 100644 include/linux/power/bq27x00_battery.h
 create mode 100644 include/linux/power/bq27xxx_battery.h

-- 
1.9.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 1/6] power: bq27x00_battery: Remove unneeded i2c MODULE_ALIAS
  2015-08-05 16:05 [PATCH v3 0/6] Add support for additional bq27xxx devices Andrew F. Davis
@ 2015-08-05 16:05 ` Andrew F. Davis
  2015-08-05 16:05 ` [PATCH v3 2/6] power: bq27x00_battery: Renaming for consistency Andrew F. Davis
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Andrew F. Davis @ 2015-08-05 16:05 UTC (permalink / raw)
  To: Pali Rohár, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, Dan Murphy
  Cc: linux-pm, linux-kernel, Andrew F. Davis

The MODULE_DEVICE_TABLE macro automatically adds all needed
i2c MODULE_ALIASes so remove the extra MODULE_ALIAS.

Signed-off-by: Andrew F. Davis <afd@ti.com>
Acked-by: Pali Rohár <pali.rohar@gmail.com>
---
 drivers/power/bq27x00_battery.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 8287261f..d0b2f3b 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -1120,10 +1120,6 @@ module_exit(bq27x00_battery_exit);
 MODULE_ALIAS("platform:bq27000-battery");
 #endif
 
-#ifdef CONFIG_BATTERY_BQ27X00_I2C
-MODULE_ALIAS("i2c:bq27000-battery");
-#endif
-
 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
 MODULE_DESCRIPTION("BQ27x00 battery monitor driver");
 MODULE_LICENSE("GPL");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 2/6] power: bq27x00_battery: Renaming for consistency
  2015-08-05 16:05 [PATCH v3 0/6] Add support for additional bq27xxx devices Andrew F. Davis
  2015-08-05 16:05 ` [PATCH v3 1/6] power: bq27x00_battery: Remove unneeded i2c MODULE_ALIAS Andrew F. Davis
@ 2015-08-05 16:05 ` Andrew F. Davis
  2015-08-05 16:05 ` [PATCH v3 3/6] power: bq27xxx_battery: Platform initialization must declare a device Andrew F. Davis
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Andrew F. Davis @ 2015-08-05 16:05 UTC (permalink / raw)
  To: Pali Rohár, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, Dan Murphy
  Cc: linux-pm, linux-kernel, Andrew F. Davis

Rename functions that are used by multiple devices. New devices
have been added and the function names and driver name are no longer
general enough for the functionality they provide.

Signed-off-by: Andrew F. Davis <afd@ti.com>
Acked-by: Pali Rohár <pali.rohar@gmail.com>
---
 MAINTAINERS                                        |   4 +-
 arch/arm/configs/omap2plus_defconfig               |   2 +-
 arch/unicore32/Kconfig                             |   2 +-
 drivers/power/Kconfig                              |  22 +-
 drivers/power/Makefile                             |   2 +-
 .../power/{bq27x00_battery.c => bq27xxx_battery.c} | 333 +++++++++++----------
 drivers/w1/slaves/w1_bq27000.c                     |   4 +-
 .../power/{bq27x00_battery.h => bq27xxx_battery.h} |   4 +-
 8 files changed, 187 insertions(+), 186 deletions(-)
 rename drivers/power/{bq27x00_battery.c => bq27xxx_battery.c} (70%)
 rename include/linux/power/{bq27x00_battery.h => bq27xxx_battery.h} (85%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8133cef..8143fa25 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7212,10 +7212,10 @@ NOKIA N900 POWER SUPPLY DRIVERS
 M:	Pali Rohár <pali.rohar@gmail.com>
 S:	Maintained
 F:	include/linux/power/bq2415x_charger.h
-F:	include/linux/power/bq27x00_battery.h
+F:	include/linux/power/bq27xxx_battery.h
 F:	include/linux/power/isp1704_charger.h
 F:	drivers/power/bq2415x_charger.c
-F:	drivers/power/bq27x00_battery.c
+F:	drivers/power/bq27xxx_battery.c
 F:	drivers/power/isp1704_charger.c
 F:	drivers/power/rx51_battery.c
 
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index ac521e7..a79232c 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -241,7 +241,7 @@ CONFIG_GPIO_TWL4030=y
 CONFIG_GPIO_PALMAS=y
 CONFIG_W1=m
 CONFIG_HDQ_MASTER_OMAP=m
-CONFIG_BATTERY_BQ27x00=m
+CONFIG_BATTERY_BQ27XXX=m
 CONFIG_CHARGER_ISP1704=m
 CONFIG_CHARGER_TWL4030=m
 CONFIG_CHARGER_BQ2415X=m
diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
index 928237a..c9faddc 100644
--- a/arch/unicore32/Kconfig
+++ b/arch/unicore32/Kconfig
@@ -222,7 +222,7 @@ config I2C_BATTERY_BQ27200
 	tristate "I2C Battery BQ27200 Support"
 	select I2C_PUV3
 	select POWER_SUPPLY
-	select BATTERY_BQ27x00
+	select BATTERY_BQ27XXX
 
 config I2C_EEPROM_AT24
 	tristate "I2C EEPROMs AT24 support"
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 08beeed..cafcfe2 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -157,26 +157,26 @@ config BATTERY_SBS
 	  Say Y to include support for SBS battery driver for SBS-compliant
 	  gas gauges.
 
-config BATTERY_BQ27x00
-	tristate "BQ27x00 battery driver"
+config BATTERY_BQ27XXX
+	tristate "BQ27xxx battery driver"
 	depends on I2C || I2C=n
 	help
-	  Say Y here to enable support for batteries with BQ27x00 (I2C/HDQ) chips.
+	  Say Y here to enable support for batteries with BQ27xxx (I2C/HDQ) chips.
 
-config BATTERY_BQ27X00_I2C
-	bool "BQ27200/BQ27500 support"
-	depends on BATTERY_BQ27x00
+config BATTERY_BQ27XXX_I2C
+	bool "BQ27xxx I2C support"
+	depends on BATTERY_BQ27XXX
 	depends on I2C
 	default y
 	help
-	  Say Y here to enable support for batteries with BQ27x00 (I2C) chips.
+	  Say Y here to enable support for batteries with BQ27xxx (I2C) chips.
 
-config BATTERY_BQ27X00_PLATFORM
-	bool "BQ27000 support"
-	depends on BATTERY_BQ27x00
+config BATTERY_BQ27XXX_PLATFORM
+	bool "BQ27xxx HDQ support"
+	depends on BATTERY_BQ27XXX
 	default y
 	help
-	  Say Y here to enable support for batteries with BQ27000 (HDQ) chips.
+	  Say Y here to enable support for batteries with BQ27xxx (HDQ) chips.
 
 config BATTERY_DA9030
 	tristate "DA9030 battery driver"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 5752ce8..7a5bc96 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -29,7 +29,7 @@ obj-$(CONFIG_BATTERY_COLLIE)	+= collie_battery.o
 obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
 obj-$(CONFIG_BATTERY_WM97XX)	+= wm97xx_battery.o
 obj-$(CONFIG_BATTERY_SBS)	+= sbs-battery.o
-obj-$(CONFIG_BATTERY_BQ27x00)	+= bq27x00_battery.o
+obj-$(CONFIG_BATTERY_BQ27XXX)	+= bq27xxx_battery.o
 obj-$(CONFIG_BATTERY_DA9030)	+= da9030_battery.o
 obj-$(CONFIG_BATTERY_DA9052)	+= da9052-battery.o
 obj-$(CONFIG_CHARGER_DA9150)	+= da9150-charger.o
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27xxx_battery.c
similarity index 70%
rename from drivers/power/bq27x00_battery.c
rename to drivers/power/bq27xxx_battery.c
index d0b2f3b..e72055c 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27xxx_battery.c
@@ -1,5 +1,5 @@
 /*
- * BQ27x00 battery driver
+ * BQ27xxx battery driver
  *
  * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
  * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
@@ -37,7 +37,7 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
-#include <linux/power/bq27x00_battery.h>
+#include <linux/power/bq27xxx_battery.h>
 
 #define DRIVER_VERSION		"1.2.0"
 
@@ -83,17 +83,17 @@
 #define BQ27425_REG_SOC		(0x1C + BQ27425_REG_OFFSET)
 #define BQ27425_REG_DCAP	(0x3C + BQ27425_REG_OFFSET)
 
-#define BQ27000_RS			20 /* Resistor sense */
-#define BQ27x00_POWER_CONSTANT		(256 * 29200 / 1000)
+#define BQ27XXX_RS			20 /* Resistor sense */
+#define BQ27XXX_POWER_CONSTANT		(256 * 29200 / 1000)
 
-struct bq27x00_device_info;
-struct bq27x00_access_methods {
-	int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);
+struct bq27xxx_device_info;
+struct bq27xxx_access_methods {
+	int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single);
 };
 
-enum bq27x00_chip { BQ27000, BQ27500, BQ27425, BQ27742, BQ27510};
+enum bq27xxx_chip { BQ27000, BQ27500, BQ27425, BQ27742, BQ27510};
 
-struct bq27x00_reg_cache {
+struct bq27xxx_reg_cache {
 	int temperature;
 	int time_to_empty;
 	int time_to_empty_avg;
@@ -107,12 +107,12 @@ struct bq27x00_reg_cache {
 	int health;
 };
 
-struct bq27x00_device_info {
+struct bq27xxx_device_info {
 	struct device		*dev;
 	int			id;
-	enum bq27x00_chip	chip;
+	enum bq27xxx_chip	chip;
 
-	struct bq27x00_reg_cache cache;
+	struct bq27xxx_reg_cache cache;
 	int charge_design_full;
 
 	unsigned long last_update;
@@ -120,7 +120,7 @@ struct bq27x00_device_info {
 
 	struct power_supply	*bat;
 
-	struct bq27x00_access_methods bus;
+	struct bq27xxx_access_methods bus;
 
 	struct mutex lock;
 };
@@ -206,10 +206,10 @@ MODULE_PARM_DESC(poll_interval,
 		 "battery poll interval in seconds - 0 disables polling");
 
 /*
- * Common code for BQ27x00 devices
+ * Common code for BQ27xxx devices
  */
 
-static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
+static inline int bq27xxx_read(struct bq27xxx_device_info *di, u8 reg,
 			       bool single)
 {
 	if (di->chip == BQ27425)
@@ -222,7 +222,7 @@ static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
  * differ from BQ27000 and BQ27200 in calculation of certain
  * parameters. Hence we need to check for the chip type.
  */
-static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di)
+static bool bq27xxx_is_chip_version_higher(struct bq27xxx_device_info *di)
 {
 	if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742
 	    || di->chip == BQ27510)
@@ -234,18 +234,18 @@ static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di)
  * Return the battery Relative State-of-Charge
  * Or < 0 if something fails.
  */
-static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
+static int bq27xxx_battery_read_rsoc(struct bq27xxx_device_info *di)
 {
 	int rsoc;
 
 	if (di->chip == BQ27500 || di->chip == BQ27742)
-		rsoc = bq27x00_read(di, BQ27500_REG_SOC, false);
+		rsoc = bq27xxx_read(di, BQ27500_REG_SOC, false);
 	else if (di->chip == BQ27510)
-		rsoc = bq27x00_read(di, BQ27510_REG_SOC, false);
+		rsoc = bq27xxx_read(di, BQ27510_REG_SOC, false);
 	else if (di->chip == BQ27425)
-		rsoc = bq27x00_read(di, BQ27425_REG_SOC, false);
+		rsoc = bq27xxx_read(di, BQ27425_REG_SOC, false);
 	else
-		rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);
+		rsoc = bq27xxx_read(di, BQ27000_REG_RSOC, true);
 
 	if (rsoc < 0)
 		dev_dbg(di->dev, "error reading relative State-of-Charge\n");
@@ -257,11 +257,11 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
  * Return a battery charge value in µAh
  * Or < 0 if something fails.
  */
-static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
+static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg)
 {
 	int charge;
 
-	charge = bq27x00_read(di, reg, false);
+	charge = bq27xxx_read(di, reg, false);
 	if (charge < 0) {
 		dev_dbg(di->dev, "error reading charge register %02x: %d\n",
 			reg, charge);
@@ -271,7 +271,7 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
 	if (bq27xxx_is_chip_version_higher(di))
 		charge *= 1000;
 	else
-		charge = charge * 3570 / BQ27000_RS;
+		charge = charge * 3570 / BQ27XXX_RS;
 
 	return charge;
 }
@@ -280,7 +280,7 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
  * Return the battery Nominal available capaciy in µAh
  * Or < 0 if something fails.
  */
-static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
+static inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di)
 {
 	int flags;
 	bool is_bq27500 = di->chip == BQ27500;
@@ -288,39 +288,39 @@ static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
 	bool is_higher = bq27xxx_is_chip_version_higher(di);
 	bool flags_1b = !(is_bq27500 || is_bq27742);
 
-	flags = bq27x00_read(di, BQ27x00_REG_FLAGS, flags_1b);
+	flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, flags_1b);
 	if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI))
 		return -ENODATA;
 
-	return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC);
+	return bq27xxx_battery_read_charge(di, BQ27x00_REG_NAC);
 }
 
 /*
  * Return the battery Last measured discharge in µAh
  * Or < 0 if something fails.
  */
-static inline int bq27x00_battery_read_lmd(struct bq27x00_device_info *di)
+static inline int bq27xxx_battery_read_lmd(struct bq27xxx_device_info *di)
 {
-	return bq27x00_battery_read_charge(di, BQ27x00_REG_LMD);
+	return bq27xxx_battery_read_charge(di, BQ27x00_REG_LMD);
 }
 
 /*
  * Return the battery Initial last measured discharge in µAh
  * Or < 0 if something fails.
  */
-static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
+static int bq27xxx_battery_read_ilmd(struct bq27xxx_device_info *di)
 {
 	int ilmd;
 
 	if (bq27xxx_is_chip_version_higher(di)) {
 		if (di->chip == BQ27425)
-			ilmd = bq27x00_read(di, BQ27425_REG_DCAP, false);
+			ilmd = bq27xxx_read(di, BQ27425_REG_DCAP, false);
 		else if (di->chip == BQ27510)
-			ilmd = bq27x00_read(di, BQ27510_REG_DCAP, false);
+			ilmd = bq27xxx_read(di, BQ27510_REG_DCAP, false);
 		else
-			ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);
+			ilmd = bq27xxx_read(di, BQ27500_REG_DCAP, false);
 	} else {
-		ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
+		ilmd = bq27xxx_read(di, BQ27000_REG_ILMD, true);
 	}
 
 	if (ilmd < 0) {
@@ -331,7 +331,7 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
 	if (bq27xxx_is_chip_version_higher(di))
 		ilmd *= 1000;
 	else
-		ilmd = ilmd * 256 * 3570 / BQ27000_RS;
+		ilmd = ilmd * 256 * 3570 / BQ27XXX_RS;
 
 	return ilmd;
 }
@@ -340,11 +340,11 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
  * Return the battery Available energy in µWh
  * Or < 0 if something fails.
  */
-static int bq27x00_battery_read_energy(struct bq27x00_device_info *di)
+static int bq27xxx_battery_read_energy(struct bq27xxx_device_info *di)
 {
 	int ae;
 
-	ae = bq27x00_read(di, BQ27x00_REG_AE, false);
+	ae = bq27xxx_read(di, BQ27x00_REG_AE, false);
 	if (ae < 0) {
 		dev_dbg(di->dev, "error reading available energy\n");
 		return ae;
@@ -353,7 +353,7 @@ static int bq27x00_battery_read_energy(struct bq27x00_device_info *di)
 	if (di->chip == BQ27500)
 		ae *= 1000;
 	else
-		ae = ae * 29200 / BQ27000_RS;
+		ae = ae * 29200 / BQ27XXX_RS;
 
 	return ae;
 }
@@ -362,11 +362,11 @@ static int bq27x00_battery_read_energy(struct bq27x00_device_info *di)
  * Return the battery temperature in tenths of degree Kelvin
  * Or < 0 if something fails.
  */
-static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
+static int bq27xxx_battery_read_temperature(struct bq27xxx_device_info *di)
 {
 	int temp;
 
-	temp = bq27x00_read(di, BQ27x00_REG_TEMP, false);
+	temp = bq27xxx_read(di, BQ27x00_REG_TEMP, false);
 	if (temp < 0) {
 		dev_err(di->dev, "error reading temperature\n");
 		return temp;
@@ -382,14 +382,14 @@ static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
  * Return the battery Cycle count total
  * Or < 0 if something fails.
  */
-static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di)
+static int bq27xxx_battery_read_cyct(struct bq27xxx_device_info *di)
 {
 	int cyct;
 
 	if (di->chip == BQ27510)
-		cyct = bq27x00_read(di, BQ27510_REG_CYCT, false);
+		cyct = bq27xxx_read(di, BQ27510_REG_CYCT, false);
 	else
-		cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false);
+		cyct = bq27xxx_read(di, BQ27x00_REG_CYCT, false);
 	if (cyct < 0)
 		dev_err(di->dev, "error reading cycle count total\n");
 
@@ -400,11 +400,11 @@ static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di)
  * Read a time register.
  * Return < 0 if something fails.
  */
-static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
+static int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, u8 reg)
 {
 	int tval;
 
-	tval = bq27x00_read(di, reg, false);
+	tval = bq27xxx_read(di, reg, false);
 	if (tval < 0) {
 		dev_dbg(di->dev, "error reading time register %02x: %d\n",
 			reg, tval);
@@ -421,11 +421,11 @@ static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
  * Read a power avg register.
  * Return < 0 if something fails.
  */
-static int bq27x00_battery_read_pwr_avg(struct bq27x00_device_info *di, u8 reg)
+static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di, u8 reg)
 {
 	int tval;
 
-	tval = bq27x00_read(di, reg, false);
+	tval = bq27xxx_read(di, reg, false);
 	if (tval < 0) {
 		dev_err(di->dev, "error reading power avg rgister  %02x: %d\n",
 			reg, tval);
@@ -435,18 +435,18 @@ static int bq27x00_battery_read_pwr_avg(struct bq27x00_device_info *di, u8 reg)
 	if (di->chip == BQ27500)
 		return tval;
 	else
-		return (tval * BQ27x00_POWER_CONSTANT) / BQ27000_RS;
+		return (tval * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS;
 }
 
 /*
  * Read flag register.
  * Return < 0 if something fails.
  */
-static int bq27x00_battery_read_health(struct bq27x00_device_info *di)
+static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
 {
 	int tval;
 
-	tval = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
+	tval = bq27xxx_read(di, BQ27x00_REG_FLAGS, false);
 	if (tval < 0) {
 		dev_err(di->dev, "error reading flag register:%d\n", tval);
 		return tval;
@@ -475,16 +475,16 @@ static int bq27x00_battery_read_health(struct bq27x00_device_info *di)
 	return -1;
 }
 
-static void bq27x00_update(struct bq27x00_device_info *di)
+static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
 {
-	struct bq27x00_reg_cache cache = {0, };
+	struct bq27xxx_reg_cache cache = {0, };
 	bool is_bq27500 = di->chip == BQ27500;
 	bool is_bq27510 = di->chip == BQ27510;
 	bool is_bq27425 = di->chip == BQ27425;
 	bool is_bq27742 = di->chip == BQ27742;
 	bool flags_1b = !(is_bq27500 || is_bq27742);
 
-	cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, flags_1b);
+	cache.flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, flags_1b);
 	if ((cache.flags & 0xff) == 0xff)
 		/* read error */
 		cache.flags = -1;
@@ -500,41 +500,41 @@ static void bq27x00_update(struct bq27x00_device_info *di)
 			cache.charge_full = -ENODATA;
 			cache.health = -ENODATA;
 		} else {
-			cache.capacity = bq27x00_battery_read_rsoc(di);
+			cache.capacity = bq27xxx_battery_read_rsoc(di);
 			if (is_bq27742 || is_bq27510)
 				cache.time_to_empty =
-					bq27x00_battery_read_time(di,
+					bq27xxx_battery_read_time(di,
 							BQ27x00_REG_TTE);
 			else if (!is_bq27425) {
-				cache.energy = bq27x00_battery_read_energy(di);
+				cache.energy = bq27xxx_battery_read_energy(di);
 				cache.time_to_empty =
-					bq27x00_battery_read_time(di,
+					bq27xxx_battery_read_time(di,
 							BQ27x00_REG_TTE);
 				cache.time_to_empty_avg =
-					bq27x00_battery_read_time(di,
+					bq27xxx_battery_read_time(di,
 							BQ27x00_REG_TTECP);
 				cache.time_to_full =
-					bq27x00_battery_read_time(di,
+					bq27xxx_battery_read_time(di,
 							BQ27x00_REG_TTF);
 			}
-			cache.charge_full = bq27x00_battery_read_lmd(di);
-			cache.health = bq27x00_battery_read_health(di);
+			cache.charge_full = bq27xxx_battery_read_lmd(di);
+			cache.health = bq27xxx_battery_read_health(di);
 		}
-		cache.temperature = bq27x00_battery_read_temperature(di);
+		cache.temperature = bq27xxx_battery_read_temperature(di);
 		if (!is_bq27425)
-			cache.cycle_count = bq27x00_battery_read_cyct(di);
+			cache.cycle_count = bq27xxx_battery_read_cyct(di);
 		if (is_bq27742)
 			cache.power_avg =
-				bq27x00_battery_read_pwr_avg(di,
+				bq27xxx_battery_read_pwr_avg(di,
 						BQ27742_POWER_AVG);
 		else
 			cache.power_avg =
-				bq27x00_battery_read_pwr_avg(di,
+				bq27xxx_battery_read_pwr_avg(di,
 						BQ27x00_POWER_AVG);
 
 		/* We only have to read charge design full once */
 		if (di->charge_design_full <= 0)
-			di->charge_design_full = bq27x00_battery_read_ilmd(di);
+			di->charge_design_full = bq27xxx_battery_read_ilmd(di);
 	}
 
 	if (di->cache.capacity != cache.capacity)
@@ -546,12 +546,12 @@ static void bq27x00_update(struct bq27x00_device_info *di)
 	di->last_update = jiffies;
 }
 
-static void bq27x00_battery_poll(struct work_struct *work)
+static void bq27xxx_battery_poll(struct work_struct *work)
 {
-	struct bq27x00_device_info *di =
-		container_of(work, struct bq27x00_device_info, work.work);
+	struct bq27xxx_device_info *di =
+		container_of(work, struct bq27xxx_device_info, work.work);
 
-	bq27x00_update(di);
+	bq27xxx_battery_update(di);
 
 	if (poll_interval > 0) {
 		/* The timer does not have to be accurate. */
@@ -565,13 +565,13 @@ static void bq27x00_battery_poll(struct work_struct *work)
  * Note that current can be negative signed as well
  * Or 0 if something fails.
  */
-static int bq27x00_battery_current(struct bq27x00_device_info *di,
+static int bq27xxx_battery_current(struct bq27xxx_device_info *di,
 				   union power_supply_propval *val)
 {
 	int curr;
 	int flags;
 
-	curr = bq27x00_read(di, BQ27x00_REG_AI, false);
+	curr = bq27xxx_read(di, BQ27x00_REG_AI, false);
 	if (curr < 0) {
 		dev_err(di->dev, "error reading current\n");
 		return curr;
@@ -581,19 +581,19 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di,
 		/* bq27500 returns signed value */
 		val->intval = (int)((s16)curr) * 1000;
 	} else {
-		flags = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
+		flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, false);
 		if (flags & BQ27000_FLAG_CHGS) {
 			dev_dbg(di->dev, "negative current!\n");
 			curr = -curr;
 		}
 
-		val->intval = curr * 3570 / BQ27000_RS;
+		val->intval = curr * 3570 / BQ27XXX_RS;
 	}
 
 	return 0;
 }
 
-static int bq27x00_battery_status(struct bq27x00_device_info *di,
+static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
 				  union power_supply_propval *val)
 {
 	int status;
@@ -621,7 +621,7 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
 	return 0;
 }
 
-static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
+static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di,
 					  union power_supply_propval *val)
 {
 	int level;
@@ -655,12 +655,12 @@ static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
  * Return the battery Voltage in millivolts
  * Or < 0 if something fails.
  */
-static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
+static int bq27xxx_battery_voltage(struct bq27xxx_device_info *di,
 				   union power_supply_propval *val)
 {
 	int volt;
 
-	volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
+	volt = bq27xxx_read(di, BQ27x00_REG_VOLT, false);
 	if (volt < 0) {
 		dev_err(di->dev, "error reading voltage\n");
 		return volt;
@@ -671,7 +671,7 @@ static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
 	return 0;
 }
 
-static int bq27x00_simple_value(int value,
+static int bq27xxx_simple_value(int value,
 				union power_supply_propval *val)
 {
 	if (value < 0)
@@ -682,17 +682,17 @@ static int bq27x00_simple_value(int value,
 	return 0;
 }
 
-static int bq27x00_battery_get_property(struct power_supply *psy,
+static int bq27xxx_battery_get_property(struct power_supply *psy,
 					enum power_supply_property psp,
 					union power_supply_propval *val)
 {
 	int ret = 0;
-	struct bq27x00_device_info *di = power_supply_get_drvdata(psy);
+	struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
 
 	mutex_lock(&di->lock);
 	if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
 		cancel_delayed_work_sync(&di->work);
-		bq27x00_battery_poll(&di->work.work);
+		bq27xxx_battery_poll(&di->work.work);
 	}
 	mutex_unlock(&di->lock);
 
@@ -701,60 +701,60 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_STATUS:
-		ret = bq27x00_battery_status(di, val);
+		ret = bq27xxx_battery_status(di, val);
 		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-		ret = bq27x00_battery_voltage(di, val);
+		ret = bq27xxx_battery_voltage(di, val);
 		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = di->cache.flags < 0 ? 0 : 1;
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
-		ret = bq27x00_battery_current(di, val);
+		ret = bq27xxx_battery_current(di, val);
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
-		ret = bq27x00_simple_value(di->cache.capacity, val);
+		ret = bq27xxx_simple_value(di->cache.capacity, val);
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
-		ret = bq27x00_battery_capacity_level(di, val);
+		ret = bq27xxx_battery_capacity_level(di, val);
 		break;
 	case POWER_SUPPLY_PROP_TEMP:
-		ret = bq27x00_simple_value(di->cache.temperature, val);
+		ret = bq27xxx_simple_value(di->cache.temperature, val);
 		if (ret == 0)
 			val->intval -= 2731;
 		break;
 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
-		ret = bq27x00_simple_value(di->cache.time_to_empty, val);
+		ret = bq27xxx_simple_value(di->cache.time_to_empty, val);
 		break;
 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
-		ret = bq27x00_simple_value(di->cache.time_to_empty_avg, val);
+		ret = bq27xxx_simple_value(di->cache.time_to_empty_avg, val);
 		break;
 	case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
-		ret = bq27x00_simple_value(di->cache.time_to_full, val);
+		ret = bq27xxx_simple_value(di->cache.time_to_full, val);
 		break;
 	case POWER_SUPPLY_PROP_TECHNOLOGY:
 		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_NOW:
-		ret = bq27x00_simple_value(bq27x00_battery_read_nac(di), val);
+		ret = bq27xxx_simple_value(bq27xxx_battery_read_nac(di), val);
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL:
-		ret = bq27x00_simple_value(di->cache.charge_full, val);
+		ret = bq27xxx_simple_value(di->cache.charge_full, val);
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
-		ret = bq27x00_simple_value(di->charge_design_full, val);
+		ret = bq27xxx_simple_value(di->charge_design_full, val);
 		break;
 	case POWER_SUPPLY_PROP_CYCLE_COUNT:
-		ret = bq27x00_simple_value(di->cache.cycle_count, val);
+		ret = bq27xxx_simple_value(di->cache.cycle_count, val);
 		break;
 	case POWER_SUPPLY_PROP_ENERGY_NOW:
-		ret = bq27x00_simple_value(di->cache.energy, val);
+		ret = bq27xxx_simple_value(di->cache.energy, val);
 		break;
 	case POWER_SUPPLY_PROP_POWER_AVG:
-		ret = bq27x00_simple_value(di->cache.power_avg, val);
+		ret = bq27xxx_simple_value(di->cache.power_avg, val);
 		break;
 	case POWER_SUPPLY_PROP_HEALTH:
-		ret = bq27x00_simple_value(di->cache.health, val);
+		ret = bq27xxx_simple_value(di->cache.health, val);
 		break;
 	case POWER_SUPPLY_PROP_MANUFACTURER:
 		val->strval = BQ27XXX_MANUFACTURER;
@@ -766,15 +766,15 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
 	return ret;
 }
 
-static void bq27x00_external_power_changed(struct power_supply *psy)
+static void bq27xxx_external_power_changed(struct power_supply *psy)
 {
-	struct bq27x00_device_info *di = power_supply_get_drvdata(psy);
+	struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
 
 	cancel_delayed_work_sync(&di->work);
 	schedule_delayed_work(&di->work, 0);
 }
 
-static int bq27x00_powersupply_init(struct bq27x00_device_info *di,
+static int bq27xxx_powersupply_init(struct bq27xxx_device_info *di,
 				    const char *name)
 {
 	int ret;
@@ -800,10 +800,10 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di,
 		psy_desc->properties = bq27x00_battery_props;
 		psy_desc->num_properties = ARRAY_SIZE(bq27x00_battery_props);
 	}
-	psy_desc->get_property = bq27x00_battery_get_property;
-	psy_desc->external_power_changed = bq27x00_external_power_changed;
+	psy_desc->get_property = bq27xxx_battery_get_property;
+	psy_desc->external_power_changed = bq27xxx_external_power_changed;
 
-	INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
+	INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
 	mutex_init(&di->lock);
 
 	di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
@@ -815,17 +815,17 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di,
 
 	dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
 
-	bq27x00_update(di);
+	bq27xxx_battery_update(di);
 
 	return 0;
 }
 
-static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
+static void bq27xxx_powersupply_unregister(struct bq27xxx_device_info *di)
 {
 	/*
-	 * power_supply_unregister call bq27x00_battery_get_property which
-	 * call bq27x00_battery_poll.
-	 * Make sure that bq27x00_battery_poll will not call
+	 * power_supply_unregister call bq27xxx_battery_get_property which
+	 * call bq27xxx_battery_poll.
+	 * Make sure that bq27xxx_battery_poll will not call
 	 * schedule_delayed_work again after unregister (which cause OOPS).
 	 */
 	poll_interval = 0;
@@ -838,7 +838,7 @@ static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
 }
 
 /* i2c specific code */
-#ifdef CONFIG_BATTERY_BQ27X00_I2C
+#ifdef CONFIG_BATTERY_BQ27XXX_I2C
 
 /* If the system has several batteries we need a different name for each
  * of them...
@@ -846,7 +846,8 @@ static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
 static DEFINE_IDR(battery_id);
 static DEFINE_MUTEX(battery_mutex);
 
-static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single)
+static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
+				    bool single)
 {
 	struct i2c_client *client = to_i2c_client(di->dev);
 	struct i2c_msg msg[2];
@@ -880,11 +881,11 @@ static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single)
 	return ret;
 }
 
-static int bq27x00_battery_probe(struct i2c_client *client,
-				 const struct i2c_device_id *id)
+static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
+				     const struct i2c_device_id *id)
 {
 	char *name;
-	struct bq27x00_device_info *di;
+	struct bq27xxx_device_info *di;
 	int num;
 	int retval = 0;
 
@@ -910,9 +911,9 @@ static int bq27x00_battery_probe(struct i2c_client *client,
 	di->id = num;
 	di->dev = &client->dev;
 	di->chip = id->driver_data;
-	di->bus.read = &bq27x00_read_i2c;
+	di->bus.read = &bq27xxx_battery_i2c_read;
 
-	retval = bq27x00_powersupply_init(di, name);
+	retval = bq27xxx_powersupply_init(di, name);
 	if (retval)
 		goto batt_failed;
 
@@ -928,11 +929,11 @@ batt_failed:
 	return retval;
 }
 
-static int bq27x00_battery_remove(struct i2c_client *client)
+static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
 {
-	struct bq27x00_device_info *di = i2c_get_clientdata(client);
+	struct bq27xxx_device_info *di = i2c_get_clientdata(client);
 
-	bq27x00_powersupply_unregister(di);
+	bq27xxx_powersupply_unregister(di);
 
 	mutex_lock(&battery_mutex);
 	idr_remove(&battery_id, di->id);
@@ -941,7 +942,7 @@ static int bq27x00_battery_remove(struct i2c_client *client)
 	return 0;
 }
 
-static const struct i2c_device_id bq27x00_id[] = {
+static const struct i2c_device_id bq27xxx_id[] = {
 	{ "bq27200", BQ27000 },	/* bq27200 is same as bq27000, but with i2c */
 	{ "bq27500", BQ27500 },
 	{ "bq27425", BQ27425 },
@@ -949,47 +950,47 @@ static const struct i2c_device_id bq27x00_id[] = {
 	{ "bq27510", BQ27510 },
 	{},
 };
-MODULE_DEVICE_TABLE(i2c, bq27x00_id);
+MODULE_DEVICE_TABLE(i2c, bq27xxx_id);
 
-static struct i2c_driver bq27x00_battery_driver = {
+static struct i2c_driver bq27xxx_battery_i2c_driver = {
 	.driver = {
-		.name = "bq27x00-battery",
+		.name = "bq27xxx-battery",
 	},
-	.probe = bq27x00_battery_probe,
-	.remove = bq27x00_battery_remove,
-	.id_table = bq27x00_id,
+	.probe = bq27xxx_battery_i2c_probe,
+	.remove = bq27xxx_battery_i2c_remove,
+	.id_table = bq27xxx_id,
 };
 
-static inline int bq27x00_battery_i2c_init(void)
+static inline int bq27xxx_battery_i2c_init(void)
 {
-	int ret = i2c_add_driver(&bq27x00_battery_driver);
+	int ret = i2c_add_driver(&bq27xxx_battery_i2c_driver);
 
 	if (ret)
-		pr_err("Unable to register BQ27x00 i2c driver\n");
+		pr_err("Unable to register BQ27xxx i2c driver\n");
 
 	return ret;
 }
 
-static inline void bq27x00_battery_i2c_exit(void)
+static inline void bq27xxx_battery_i2c_exit(void)
 {
-	i2c_del_driver(&bq27x00_battery_driver);
+	i2c_del_driver(&bq27xxx_battery_i2c_driver);
 }
 
 #else
 
-static inline int bq27x00_battery_i2c_init(void) { return 0; }
-static inline void bq27x00_battery_i2c_exit(void) {};
+static inline int bq27xxx_battery_i2c_init(void) { return 0; }
+static inline void bq27xxx_battery_i2c_exit(void) {};
 
 #endif
 
 /* platform specific code */
-#ifdef CONFIG_BATTERY_BQ27X00_PLATFORM
+#ifdef CONFIG_BATTERY_BQ27XXX_PLATFORM
 
-static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
-				 bool single)
+static int bq27xxx_battery_platform_read(struct bq27xxx_device_info *di, u8 reg,
+					 bool single)
 {
 	struct device *dev = di->dev;
-	struct bq27000_platform_data *pdata = dev->platform_data;
+	struct bq27xxx_platform_data *pdata = dev->platform_data;
 	unsigned int timeout = 3;
 	int upper, lower;
 	int temp;
@@ -1019,10 +1020,10 @@ static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
 	return pdata->read(dev, reg);
 }
 
-static int bq27000_battery_probe(struct platform_device *pdev)
+static int bq27xxx_battery_platform_probe(struct platform_device *pdev)
 {
-	struct bq27x00_device_info *di;
-	struct bq27000_platform_data *pdata = pdev->dev.platform_data;
+	struct bq27xxx_device_info *di;
+	struct bq27xxx_platform_data *pdata = pdev->dev.platform_data;
 	const char *name;
 
 	if (!pdata) {
@@ -1045,47 +1046,47 @@ static int bq27000_battery_probe(struct platform_device *pdev)
 	di->chip = BQ27000;
 
 	name = pdata->name ?: dev_name(&pdev->dev);
-	di->bus.read = &bq27000_read_platform;
+	di->bus.read = &bq27xxx_battery_platform_read;
 
-	return bq27x00_powersupply_init(di, name);
+	return bq27xxx_powersupply_init(di, name);
 }
 
-static int bq27000_battery_remove(struct platform_device *pdev)
+static int bq27xxx_battery_platform_remove(struct platform_device *pdev)
 {
-	struct bq27x00_device_info *di = platform_get_drvdata(pdev);
+	struct bq27xxx_device_info *di = platform_get_drvdata(pdev);
 
-	bq27x00_powersupply_unregister(di);
+	bq27xxx_powersupply_unregister(di);
 
 	return 0;
 }
 
-static struct platform_driver bq27000_battery_driver = {
-	.probe	= bq27000_battery_probe,
-	.remove = bq27000_battery_remove,
+static struct platform_driver bq27xxx_battery_platform_driver = {
+	.probe	= bq27xxx_battery_platform_probe,
+	.remove = bq27xxx_battery_platform_remove,
 	.driver = {
 		.name = "bq27000-battery",
 	},
 };
 
-static inline int bq27x00_battery_platform_init(void)
+static inline int bq27xxx_battery_platform_init(void)
 {
-	int ret = platform_driver_register(&bq27000_battery_driver);
+	int ret = platform_driver_register(&bq27xxx_battery_platform_driver);
 
 	if (ret)
-		pr_err("Unable to register BQ27000 platform driver\n");
+		pr_err("Unable to register BQ27xxx platform driver\n");
 
 	return ret;
 }
 
-static inline void bq27x00_battery_platform_exit(void)
+static inline void bq27xxx_battery_platform_exit(void)
 {
-	platform_driver_unregister(&bq27000_battery_driver);
+	platform_driver_unregister(&bq27xxx_battery_platform_driver);
 }
 
 #else
 
-static inline int bq27x00_battery_platform_init(void) { return 0; }
-static inline void bq27x00_battery_platform_exit(void) {};
+static inline int bq27xxx_battery_platform_init(void) { return 0; }
+static inline void bq27xxx_battery_platform_exit(void) {};
 
 #endif
 
@@ -1093,33 +1094,33 @@ static inline void bq27x00_battery_platform_exit(void) {};
  * Module stuff
  */
 
-static int __init bq27x00_battery_init(void)
+static int __init bq27xxx_battery_init(void)
 {
 	int ret;
 
-	ret = bq27x00_battery_i2c_init();
+	ret = bq27xxx_battery_i2c_init();
 	if (ret)
 		return ret;
 
-	ret = bq27x00_battery_platform_init();
+	ret = bq27xxx_battery_platform_init();
 	if (ret)
-		bq27x00_battery_i2c_exit();
+		bq27xxx_battery_i2c_exit();
 
 	return ret;
 }
-module_init(bq27x00_battery_init);
+module_init(bq27xxx_battery_init);
 
-static void __exit bq27x00_battery_exit(void)
+static void __exit bq27xxx_battery_exit(void)
 {
-	bq27x00_battery_platform_exit();
-	bq27x00_battery_i2c_exit();
+	bq27xxx_battery_platform_exit();
+	bq27xxx_battery_i2c_exit();
 }
-module_exit(bq27x00_battery_exit);
+module_exit(bq27xxx_battery_exit);
 
-#ifdef CONFIG_BATTERY_BQ27X00_PLATFORM
+#ifdef CONFIG_BATTERY_BQ27XXX_PLATFORM
 MODULE_ALIAS("platform:bq27000-battery");
 #endif
 
 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
-MODULE_DESCRIPTION("BQ27x00 battery monitor driver");
+MODULE_DESCRIPTION("BQ27xxx battery monitor driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c
index caafb17..8480531 100644
--- a/drivers/w1/slaves/w1_bq27000.c
+++ b/drivers/w1/slaves/w1_bq27000.c
@@ -15,7 +15,7 @@
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
-#include <linux/power/bq27x00_battery.h>
+#include <linux/power/bq27xxx_battery.h>
 
 #include "../w1.h"
 #include "../w1_int.h"
@@ -39,7 +39,7 @@ static int w1_bq27000_read(struct device *dev, unsigned int reg)
 	return val;
 }
 
-static struct bq27000_platform_data bq27000_battery_info = {
+static struct bq27xxx_platform_data bq27000_battery_info = {
 	.read   = w1_bq27000_read,
 	.name   = "bq27000-battery",
 };
diff --git a/include/linux/power/bq27x00_battery.h b/include/linux/power/bq27xxx_battery.h
similarity index 85%
rename from include/linux/power/bq27x00_battery.h
rename to include/linux/power/bq27xxx_battery.h
index a857f71..e70a93a 100644
--- a/include/linux/power/bq27x00_battery.h
+++ b/include/linux/power/bq27xxx_battery.h
@@ -2,7 +2,7 @@
 #define __LINUX_BQ27X00_BATTERY_H__
 
 /**
- * struct bq27000_plaform_data - Platform data for bq27000 devices
+ * struct bq27xxx_plaform_data - Platform data for bq27xxx devices
  * @name: Name of the battery. If NULL the driver will fallback to "bq27000".
  * @read: HDQ read callback.
  *	This function should provide access to the HDQ bus the battery is
@@ -11,7 +11,7 @@
  *	register to be read. The return value should either be the content of
  *	the passed register or an error value.
  */
-struct bq27000_platform_data {
+struct bq27xxx_platform_data {
 	const char *name;
 	int (*read)(struct device *dev, unsigned int);
 };
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 3/6] power: bq27xxx_battery: Platform initialization must declare a device
  2015-08-05 16:05 [PATCH v3 0/6] Add support for additional bq27xxx devices Andrew F. Davis
  2015-08-05 16:05 ` [PATCH v3 1/6] power: bq27x00_battery: Remove unneeded i2c MODULE_ALIAS Andrew F. Davis
  2015-08-05 16:05 ` [PATCH v3 2/6] power: bq27x00_battery: Renaming for consistency Andrew F. Davis
@ 2015-08-05 16:05 ` Andrew F. Davis
  2015-08-05 16:05 ` [PATCH v3 4/6] power: bq27xxx_battery: Fix typos and change naming for state of charge functions Andrew F. Davis
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Andrew F. Davis @ 2015-08-05 16:05 UTC (permalink / raw)
  To: Pali Rohár, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, Dan Murphy
  Cc: linux-pm, linux-kernel, Andrew F. Davis

When initialized as a platform device the initializer must now specify
a device. An empty device name is no longer valid.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 drivers/power/bq27xxx_battery.c       | 9 ++++++---
 drivers/w1/slaves/w1_bq27000.c        | 1 +
 include/linux/power/bq27xxx_battery.h | 6 +++++-
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c
index e72055c..0734413 100644
--- a/drivers/power/bq27xxx_battery.c
+++ b/drivers/power/bq27xxx_battery.c
@@ -91,8 +91,6 @@ struct bq27xxx_access_methods {
 	int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single);
 };
 
-enum bq27xxx_chip { BQ27000, BQ27500, BQ27425, BQ27742, BQ27510};
-
 struct bq27xxx_reg_cache {
 	int temperature;
 	int time_to_empty;
@@ -1036,6 +1034,11 @@ static int bq27xxx_battery_platform_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
+	if (!pdata->chip) {
+		dev_err(&pdev->dev, "no device supplied\n");
+		return -EINVAL;
+	}
+
 	di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
 	if (!di)
 		return -ENOMEM;
@@ -1043,7 +1046,7 @@ static int bq27xxx_battery_platform_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, di);
 
 	di->dev = &pdev->dev;
-	di->chip = BQ27000;
+	di->chip = pdata->chip;
 
 	name = pdata->name ?: dev_name(&pdev->dev);
 	di->bus.read = &bq27xxx_battery_platform_read;
diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c
index 8480531..9f4a86b 100644
--- a/drivers/w1/slaves/w1_bq27000.c
+++ b/drivers/w1/slaves/w1_bq27000.c
@@ -42,6 +42,7 @@ static int w1_bq27000_read(struct device *dev, unsigned int reg)
 static struct bq27xxx_platform_data bq27000_battery_info = {
 	.read   = w1_bq27000_read,
 	.name   = "bq27000-battery",
+	.chip   = BQ27000,
 };
 
 static int w1_bq27000_add_slave(struct w1_slave *sl)
diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
index e70a93a..a4efb10 100644
--- a/include/linux/power/bq27xxx_battery.h
+++ b/include/linux/power/bq27xxx_battery.h
@@ -3,7 +3,8 @@
 
 /**
  * struct bq27xxx_plaform_data - Platform data for bq27xxx devices
- * @name: Name of the battery. If NULL the driver will fallback to "bq27000".
+ * @name: Name of the battery.
+ * @chip: Chip class number of this device.
  * @read: HDQ read callback.
  *	This function should provide access to the HDQ bus the battery is
  *	connected to.
@@ -11,8 +12,11 @@
  *	register to be read. The return value should either be the content of
  *	the passed register or an error value.
  */
+enum bq27xxx_chip { BQ27000 = 1, BQ27500, BQ27425, BQ27742, BQ27510 };
+
 struct bq27xxx_platform_data {
 	const char *name;
+	enum bq27xxx_chip chip;
 	int (*read)(struct device *dev, unsigned int);
 };
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 4/6] power: bq27xxx_battery: Fix typos and change naming for state of charge functions
  2015-08-05 16:05 [PATCH v3 0/6] Add support for additional bq27xxx devices Andrew F. Davis
                   ` (2 preceding siblings ...)
  2015-08-05 16:05 ` [PATCH v3 3/6] power: bq27xxx_battery: Platform initialization must declare a device Andrew F. Davis
@ 2015-08-05 16:05 ` Andrew F. Davis
  2015-08-05 16:05 ` [PATCH v3 5/6] power: bq27xxx_battery: Add support for additional bq27xxx family devices Andrew F. Davis
  2015-08-05 16:05 ` [PATCH v3 6/6] power: bq27xxx_battery: Cleanup health checking Andrew F. Davis
  5 siblings, 0 replies; 9+ messages in thread
From: Andrew F. Davis @ 2015-08-05 16:05 UTC (permalink / raw)
  To: Pali Rohár, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, Dan Murphy
  Cc: linux-pm, linux-kernel, Andrew F. Davis

Fix typos and change "relative state of charge" to "state of charge" as not
all supported devices use relative state of charge.

Signed-off-by: Andrew F. Davis <afd@ti.com>
Acked-by: Pali Rohár <pali.rohar@gmail.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
 drivers/power/bq27xxx_battery.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c
index 0734413..1ff88ad 100644
--- a/drivers/power/bq27xxx_battery.c
+++ b/drivers/power/bq27xxx_battery.c
@@ -229,26 +229,26 @@ static bool bq27xxx_is_chip_version_higher(struct bq27xxx_device_info *di)
 }
 
 /*
- * Return the battery Relative State-of-Charge
+ * Return the battery State-of-Charge
  * Or < 0 if something fails.
  */
-static int bq27xxx_battery_read_rsoc(struct bq27xxx_device_info *di)
+static int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di)
 {
-	int rsoc;
+	int soc;
 
 	if (di->chip == BQ27500 || di->chip == BQ27742)
-		rsoc = bq27xxx_read(di, BQ27500_REG_SOC, false);
+		soc = bq27xxx_read(di, BQ27500_REG_SOC, false);
 	else if (di->chip == BQ27510)
-		rsoc = bq27xxx_read(di, BQ27510_REG_SOC, false);
+		soc = bq27xxx_read(di, BQ27510_REG_SOC, false);
 	else if (di->chip == BQ27425)
-		rsoc = bq27xxx_read(di, BQ27425_REG_SOC, false);
-	else
-		rsoc = bq27xxx_read(di, BQ27000_REG_RSOC, true);
+		soc = bq27xxx_read(di, BQ27425_REG_SOC, false);
+	else /* for the bq27000 we read the "relative" SoC register */
+		soc = bq27xxx_read(di, BQ27000_REG_RSOC, true);
 
-	if (rsoc < 0)
-		dev_dbg(di->dev, "error reading relative State-of-Charge\n");
+	if (soc < 0)
+		dev_dbg(di->dev, "error reading State-of-Charge\n");
 
-	return rsoc;
+	return soc;
 }
 
 /*
@@ -275,7 +275,7 @@ static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg)
 }
 
 /*
- * Return the battery Nominal available capaciy in µAh
+ * Return the battery Nominal available capacity in µAh
  * Or < 0 if something fails.
  */
 static inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di)
@@ -416,7 +416,7 @@ static int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, u8 reg)
 }
 
 /*
- * Read a power avg register.
+ * Read an average power register.
  * Return < 0 if something fails.
  */
 static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di, u8 reg)
@@ -498,7 +498,7 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
 			cache.charge_full = -ENODATA;
 			cache.health = -ENODATA;
 		} else {
-			cache.capacity = bq27xxx_battery_read_rsoc(di);
+			cache.capacity = bq27xxx_battery_read_soc(di);
 			if (is_bq27742 || is_bq27510)
 				cache.time_to_empty =
 					bq27xxx_battery_read_time(di,
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 5/6] power: bq27xxx_battery: Add support for additional bq27xxx family devices
  2015-08-05 16:05 [PATCH v3 0/6] Add support for additional bq27xxx devices Andrew F. Davis
                   ` (3 preceding siblings ...)
  2015-08-05 16:05 ` [PATCH v3 4/6] power: bq27xxx_battery: Fix typos and change naming for state of charge functions Andrew F. Davis
@ 2015-08-05 16:05 ` Andrew F. Davis
  2015-08-06  8:28   ` Pali Rohár
  2015-08-05 16:05 ` [PATCH v3 6/6] power: bq27xxx_battery: Cleanup health checking Andrew F. Davis
  5 siblings, 1 reply; 9+ messages in thread
From: Andrew F. Davis @ 2015-08-05 16:05 UTC (permalink / raw)
  To: Pali Rohár, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, Dan Murphy
  Cc: linux-pm, linux-kernel, Andrew F. Davis

Add support for additional devices and register equivalent family devices
including the bq27010, bq27210, bq27500, bq27510, bq27520, bq27530,
bq27531, bq27541, bq27542, bq27546, bq27545, bq27441, bq27421, and the
bq27641.

To facilitate this process the register mapings have been moved to tables
and other small cleanups have been made.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 drivers/power/bq27xxx_battery.c       | 627 +++++++++++++++++++++++-----------
 include/linux/power/bq27xxx_battery.h |  10 +-
 2 files changed, 428 insertions(+), 209 deletions(-)

diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c
index 1ff88ad..3098609 100644
--- a/drivers/power/bq27xxx_battery.c
+++ b/drivers/power/bq27xxx_battery.c
@@ -17,11 +17,24 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * Datasheets:
- * http://focus.ti.com/docs/prod/folders/print/bq27000.html
- * http://focus.ti.com/docs/prod/folders/print/bq27500.html
+ * http://www.ti.com/product/bq27000
+ * http://www.ti.com/product/bq27200
+ * http://www.ti.com/product/bq27010
+ * http://www.ti.com/product/bq27210
+ * http://www.ti.com/product/bq27500
+ * http://www.ti.com/product/bq27510-g3
+ * http://www.ti.com/product/bq27520-g4
+ * http://www.ti.com/product/bq27530-g1
+ * http://www.ti.com/product/bq27531-g1
+ * http://www.ti.com/product/bq27541-g1
+ * http://www.ti.com/product/bq27542-g1
+ * http://www.ti.com/product/bq27546-g1
+ * http://www.ti.com/product/bq27742-g1
+ * http://www.ti.com/product/bq27545-g1
+ * http://www.ti.com/product/bq27421-g1
  * http://www.ti.com/product/bq27425-g1
- * http://www.ti.com/product/BQ27742-G1
- * http://www.ti.com/product/BQ27510-G3
+ * http://www.ti.com/product/bq27411-g1
+ * http://www.ti.com/product/bq27621-g1
  */
 
 #include <linux/device.h>
@@ -43,54 +56,57 @@
 
 #define BQ27XXX_MANUFACTURER	"Texas Instruments"
 
-#define BQ27x00_REG_TEMP	0x06
-#define BQ27x00_REG_VOLT	0x08
-#define BQ27x00_REG_AI		0x14
-#define BQ27x00_REG_FLAGS	0x0A
-#define BQ27x00_REG_TTE		0x16
-#define BQ27x00_REG_TTF		0x18
-#define BQ27x00_REG_TTECP	0x26
-#define BQ27x00_REG_NAC		0x0C /* Nominal available capacity */
-#define BQ27x00_REG_LMD		0x12 /* Last measured discharge */
-#define BQ27x00_REG_CYCT	0x2A /* Cycle count total */
-#define BQ27x00_REG_AE		0x22 /* Available energy */
-#define BQ27x00_POWER_AVG	0x24
-
-#define BQ27000_REG_RSOC	0x0B /* Relative State-of-Charge */
-#define BQ27000_REG_ILMD	0x76 /* Initial last measured discharge */
+/* BQ27XXX Flags */
+#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_FC		BIT(9)
+#define BQ27XXX_FLAG_OTD	BIT(14)
+#define BQ27XXX_FLAG_OTC	BIT(15)
+
+/* BQ27000 has different layout for Flags register */
 #define BQ27000_FLAG_EDVF	BIT(0) /* Final End-of-Discharge-Voltage flag */
 #define BQ27000_FLAG_EDV1	BIT(1) /* First End-of-Discharge-Voltage flag */
 #define BQ27000_FLAG_CI		BIT(4) /* Capacity Inaccurate flag */
 #define BQ27000_FLAG_FC		BIT(5)
 #define BQ27000_FLAG_CHGS	BIT(7) /* Charge state flag */
 
-#define BQ27500_REG_SOC		0x2C
-#define BQ27500_REG_DCAP	0x3C /* Design capacity */
-#define BQ27500_FLAG_DSC	BIT(0)
-#define BQ27500_FLAG_SOCF	BIT(1) /* State-of-Charge threshold final */
-#define BQ27500_FLAG_SOC1	BIT(2) /* State-of-Charge threshold 1 */
-#define BQ27500_FLAG_FC		BIT(9)
-#define BQ27500_FLAG_OTC	BIT(15)
-
-#define BQ27742_POWER_AVG	0x76
-
-#define BQ27510_REG_SOC		0x20
-#define BQ27510_REG_DCAP	0x2E /* Design capacity */
-#define BQ27510_REG_CYCT	0x1E /* Cycle count total */
-
-/* bq27425 register addresses are same as bq27x00 addresses minus 4 */
-#define BQ27425_REG_OFFSET	0x04
-#define BQ27425_REG_SOC		(0x1C + BQ27425_REG_OFFSET)
-#define BQ27425_REG_DCAP	(0x3C + BQ27425_REG_OFFSET)
-
-#define BQ27XXX_RS			20 /* Resistor sense */
-#define BQ27XXX_POWER_CONSTANT		(256 * 29200 / 1000)
+#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 */
 
 struct bq27xxx_device_info;
 struct bq27xxx_access_methods {
 	int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single);
 };
 
+#define INVALID_REG_ADDR	0xff
+
+/*
+ * bq27xxx_reg_index - Register names
+ *
+ * These are indexes into a device's register mapping array.
+ */
+enum bq27xxx_reg_index {
+	BQ27XXX_REG_CTRL = 0,	/* Control */
+	BQ27XXX_REG_TEMP,	/* Temperature */
+	BQ27XXX_REG_INT_TEMP,	/* Internal Temperature */
+	BQ27XXX_REG_VOLT,	/* Voltage */
+	BQ27XXX_REG_AI,		/* Average Current */
+	BQ27XXX_REG_FLAGS,	/* Flags */
+	BQ27XXX_REG_TTE,	/* Time-to-Empty */
+	BQ27XXX_REG_TTF,	/* Time-to-Full */
+	BQ27XXX_REG_TTES,	/* Time-to-Empty Standby */
+	BQ27XXX_REG_TTECP,	/* Time-to-Empty at Constant Power */
+	BQ27XXX_REG_NAC,	/* Nominal Available Capacity */
+	BQ27XXX_REG_FCC,	/* Full Charge Capacity */
+	BQ27XXX_REG_CYCT,	/* Cycle Count */
+	BQ27XXX_REG_AE,		/* Available Energy */
+	BQ27XXX_REG_SOC,	/* State-of-Charge */
+	BQ27XXX_REG_DCAP,	/* Design Capacity */
+	BQ27XXX_REG_AP,		/* Average Power */
+};
+
 struct bq27xxx_reg_cache {
 	int temperature;
 	int time_to_empty;
@@ -121,9 +137,152 @@ struct bq27xxx_device_info {
 	struct bq27xxx_access_methods bus;
 
 	struct mutex lock;
+
+	u8 *regs;
+};
+
+/* Register mappings */
+static u8 bq27000_regs[] = {
+	0x00,	/* CONTROL	*/
+	0x06,	/* TEMP		*/
+	INVALID_REG_ADDR,	/* INT TEMP - NA*/
+	0x08,	/* VOLT		*/
+	0x14,	/* AVG CURR	*/
+	0x0a,	/* FLAGS	*/
+	0x16,	/* TTE		*/
+	0x18,	/* TTF		*/
+	0x1c,	/* TTES		*/
+	0x26,	/* TTECP	*/
+	0x0c,	/* NAC		*/
+	0x12,	/* LMD(FCC)	*/
+	0x2a,	/* CYCT		*/
+	0x22,	/* AE		*/
+	0x0b,	/* SOC(RSOC)	*/
+	0x76,	/* DCAP(ILMD)	*/
+	0x24,	/* AP		*/
+};
+
+static u8 bq27010_regs[] = {
+	0x00,	/* CONTROL	*/
+	0x06,	/* TEMP		*/
+	INVALID_REG_ADDR,	/* INT TEMP - NA*/
+	0x08,	/* VOLT		*/
+	0x14,	/* AVG CURR	*/
+	0x0a,	/* FLAGS	*/
+	0x16,	/* TTE		*/
+	0x18,	/* TTF		*/
+	0x1c,	/* TTES		*/
+	0x26,	/* TTECP	*/
+	0x0c,	/* NAC		*/
+	0x12,	/* LMD(FCC)	*/
+	0x2a,	/* CYCT		*/
+	INVALID_REG_ADDR,	/* AE - NA	*/
+	0x0b,	/* SOC(RSOC)	*/
+	0x76,	/* DCAP(ILMD)	*/
+	INVALID_REG_ADDR,	/* AP - NA	*/
+};
+
+static u8 bq27500_regs[] = {
+	0x00,	/* CONTROL	*/
+	0x06,	/* TEMP		*/
+	0x28,	/* INT TEMP	*/
+	0x08,	/* VOLT		*/
+	0x14,	/* AVG CURR	*/
+	0x0a,	/* FLAGS	*/
+	0x16,	/* TTE		*/
+	INVALID_REG_ADDR,	/* TTF - NA	*/
+	0x1a,	/* TTES		*/
+	INVALID_REG_ADDR,	/* TTECP - NA	*/
+	0x0c,	/* NAC		*/
+	0x12,	/* LMD(FCC)	*/
+	0x1e,	/* CYCT		*/
+	INVALID_REG_ADDR,	/* AE - NA	*/
+	0x20,	/* SOC(RSOC)	*/
+	0x2e,	/* DCAP(ILMD)	*/
+	INVALID_REG_ADDR,	/* AP - NA	*/
 };
 
-static enum power_supply_property bq27x00_battery_props[] = {
+static u8 bq27530_regs[] = {
+	0x00,	/* CONTROL	*/
+	0x06,	/* TEMP		*/
+	0x32,	/* INT TEMP	*/
+	0x08,	/* VOLT		*/
+	0x14,	/* AVG CURR	*/
+	0x0a,	/* FLAGS	*/
+	0x16,	/* TTE		*/
+	INVALID_REG_ADDR,	/* TTF - NA	*/
+	INVALID_REG_ADDR,	/* TTES - NA	*/
+	INVALID_REG_ADDR,	/* TTECP - NA	*/
+	0x0c,	/* NAC		*/
+	0x12,	/* LMD(FCC)	*/
+	0x2a,	/* CYCT		*/
+	INVALID_REG_ADDR,	/* AE - NA	*/
+	0x2c,	/* SOC(RSOC)	*/
+	INVALID_REG_ADDR,	/* DCAP - NA	*/
+	0x24,	/* AP		*/
+};
+
+static u8 bq27541_regs[] = {
+	0x00,	/* CONTROL	*/
+	0x06,	/* TEMP		*/
+	0x28,	/* INT TEMP	*/
+	0x08,	/* VOLT		*/
+	0x14,	/* AVG CURR	*/
+	0x0a,	/* FLAGS	*/
+	0x16,	/* TTE		*/
+	INVALID_REG_ADDR,	/* TTF - NA	*/
+	INVALID_REG_ADDR,	/* TTES - NA	*/
+	INVALID_REG_ADDR,	/* TTECP - NA	*/
+	0x0c,	/* NAC		*/
+	0x12,	/* LMD(FCC)	*/
+	0x2a,	/* CYCT		*/
+	INVALID_REG_ADDR,	/* AE - NA	*/
+	0x2c,	/* SOC(RSOC)	*/
+	0x3c,	/* DCAP		*/
+	0x76,	/* AP		*/
+};
+
+static u8 bq27545_regs[] = {
+	0x00,	/* CONTROL	*/
+	0x06,	/* TEMP		*/
+	0x28,	/* INT TEMP	*/
+	0x08,	/* VOLT		*/
+	0x14,	/* AVG CURR	*/
+	0x0a,	/* FLAGS	*/
+	0x16,	/* TTE		*/
+	INVALID_REG_ADDR,	/* TTF - NA	*/
+	INVALID_REG_ADDR,	/* TTES - NA	*/
+	INVALID_REG_ADDR,	/* TTECP - NA	*/
+	0x0c,	/* NAC		*/
+	0x12,	/* LMD(FCC)	*/
+	0x2a,	/* CYCT		*/
+	INVALID_REG_ADDR,	/* AE - NA	*/
+	0x2c,	/* SOC(RSOC)	*/
+	INVALID_REG_ADDR,	/* DCAP - NA */
+	0x24,	/* AP		*/
+};
+
+static u8 bq27421_regs[] = {
+	0x00,	/* CONTROL	*/
+	0x02,	/* TEMP		*/
+	0x1e,	/* INT TEMP	*/
+	0x04,	/* VOLT		*/
+	0x10,	/* AVG CURR	*/
+	0x06,	/* FLAGS	*/
+	INVALID_REG_ADDR,	/* TTE - NA	*/
+	INVALID_REG_ADDR,	/* TTF - NA	*/
+	INVALID_REG_ADDR,	/* TTES - NA	*/
+	INVALID_REG_ADDR,	/* TTECP - NA	*/
+	0x08,	/* NAC		*/
+	0x0e,	/* FCC		*/
+	INVALID_REG_ADDR,	/* CYCT - NA	*/
+	INVALID_REG_ADDR,	/* AE - NA	*/
+	0x1c,	/* SOC		*/
+	0x3c,	/* DCAP		*/
+	0x18,	/* AP		*/
+};
+
+static enum power_supply_property bq27000_battery_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
@@ -145,7 +304,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
 	POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
-static enum power_supply_property bq27425_battery_props[] = {
+static enum power_supply_property bq27010_battery_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
@@ -153,14 +312,19 @@ static enum power_supply_property bq27425_battery_props[] = {
 	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_EMPTY_AVG,
+	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_HEALTH,
 	POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
-static enum power_supply_property bq27742_battery_props[] = {
+static enum power_supply_property bq27500_battery_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
@@ -174,12 +338,29 @@ static enum power_supply_property bq27742_battery_props[] = {
 	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 bq27530_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_POWER_AVG,
 	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_CYCLE_COUNT,
 	POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
-static enum power_supply_property bq27510_battery_props[] = {
+static enum power_supply_property bq27541_battery_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
@@ -198,6 +379,39 @@ static enum power_supply_property bq27510_battery_props[] = {
 	POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
+static enum power_supply_property bq27545_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_HEALTH,
+	POWER_SUPPLY_PROP_CYCLE_COUNT,
+	POWER_SUPPLY_PROP_POWER_AVG,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static enum power_supply_property bq27421_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_TECHNOLOGY,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
 static unsigned int poll_interval = 360;
 module_param(poll_interval, uint, 0644);
 MODULE_PARM_DESC(poll_interval,
@@ -207,25 +421,14 @@ MODULE_PARM_DESC(poll_interval,
  * Common code for BQ27xxx devices
  */
 
-static inline int bq27xxx_read(struct bq27xxx_device_info *di, u8 reg,
+static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index,
 			       bool single)
 {
-	if (di->chip == BQ27425)
-		return di->bus.read(di, reg - BQ27425_REG_OFFSET, single);
-	return di->bus.read(di, reg, single);
-}
+	/* Reports EINVAL for invalid/missing registers */
+	if (!di || di->regs[reg_index] == INVALID_REG_ADDR)
+		return -EINVAL;
 
-/*
- * Higher versions of the chip like BQ27425 and BQ27500
- * differ from BQ27000 and BQ27200 in calculation of certain
- * parameters. Hence we need to check for the chip type.
- */
-static bool bq27xxx_is_chip_version_higher(struct bq27xxx_device_info *di)
-{
-	if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742
-	    || di->chip == BQ27510)
-		return true;
-	return false;
+	return di->bus.read(di, di->regs[reg_index], single);
 }
 
 /*
@@ -236,14 +439,7 @@ static int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di)
 {
 	int soc;
 
-	if (di->chip == BQ27500 || di->chip == BQ27742)
-		soc = bq27xxx_read(di, BQ27500_REG_SOC, false);
-	else if (di->chip == BQ27510)
-		soc = bq27xxx_read(di, BQ27510_REG_SOC, false);
-	else if (di->chip == BQ27425)
-		soc = bq27xxx_read(di, BQ27425_REG_SOC, false);
-	else /* for the bq27000 we read the "relative" SoC register */
-		soc = bq27xxx_read(di, BQ27000_REG_RSOC, true);
+	soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false);
 
 	if (soc < 0)
 		dev_dbg(di->dev, "error reading State-of-Charge\n");
@@ -266,10 +462,10 @@ static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg)
 		return charge;
 	}
 
-	if (bq27xxx_is_chip_version_higher(di))
-		charge *= 1000;
+	if (di->chip == BQ27000 || di->chip == BQ27010)
+		charge *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
 	else
-		charge = charge * 3570 / BQ27XXX_RS;
+		charge *= 1000;
 
 	return charge;
 }
@@ -281,57 +477,46 @@ static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg)
 static inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di)
 {
 	int flags;
-	bool is_bq27500 = di->chip == BQ27500;
-	bool is_bq27742 = di->chip == BQ27742;
-	bool is_higher = bq27xxx_is_chip_version_higher(di);
-	bool flags_1b = !(is_bq27500 || is_bq27742);
 
-	flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, flags_1b);
-	if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI))
-		return -ENODATA;
+	if (di->chip == BQ27000 || di->chip == BQ27010) {
+		flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, true);
+		if (flags >= 0 && (flags & BQ27000_FLAG_CI))
+			return -ENODATA;
+	}
 
-	return bq27xxx_battery_read_charge(di, BQ27x00_REG_NAC);
+	return bq27xxx_battery_read_charge(di, BQ27XXX_REG_NAC);
 }
 
 /*
- * Return the battery Last measured discharge in µAh
+ * Return the battery Full Charge Capacity in µAh
  * Or < 0 if something fails.
  */
-static inline int bq27xxx_battery_read_lmd(struct bq27xxx_device_info *di)
+static inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di)
 {
-	return bq27xxx_battery_read_charge(di, BQ27x00_REG_LMD);
+	return bq27xxx_battery_read_charge(di, BQ27XXX_REG_FCC);
 }
 
 /*
- * Return the battery Initial last measured discharge in µAh
+ * Return the Design Capacity in µAh
  * Or < 0 if something fails.
  */
-static int bq27xxx_battery_read_ilmd(struct bq27xxx_device_info *di)
+static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
 {
-	int ilmd;
+	int dcap;
 
-	if (bq27xxx_is_chip_version_higher(di)) {
-		if (di->chip == BQ27425)
-			ilmd = bq27xxx_read(di, BQ27425_REG_DCAP, false);
-		else if (di->chip == BQ27510)
-			ilmd = bq27xxx_read(di, BQ27510_REG_DCAP, false);
-		else
-			ilmd = bq27xxx_read(di, BQ27500_REG_DCAP, false);
-	} else {
-		ilmd = bq27xxx_read(di, BQ27000_REG_ILMD, true);
-	}
+	dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
 
-	if (ilmd < 0) {
+	if (dcap < 0) {
 		dev_dbg(di->dev, "error reading initial last measured discharge\n");
-		return ilmd;
+		return dcap;
 	}
 
-	if (bq27xxx_is_chip_version_higher(di))
-		ilmd *= 1000;
+	if (di->chip == BQ27000 || di->chip == BQ27010)
+		dcap *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
 	else
-		ilmd = ilmd * 256 * 3570 / BQ27XXX_RS;
+		dcap *= 1000;
 
-	return ilmd;
+	return dcap;
 }
 
 /*
@@ -342,16 +527,16 @@ static int bq27xxx_battery_read_energy(struct bq27xxx_device_info *di)
 {
 	int ae;
 
-	ae = bq27xxx_read(di, BQ27x00_REG_AE, false);
+	ae = bq27xxx_read(di, BQ27XXX_REG_AE, false);
 	if (ae < 0) {
 		dev_dbg(di->dev, "error reading available energy\n");
 		return ae;
 	}
 
-	if (di->chip == BQ27500)
-		ae *= 1000;
+	if (di->chip == BQ27000 || di->chip == BQ27010)
+		ae *= BQ27XXX_POWER_CONSTANT / BQ27XXX_RS;
 	else
-		ae = ae * 29200 / BQ27XXX_RS;
+		ae *= 1000;
 
 	return ae;
 }
@@ -364,13 +549,13 @@ static int bq27xxx_battery_read_temperature(struct bq27xxx_device_info *di)
 {
 	int temp;
 
-	temp = bq27xxx_read(di, BQ27x00_REG_TEMP, false);
+	temp = bq27xxx_read(di, BQ27XXX_REG_TEMP, false);
 	if (temp < 0) {
 		dev_err(di->dev, "error reading temperature\n");
 		return temp;
 	}
 
-	if (!bq27xxx_is_chip_version_higher(di))
+	if (di->chip == BQ27000 || di->chip == BQ27010)
 		temp = 5 * temp / 2;
 
 	return temp;
@@ -384,10 +569,7 @@ static int bq27xxx_battery_read_cyct(struct bq27xxx_device_info *di)
 {
 	int cyct;
 
-	if (di->chip == BQ27510)
-		cyct = bq27xxx_read(di, BQ27510_REG_CYCT, false);
-	else
-		cyct = bq27xxx_read(di, BQ27x00_REG_CYCT, false);
+	cyct = bq27xxx_read(di, BQ27XXX_REG_CYCT, false);
 	if (cyct < 0)
 		dev_err(di->dev, "error reading cycle count total\n");
 
@@ -419,21 +601,32 @@ static int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, u8 reg)
  * Read an average power register.
  * Return < 0 if something fails.
  */
-static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di, u8 reg)
+static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di)
 {
 	int tval;
 
-	tval = bq27xxx_read(di, reg, false);
+	tval = bq27xxx_read(di, BQ27XXX_REG_AP, false);
 	if (tval < 0) {
-		dev_err(di->dev, "error reading power avg rgister  %02x: %d\n",
-			reg, tval);
+		dev_err(di->dev, "error reading average power register  %02x: %d\n",
+			BQ27XXX_REG_AP, tval);
 		return tval;
 	}
 
-	if (di->chip == BQ27500)
+	if (di->chip == BQ27000 || di->chip == BQ27010)
+		return (tval * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS;
+	else
 		return tval;
+}
+
+/*
+ * Returns true if a battery over temperature condition is detected
+ */
+static int bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags)
+{
+	if (di->chip == BQ27500 || di->chip == BQ27541)
+		return flags & (BQ27XXX_FLAG_OTC | BQ27XXX_FLAG_OTD);
 	else
-		return (tval * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS;
+		return flags & BQ27XXX_FLAG_OTC;
 }
 
 /*
@@ -442,53 +635,43 @@ static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di, u8 reg)
  */
 static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
 {
-	int tval;
+	u16 tval;
 
-	tval = bq27xxx_read(di, BQ27x00_REG_FLAGS, false);
+	tval = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
 	if (tval < 0) {
 		dev_err(di->dev, "error reading flag register:%d\n", tval);
 		return tval;
 	}
 
-	if (di->chip == BQ27500) {
-		if (tval & BQ27500_FLAG_SOCF)
+	if (di->chip == BQ27000 || di->chip == BQ27010) {
+		if (tval & BQ27000_FLAG_EDV1)
 			tval = POWER_SUPPLY_HEALTH_DEAD;
-		else if (tval & BQ27500_FLAG_OTC)
-			tval = POWER_SUPPLY_HEALTH_OVERHEAT;
 		else
 			tval = POWER_SUPPLY_HEALTH_GOOD;
-		return tval;
-	} else if (di->chip == BQ27510) {
-		if (tval & BQ27500_FLAG_OTC)
-			return POWER_SUPPLY_HEALTH_OVERHEAT;
-		return POWER_SUPPLY_HEALTH_GOOD;
 	} else {
-		if (tval & BQ27000_FLAG_EDV1)
+		if (tval & BQ27XXX_FLAG_SOCF)
 			tval = POWER_SUPPLY_HEALTH_DEAD;
+		else if (bq27xxx_battery_overtemp(di, tval))
+			tval = POWER_SUPPLY_HEALTH_OVERHEAT;
 		else
 			tval = POWER_SUPPLY_HEALTH_GOOD;
-		return tval;
 	}
 
-	return -1;
+	return tval;
 }
 
 static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
 {
 	struct bq27xxx_reg_cache cache = {0, };
-	bool is_bq27500 = di->chip == BQ27500;
-	bool is_bq27510 = di->chip == BQ27510;
-	bool is_bq27425 = di->chip == BQ27425;
-	bool is_bq27742 = di->chip == BQ27742;
-	bool flags_1b = !(is_bq27500 || is_bq27742);
+	bool has_ci_flag = di->chip == BQ27000 || di->chip == BQ27010;
+	bool has_singe_flag = di->chip == BQ27000 || di->chip == BQ27010;
 
-	cache.flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, flags_1b);
+	cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
 	if ((cache.flags & 0xff) == 0xff)
-		/* read error */
-		cache.flags = -1;
+		cache.flags = -1; /* read error */
 	if (cache.flags >= 0) {
-		if (!is_bq27500 && !is_bq27425 && !is_bq27742 && !is_bq27510
-				&& (cache.flags & BQ27000_FLAG_CI)) {
+		cache.temperature = bq27xxx_battery_read_temperature(di);
+		if (has_ci_flag && (cache.flags & BQ27000_FLAG_CI)) {
 			dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
 			cache.capacity = -ENODATA;
 			cache.energy = -ENODATA;
@@ -498,41 +681,26 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
 			cache.charge_full = -ENODATA;
 			cache.health = -ENODATA;
 		} else {
+			if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
+				cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
+			if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
+				cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
+			if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
+				cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
+			cache.charge_full = bq27xxx_battery_read_fcc(di);
 			cache.capacity = bq27xxx_battery_read_soc(di);
-			if (is_bq27742 || is_bq27510)
-				cache.time_to_empty =
-					bq27xxx_battery_read_time(di,
-							BQ27x00_REG_TTE);
-			else if (!is_bq27425) {
+			if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
 				cache.energy = bq27xxx_battery_read_energy(di);
-				cache.time_to_empty =
-					bq27xxx_battery_read_time(di,
-							BQ27x00_REG_TTE);
-				cache.time_to_empty_avg =
-					bq27xxx_battery_read_time(di,
-							BQ27x00_REG_TTECP);
-				cache.time_to_full =
-					bq27xxx_battery_read_time(di,
-							BQ27x00_REG_TTF);
-			}
-			cache.charge_full = bq27xxx_battery_read_lmd(di);
 			cache.health = bq27xxx_battery_read_health(di);
 		}
-		cache.temperature = bq27xxx_battery_read_temperature(di);
-		if (!is_bq27425)
+		if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
 			cache.cycle_count = bq27xxx_battery_read_cyct(di);
-		if (is_bq27742)
-			cache.power_avg =
-				bq27xxx_battery_read_pwr_avg(di,
-						BQ27742_POWER_AVG);
-		else
-			cache.power_avg =
-				bq27xxx_battery_read_pwr_avg(di,
-						BQ27x00_POWER_AVG);
+		if (di->regs[BQ27XXX_REG_AP] != INVALID_REG_ADDR)
+			cache.power_avg = bq27xxx_battery_read_pwr_avg(di);
 
 		/* We only have to read charge design full once */
 		if (di->charge_design_full <= 0)
-			di->charge_design_full = bq27xxx_battery_read_ilmd(di);
+			di->charge_design_full = bq27xxx_battery_read_dcap(di);
 	}
 
 	if (di->cache.capacity != cache.capacity)
@@ -547,7 +715,8 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
 static void bq27xxx_battery_poll(struct work_struct *work)
 {
 	struct bq27xxx_device_info *di =
-		container_of(work, struct bq27xxx_device_info, work.work);
+			container_of(work, struct bq27xxx_device_info,
+				     work.work);
 
 	bq27xxx_battery_update(di);
 
@@ -569,23 +738,23 @@ static int bq27xxx_battery_current(struct bq27xxx_device_info *di,
 	int curr;
 	int flags;
 
-	curr = bq27xxx_read(di, BQ27x00_REG_AI, false);
+	curr = bq27xxx_read(di, BQ27XXX_REG_AI, false);
 	if (curr < 0) {
 		dev_err(di->dev, "error reading current\n");
 		return curr;
 	}
 
-	if (bq27xxx_is_chip_version_higher(di)) {
-		/* bq27500 returns signed value */
-		val->intval = (int)((s16)curr) * 1000;
-	} else {
-		flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, false);
+	if (di->chip == BQ27000 || di->chip == BQ27010) {
+		flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
 		if (flags & BQ27000_FLAG_CHGS) {
 			dev_dbg(di->dev, "negative current!\n");
 			curr = -curr;
 		}
 
-		val->intval = curr * 3570 / BQ27XXX_RS;
+		val->intval = curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
+	} else {
+		/* Other gauges return signed value */
+		val->intval = (int)((s16)curr) * 1000;
 	}
 
 	return 0;
@@ -596,14 +765,7 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
 {
 	int status;
 
-	if (bq27xxx_is_chip_version_higher(di)) {
-		if (di->cache.flags & BQ27500_FLAG_FC)
-			status = POWER_SUPPLY_STATUS_FULL;
-		else if (di->cache.flags & BQ27500_FLAG_DSC)
-			status = POWER_SUPPLY_STATUS_DISCHARGING;
-		else
-			status = POWER_SUPPLY_STATUS_CHARGING;
-	} else {
+	if (di->chip == BQ27000 || di->chip == BQ27010) {
 		if (di->cache.flags & BQ27000_FLAG_FC)
 			status = POWER_SUPPLY_STATUS_FULL;
 		else if (di->cache.flags & BQ27000_FLAG_CHGS)
@@ -612,6 +774,13 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
 			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
 		else
 			status = POWER_SUPPLY_STATUS_DISCHARGING;
+	} else {
+		if (di->cache.flags & BQ27XXX_FLAG_FC)
+			status = POWER_SUPPLY_STATUS_FULL;
+		else if (di->cache.flags & BQ27XXX_FLAG_DSC)
+			status = POWER_SUPPLY_STATUS_DISCHARGING;
+		else
+			status = POWER_SUPPLY_STATUS_CHARGING;
 	}
 
 	val->intval = status;
@@ -624,21 +793,21 @@ static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di,
 {
 	int level;
 
-	if (bq27xxx_is_chip_version_higher(di)) {
-		if (di->cache.flags & BQ27500_FLAG_FC)
+	if (di->chip == BQ27000 || di->chip == BQ27010) {
+		if (di->cache.flags & BQ27000_FLAG_FC)
 			level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
-		else if (di->cache.flags & BQ27500_FLAG_SOC1)
+		else if (di->cache.flags & BQ27000_FLAG_EDV1)
 			level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
-		else if (di->cache.flags & BQ27500_FLAG_SOCF)
+		else if (di->cache.flags & BQ27000_FLAG_EDVF)
 			level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
 		else
 			level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
 	} else {
-		if (di->cache.flags & BQ27000_FLAG_FC)
+		if (di->cache.flags & BQ27XXX_FLAG_FC)
 			level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
-		else if (di->cache.flags & BQ27000_FLAG_EDV1)
+		else if (di->cache.flags & BQ27XXX_FLAG_SOC1)
 			level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
-		else if (di->cache.flags & BQ27000_FLAG_EDVF)
+		else if (di->cache.flags & BQ27XXX_FLAG_SOCF)
 			level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
 		else
 			level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
@@ -658,7 +827,7 @@ static int bq27xxx_battery_voltage(struct bq27xxx_device_info *di,
 {
 	int volt;
 
-	volt = bq27xxx_read(di, BQ27x00_REG_VOLT, false);
+	volt = bq27xxx_read(di, BQ27XXX_REG_VOLT, false);
 	if (volt < 0) {
 		dev_err(di->dev, "error reading voltage\n");
 		return volt;
@@ -719,7 +888,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_TEMP:
 		ret = bq27xxx_simple_value(di->cache.temperature, val);
 		if (ret == 0)
-			val->intval -= 2731;
+			val->intval -= 2731; /* convert decidegree k to c */
 		break;
 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
 		ret = bq27xxx_simple_value(di->cache.time_to_empty, val);
@@ -785,18 +954,27 @@ static int bq27xxx_powersupply_init(struct bq27xxx_device_info *di,
 
 	psy_desc->name = name;
 	psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
-	if (di->chip == BQ27425) {
-		psy_desc->properties = bq27425_battery_props;
-		psy_desc->num_properties = ARRAY_SIZE(bq27425_battery_props);
-	} else if (di->chip == BQ27742) {
-		psy_desc->properties = bq27742_battery_props;
-		psy_desc->num_properties = ARRAY_SIZE(bq27742_battery_props);
-	} else if (di->chip == BQ27510) {
-		psy_desc->properties = bq27510_battery_props;
-		psy_desc->num_properties = ARRAY_SIZE(bq27510_battery_props);
+	if (di->chip == BQ27000) {
+		psy_desc->properties = bq27000_battery_props;
+		psy_desc->num_properties = ARRAY_SIZE(bq27000_battery_props);
+	} else if (di->chip == BQ27010) {
+		psy_desc->properties = bq27010_battery_props;
+		psy_desc->num_properties = ARRAY_SIZE(bq27010_battery_props);
+	} else if (di->chip == BQ27500) {
+		psy_desc->properties = bq27500_battery_props;
+		psy_desc->num_properties = ARRAY_SIZE(bq27500_battery_props);
+	} else if (di->chip == BQ27530) {
+		psy_desc->properties = bq27530_battery_props;
+		psy_desc->num_properties = ARRAY_SIZE(bq27530_battery_props);
+	} else if (di->chip == BQ27541) {
+		psy_desc->properties = bq27541_battery_props;
+		psy_desc->num_properties = ARRAY_SIZE(bq27541_battery_props);
+	} else if (di->chip == BQ27545) {
+		psy_desc->properties = bq27545_battery_props;
+		psy_desc->num_properties = ARRAY_SIZE(bq27545_battery_props);
 	} else {
-		psy_desc->properties = bq27x00_battery_props;
-		psy_desc->num_properties = ARRAY_SIZE(bq27x00_battery_props);
+		psy_desc->properties = bq27421_battery_props;
+		psy_desc->num_properties = ARRAY_SIZE(bq27421_battery_props);
 	}
 	psy_desc->get_property = bq27xxx_battery_get_property;
 	psy_desc->external_power_changed = bq27xxx_external_power_changed;
@@ -911,10 +1089,32 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
 	di->chip = id->driver_data;
 	di->bus.read = &bq27xxx_battery_i2c_read;
 
+	if (di->chip == BQ27000) {
+		di->regs = bq27000_regs;
+	} else if (di->chip == BQ27010) {
+		di->regs = bq27010_regs;
+	} else if (di->chip == BQ27500) {
+		di->regs = bq27500_regs;
+	} else if (di->chip == BQ27530) {
+		di->regs = bq27530_regs;
+	} else if (di->chip == BQ27541) {
+		di->regs = bq27541_regs;
+	} else if (di->chip == BQ27545) {
+		di->regs = bq27545_regs;
+	} else if (di->chip == BQ27421) {
+		di->regs = bq27421_regs;
+	} else {
+		dev_err(&client->dev, "Unexpected gas gauge: %d\n", di->chip);
+		di->regs = bq27000_regs;
+	}
+
 	retval = bq27xxx_powersupply_init(di, name);
 	if (retval)
 		goto batt_failed;
 
+	/* Schedule a polling after about 1 min */
+	schedule_delayed_work(&di->work, 60 * HZ);
+
 	i2c_set_clientdata(client, di);
 
 	return 0;
@@ -941,11 +1141,22 @@ static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id bq27xxx_id[] = {
-	{ "bq27200", BQ27000 },	/* bq27200 is same as bq27000, but with i2c */
+	{ "bq27200", BQ27000 },
+	{ "bq27210", BQ27010 },
 	{ "bq27500", BQ27500 },
-	{ "bq27425", BQ27425 },
-	{ "bq27742", BQ27742 },
-	{ "bq27510", BQ27510 },
+	{ "bq27510", BQ27500 },
+	{ "bq27520", BQ27500 },
+	{ "bq27530", BQ27530 },
+	{ "bq27531", BQ27530 },
+	{ "bq27541", BQ27541 },
+	{ "bq27542", BQ27541 },
+	{ "bq27546", BQ27541 },
+	{ "bq27742", BQ27541 },
+	{ "bq27545", BQ27545 },
+	{ "bq27421", BQ27421 },
+	{ "bq27425", BQ27421 },
+	{ "bq27441", BQ27421 },
+	{ "bq27621", BQ27421 },
 	{},
 };
 MODULE_DEVICE_TABLE(i2c, bq27xxx_id);
diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
index a4efb10..45f6a7b 100644
--- a/include/linux/power/bq27xxx_battery.h
+++ b/include/linux/power/bq27xxx_battery.h
@@ -12,7 +12,15 @@
  *	register to be read. The return value should either be the content of
  *	the passed register or an error value.
  */
-enum bq27xxx_chip { BQ27000 = 1, BQ27500, BQ27425, BQ27742, BQ27510 };
+enum bq27xxx_chip {
+	BQ27000 = 1, /* bq27000, bq27200 */
+	BQ27010, /* bq27010, bq27210 */
+	BQ27500, /* bq27500, bq27510, bq27520 */
+	BQ27530, /* bq27530, bq27531 */
+	BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
+	BQ27545, /* bq27545 */
+	BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
+};
 
 struct bq27xxx_platform_data {
 	const char *name;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 6/6] power: bq27xxx_battery: Cleanup health checking
  2015-08-05 16:05 [PATCH v3 0/6] Add support for additional bq27xxx devices Andrew F. Davis
                   ` (4 preceding siblings ...)
  2015-08-05 16:05 ` [PATCH v3 5/6] power: bq27xxx_battery: Add support for additional bq27xxx family devices Andrew F. Davis
@ 2015-08-05 16:05 ` Andrew F. Davis
  5 siblings, 0 replies; 9+ messages in thread
From: Andrew F. Davis @ 2015-08-05 16:05 UTC (permalink / raw)
  To: Pali Rohár, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, Dan Murphy
  Cc: linux-pm, linux-kernel, Andrew F. Davis

Reorganize the logic checking battery health and add under temperature
condition checking.

Signed-off-by: Andrew F. Davis <afd@ti.com>
Acked-by: Pali Rohár <pali.rohar@gmail.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
 drivers/power/bq27xxx_battery.c | 64 +++++++++++++++++++++++++++--------------
 1 file changed, 42 insertions(+), 22 deletions(-)

diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c
index 3098609..ef5b9a3 100644
--- a/drivers/power/bq27xxx_battery.c
+++ b/drivers/power/bq27xxx_battery.c
@@ -63,6 +63,8 @@
 #define BQ27XXX_FLAG_FC		BIT(9)
 #define BQ27XXX_FLAG_OTD	BIT(14)
 #define BQ27XXX_FLAG_OTC	BIT(15)
+#define BQ27XXX_FLAG_UT		BIT(14)
+#define BQ27XXX_FLAG_OT		BIT(15)
 
 /* BQ27000 has different layout for Flags register */
 #define BQ27000_FLAG_EDVF	BIT(0) /* Final End-of-Discharge-Voltage flag */
@@ -621,12 +623,36 @@ static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di)
 /*
  * Returns true if a battery over temperature condition is detected
  */
-static int bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags)
+static bool bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags)
 {
-	if (di->chip == BQ27500 || di->chip == BQ27541)
+	if (di->chip == BQ27500 || di->chip == BQ27541 || di->chip == BQ27545)
 		return flags & (BQ27XXX_FLAG_OTC | BQ27XXX_FLAG_OTD);
+	if (di->chip == BQ27530 || di->chip == BQ27421)
+		return flags & BQ27XXX_FLAG_OT;
+
+	return false;
+}
+
+/*
+ * Returns true if a battery under temperature condition is detected
+ */
+static bool bq27xxx_battery_undertemp(struct bq27xxx_device_info *di, u16 flags)
+{
+	if (di->chip == BQ27530 || di->chip == BQ27421)
+			return flags & BQ27XXX_FLAG_UT;
+
+	return false;
+}
+
+/*
+ * Returns true if a low state of charge condition is detected
+ */
+static bool bq27xxx_battery_dead(struct bq27xxx_device_info *di, u16 flags)
+{
+	if (di->chip == BQ27000 || di->chip == BQ27010)
+		return flags & (BQ27000_FLAG_EDV1 | BQ27000_FLAG_EDVF);
 	else
-		return flags & BQ27XXX_FLAG_OTC;
+		return flags & (BQ27XXX_FLAG_SOC1 | BQ27XXX_FLAG_SOCF);
 }
 
 /*
@@ -635,29 +661,23 @@ static int bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags)
  */
 static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
 {
-	u16 tval;
+	u16 flags;
 
-	tval = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
-	if (tval < 0) {
-		dev_err(di->dev, "error reading flag register:%d\n", tval);
-		return tval;
+	flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
+	if (flags < 0) {
+		dev_err(di->dev, "error reading flag register:%d\n", flags);
+		return flags;
 	}
 
-	if (di->chip == BQ27000 || di->chip == BQ27010) {
-		if (tval & BQ27000_FLAG_EDV1)
-			tval = POWER_SUPPLY_HEALTH_DEAD;
-		else
-			tval = POWER_SUPPLY_HEALTH_GOOD;
-	} else {
-		if (tval & BQ27XXX_FLAG_SOCF)
-			tval = POWER_SUPPLY_HEALTH_DEAD;
-		else if (bq27xxx_battery_overtemp(di, tval))
-			tval = POWER_SUPPLY_HEALTH_OVERHEAT;
-		else
-			tval = POWER_SUPPLY_HEALTH_GOOD;
-	}
+	/* Unlikely but important to return first */
+	if (unlikely(bq27xxx_battery_overtemp(di, flags)))
+		return POWER_SUPPLY_HEALTH_OVERHEAT;
+	if (unlikely(bq27xxx_battery_undertemp(di, flags)))
+		return POWER_SUPPLY_HEALTH_COLD;
+	if (unlikely(bq27xxx_battery_dead(di, flags)))
+		return POWER_SUPPLY_HEALTH_DEAD;
 
-	return tval;
+	return POWER_SUPPLY_HEALTH_GOOD;
 }
 
 static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 5/6] power: bq27xxx_battery: Add support for additional bq27xxx family devices
  2015-08-05 16:05 ` [PATCH v3 5/6] power: bq27xxx_battery: Add support for additional bq27xxx family devices Andrew F. Davis
@ 2015-08-06  8:28   ` Pali Rohár
  2015-08-07 15:08     ` Andrew F. Davis
  0 siblings, 1 reply; 9+ messages in thread
From: Pali Rohár @ 2015-08-06  8:28 UTC (permalink / raw)
  To: Andrew F. Davis
  Cc: Sebastian Reichel, Dmitry Eremin-Solenikov, David Woodhouse,
	Dan Murphy, linux-pm, linux-kernel

On Wednesday 05 August 2015 11:05:39 Andrew F. Davis wrote:
> Add support for additional devices and register equivalent family devices
> including the bq27010, bq27210, bq27500, bq27510, bq27520, bq27530,
> bq27531, bq27541, bq27542, bq27546, bq27545, bq27441, bq27421, and the
> bq27641.
> 
> To facilitate this process the register mapings have been moved to tables
> and other small cleanups have been made.
> 
> Signed-off-by: Andrew F. Davis <afd@ti.com>
> ---
>  drivers/power/bq27xxx_battery.c       | 627 +++++++++++++++++++++++-----------
>  include/linux/power/bq27xxx_battery.h |  10 +-
>  2 files changed, 428 insertions(+), 209 deletions(-)
> 
> diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c
> index 1ff88ad..3098609 100644
> --- a/drivers/power/bq27xxx_battery.c
> +++ b/drivers/power/bq27xxx_battery.c
> @@ -17,11 +17,24 @@
>   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
>   *
>   * Datasheets:
> - * http://focus.ti.com/docs/prod/folders/print/bq27000.html
> - * http://focus.ti.com/docs/prod/folders/print/bq27500.html
> + * http://www.ti.com/product/bq27000
> + * http://www.ti.com/product/bq27200
> + * http://www.ti.com/product/bq27010
> + * http://www.ti.com/product/bq27210
> + * http://www.ti.com/product/bq27500
> + * http://www.ti.com/product/bq27510-g3
> + * http://www.ti.com/product/bq27520-g4
> + * http://www.ti.com/product/bq27530-g1
> + * http://www.ti.com/product/bq27531-g1
> + * http://www.ti.com/product/bq27541-g1
> + * http://www.ti.com/product/bq27542-g1
> + * http://www.ti.com/product/bq27546-g1
> + * http://www.ti.com/product/bq27742-g1
> + * http://www.ti.com/product/bq27545-g1
> + * http://www.ti.com/product/bq27421-g1
>   * http://www.ti.com/product/bq27425-g1
> - * http://www.ti.com/product/BQ27742-G1
> - * http://www.ti.com/product/BQ27510-G3
> + * http://www.ti.com/product/bq27411-g1
> + * http://www.ti.com/product/bq27621-g1
>   */
>  
>  #include <linux/device.h>
> @@ -43,54 +56,57 @@
>  
>  #define BQ27XXX_MANUFACTURER	"Texas Instruments"
>  
> -#define BQ27x00_REG_TEMP	0x06
> -#define BQ27x00_REG_VOLT	0x08
> -#define BQ27x00_REG_AI		0x14
> -#define BQ27x00_REG_FLAGS	0x0A
> -#define BQ27x00_REG_TTE		0x16
> -#define BQ27x00_REG_TTF		0x18
> -#define BQ27x00_REG_TTECP	0x26
> -#define BQ27x00_REG_NAC		0x0C /* Nominal available capacity */
> -#define BQ27x00_REG_LMD		0x12 /* Last measured discharge */
> -#define BQ27x00_REG_CYCT	0x2A /* Cycle count total */
> -#define BQ27x00_REG_AE		0x22 /* Available energy */
> -#define BQ27x00_POWER_AVG	0x24
> -
> -#define BQ27000_REG_RSOC	0x0B /* Relative State-of-Charge */
> -#define BQ27000_REG_ILMD	0x76 /* Initial last measured discharge */
> +/* BQ27XXX Flags */
> +#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_FC		BIT(9)
> +#define BQ27XXX_FLAG_OTD	BIT(14)
> +#define BQ27XXX_FLAG_OTC	BIT(15)
> +
> +/* BQ27000 has different layout for Flags register */
>  #define BQ27000_FLAG_EDVF	BIT(0) /* Final End-of-Discharge-Voltage flag */
>  #define BQ27000_FLAG_EDV1	BIT(1) /* First End-of-Discharge-Voltage flag */
>  #define BQ27000_FLAG_CI		BIT(4) /* Capacity Inaccurate flag */
>  #define BQ27000_FLAG_FC		BIT(5)
>  #define BQ27000_FLAG_CHGS	BIT(7) /* Charge state flag */
>  
> -#define BQ27500_REG_SOC		0x2C
> -#define BQ27500_REG_DCAP	0x3C /* Design capacity */
> -#define BQ27500_FLAG_DSC	BIT(0)
> -#define BQ27500_FLAG_SOCF	BIT(1) /* State-of-Charge threshold final */
> -#define BQ27500_FLAG_SOC1	BIT(2) /* State-of-Charge threshold 1 */
> -#define BQ27500_FLAG_FC		BIT(9)
> -#define BQ27500_FLAG_OTC	BIT(15)
> -
> -#define BQ27742_POWER_AVG	0x76
> -
> -#define BQ27510_REG_SOC		0x20
> -#define BQ27510_REG_DCAP	0x2E /* Design capacity */
> -#define BQ27510_REG_CYCT	0x1E /* Cycle count total */
> -
> -/* bq27425 register addresses are same as bq27x00 addresses minus 4 */
> -#define BQ27425_REG_OFFSET	0x04
> -#define BQ27425_REG_SOC		(0x1C + BQ27425_REG_OFFSET)
> -#define BQ27425_REG_DCAP	(0x3C + BQ27425_REG_OFFSET)
> -
> -#define BQ27XXX_RS			20 /* Resistor sense */
> -#define BQ27XXX_POWER_CONSTANT		(256 * 29200 / 1000)
> +#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 */
>  
>  struct bq27xxx_device_info;
>  struct bq27xxx_access_methods {
>  	int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single);
>  };
>  
> +#define INVALID_REG_ADDR	0xff
> +
> +/*
> + * bq27xxx_reg_index - Register names
> + *
> + * These are indexes into a device's register mapping array.
> + */
> +enum bq27xxx_reg_index {
> +	BQ27XXX_REG_CTRL = 0,	/* Control */
> +	BQ27XXX_REG_TEMP,	/* Temperature */
> +	BQ27XXX_REG_INT_TEMP,	/* Internal Temperature */
> +	BQ27XXX_REG_VOLT,	/* Voltage */
> +	BQ27XXX_REG_AI,		/* Average Current */
> +	BQ27XXX_REG_FLAGS,	/* Flags */
> +	BQ27XXX_REG_TTE,	/* Time-to-Empty */
> +	BQ27XXX_REG_TTF,	/* Time-to-Full */
> +	BQ27XXX_REG_TTES,	/* Time-to-Empty Standby */
> +	BQ27XXX_REG_TTECP,	/* Time-to-Empty at Constant Power */
> +	BQ27XXX_REG_NAC,	/* Nominal Available Capacity */
> +	BQ27XXX_REG_FCC,	/* Full Charge Capacity */
> +	BQ27XXX_REG_CYCT,	/* Cycle Count */
> +	BQ27XXX_REG_AE,		/* Available Energy */
> +	BQ27XXX_REG_SOC,	/* State-of-Charge */
> +	BQ27XXX_REG_DCAP,	/* Design Capacity */
> +	BQ27XXX_REG_AP,		/* Average Power */
> +};
> +
>  struct bq27xxx_reg_cache {
>  	int temperature;
>  	int time_to_empty;
> @@ -121,9 +137,152 @@ struct bq27xxx_device_info {
>  	struct bq27xxx_access_methods bus;
>  
>  	struct mutex lock;
> +
> +	u8 *regs;
> +};
> +
> +/* Register mappings */
> +static u8 bq27000_regs[] = {
> +	0x00,	/* CONTROL	*/
> +	0x06,	/* TEMP		*/
> +	INVALID_REG_ADDR,	/* INT TEMP - NA*/
> +	0x08,	/* VOLT		*/
> +	0x14,	/* AVG CURR	*/
> +	0x0a,	/* FLAGS	*/
> +	0x16,	/* TTE		*/
> +	0x18,	/* TTF		*/
> +	0x1c,	/* TTES		*/
> +	0x26,	/* TTECP	*/
> +	0x0c,	/* NAC		*/
> +	0x12,	/* LMD(FCC)	*/
> +	0x2a,	/* CYCT		*/
> +	0x22,	/* AE		*/
> +	0x0b,	/* SOC(RSOC)	*/
> +	0x76,	/* DCAP(ILMD)	*/
> +	0x24,	/* AP		*/
> +};
> +
> +static u8 bq27010_regs[] = {
> +	0x00,	/* CONTROL	*/
> +	0x06,	/* TEMP		*/
> +	INVALID_REG_ADDR,	/* INT TEMP - NA*/
> +	0x08,	/* VOLT		*/
> +	0x14,	/* AVG CURR	*/
> +	0x0a,	/* FLAGS	*/
> +	0x16,	/* TTE		*/
> +	0x18,	/* TTF		*/
> +	0x1c,	/* TTES		*/
> +	0x26,	/* TTECP	*/
> +	0x0c,	/* NAC		*/
> +	0x12,	/* LMD(FCC)	*/
> +	0x2a,	/* CYCT		*/
> +	INVALID_REG_ADDR,	/* AE - NA	*/
> +	0x0b,	/* SOC(RSOC)	*/
> +	0x76,	/* DCAP(ILMD)	*/
> +	INVALID_REG_ADDR,	/* AP - NA	*/
> +};
> +
> +static u8 bq27500_regs[] = {
> +	0x00,	/* CONTROL	*/
> +	0x06,	/* TEMP		*/
> +	0x28,	/* INT TEMP	*/
> +	0x08,	/* VOLT		*/
> +	0x14,	/* AVG CURR	*/
> +	0x0a,	/* FLAGS	*/
> +	0x16,	/* TTE		*/
> +	INVALID_REG_ADDR,	/* TTF - NA	*/
> +	0x1a,	/* TTES		*/
> +	INVALID_REG_ADDR,	/* TTECP - NA	*/
> +	0x0c,	/* NAC		*/
> +	0x12,	/* LMD(FCC)	*/
> +	0x1e,	/* CYCT		*/
> +	INVALID_REG_ADDR,	/* AE - NA	*/
> +	0x20,	/* SOC(RSOC)	*/
> +	0x2e,	/* DCAP(ILMD)	*/
> +	INVALID_REG_ADDR,	/* AP - NA	*/
>  };
>  
> -static enum power_supply_property bq27x00_battery_props[] = {
> +static u8 bq27530_regs[] = {
> +	0x00,	/* CONTROL	*/
> +	0x06,	/* TEMP		*/
> +	0x32,	/* INT TEMP	*/
> +	0x08,	/* VOLT		*/
> +	0x14,	/* AVG CURR	*/
> +	0x0a,	/* FLAGS	*/
> +	0x16,	/* TTE		*/
> +	INVALID_REG_ADDR,	/* TTF - NA	*/
> +	INVALID_REG_ADDR,	/* TTES - NA	*/
> +	INVALID_REG_ADDR,	/* TTECP - NA	*/
> +	0x0c,	/* NAC		*/
> +	0x12,	/* LMD(FCC)	*/
> +	0x2a,	/* CYCT		*/
> +	INVALID_REG_ADDR,	/* AE - NA	*/
> +	0x2c,	/* SOC(RSOC)	*/
> +	INVALID_REG_ADDR,	/* DCAP - NA	*/
> +	0x24,	/* AP		*/
> +};
> +
> +static u8 bq27541_regs[] = {
> +	0x00,	/* CONTROL	*/
> +	0x06,	/* TEMP		*/
> +	0x28,	/* INT TEMP	*/
> +	0x08,	/* VOLT		*/
> +	0x14,	/* AVG CURR	*/
> +	0x0a,	/* FLAGS	*/
> +	0x16,	/* TTE		*/
> +	INVALID_REG_ADDR,	/* TTF - NA	*/
> +	INVALID_REG_ADDR,	/* TTES - NA	*/
> +	INVALID_REG_ADDR,	/* TTECP - NA	*/
> +	0x0c,	/* NAC		*/
> +	0x12,	/* LMD(FCC)	*/
> +	0x2a,	/* CYCT		*/
> +	INVALID_REG_ADDR,	/* AE - NA	*/
> +	0x2c,	/* SOC(RSOC)	*/
> +	0x3c,	/* DCAP		*/
> +	0x76,	/* AP		*/
> +};
> +
> +static u8 bq27545_regs[] = {
> +	0x00,	/* CONTROL	*/
> +	0x06,	/* TEMP		*/
> +	0x28,	/* INT TEMP	*/
> +	0x08,	/* VOLT		*/
> +	0x14,	/* AVG CURR	*/
> +	0x0a,	/* FLAGS	*/
> +	0x16,	/* TTE		*/
> +	INVALID_REG_ADDR,	/* TTF - NA	*/
> +	INVALID_REG_ADDR,	/* TTES - NA	*/
> +	INVALID_REG_ADDR,	/* TTECP - NA	*/
> +	0x0c,	/* NAC		*/
> +	0x12,	/* LMD(FCC)	*/
> +	0x2a,	/* CYCT		*/
> +	INVALID_REG_ADDR,	/* AE - NA	*/
> +	0x2c,	/* SOC(RSOC)	*/
> +	INVALID_REG_ADDR,	/* DCAP - NA */
> +	0x24,	/* AP		*/
> +};
> +
> +static u8 bq27421_regs[] = {
> +	0x00,	/* CONTROL	*/
> +	0x02,	/* TEMP		*/
> +	0x1e,	/* INT TEMP	*/
> +	0x04,	/* VOLT		*/
> +	0x10,	/* AVG CURR	*/
> +	0x06,	/* FLAGS	*/
> +	INVALID_REG_ADDR,	/* TTE - NA	*/
> +	INVALID_REG_ADDR,	/* TTF - NA	*/
> +	INVALID_REG_ADDR,	/* TTES - NA	*/
> +	INVALID_REG_ADDR,	/* TTECP - NA	*/
> +	0x08,	/* NAC		*/
> +	0x0e,	/* FCC		*/
> +	INVALID_REG_ADDR,	/* CYCT - NA	*/
> +	INVALID_REG_ADDR,	/* AE - NA	*/
> +	0x1c,	/* SOC		*/
> +	0x3c,	/* DCAP		*/
> +	0x18,	/* AP		*/
> +};
> +
> +static enum power_supply_property bq27000_battery_props[] = {
>  	POWER_SUPPLY_PROP_STATUS,
>  	POWER_SUPPLY_PROP_PRESENT,
>  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
> @@ -145,7 +304,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
>  	POWER_SUPPLY_PROP_MANUFACTURER,
>  };
>  
> -static enum power_supply_property bq27425_battery_props[] = {
> +static enum power_supply_property bq27010_battery_props[] = {
>  	POWER_SUPPLY_PROP_STATUS,
>  	POWER_SUPPLY_PROP_PRESENT,
>  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
> @@ -153,14 +312,19 @@ static enum power_supply_property bq27425_battery_props[] = {
>  	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_EMPTY_AVG,
> +	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_HEALTH,
>  	POWER_SUPPLY_PROP_MANUFACTURER,
>  };
>  
> -static enum power_supply_property bq27742_battery_props[] = {
> +static enum power_supply_property bq27500_battery_props[] = {
>  	POWER_SUPPLY_PROP_STATUS,
>  	POWER_SUPPLY_PROP_PRESENT,
>  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
> @@ -174,12 +338,29 @@ static enum power_supply_property bq27742_battery_props[] = {
>  	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 bq27530_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_POWER_AVG,
>  	POWER_SUPPLY_PROP_HEALTH,
> +	POWER_SUPPLY_PROP_CYCLE_COUNT,
>  	POWER_SUPPLY_PROP_MANUFACTURER,
>  };
>  
> -static enum power_supply_property bq27510_battery_props[] = {
> +static enum power_supply_property bq27541_battery_props[] = {
>  	POWER_SUPPLY_PROP_STATUS,
>  	POWER_SUPPLY_PROP_PRESENT,
>  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
> @@ -198,6 +379,39 @@ static enum power_supply_property bq27510_battery_props[] = {
>  	POWER_SUPPLY_PROP_MANUFACTURER,
>  };
>  
> +static enum power_supply_property bq27545_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_HEALTH,
> +	POWER_SUPPLY_PROP_CYCLE_COUNT,
> +	POWER_SUPPLY_PROP_POWER_AVG,
> +	POWER_SUPPLY_PROP_MANUFACTURER,
> +};
> +
> +static enum power_supply_property bq27421_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_TECHNOLOGY,
> +	POWER_SUPPLY_PROP_CHARGE_FULL,
> +	POWER_SUPPLY_PROP_CHARGE_NOW,
> +	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
> +	POWER_SUPPLY_PROP_MANUFACTURER,
> +};
> +
>  static unsigned int poll_interval = 360;
>  module_param(poll_interval, uint, 0644);
>  MODULE_PARM_DESC(poll_interval,
> @@ -207,25 +421,14 @@ MODULE_PARM_DESC(poll_interval,
>   * Common code for BQ27xxx devices
>   */
>  
> -static inline int bq27xxx_read(struct bq27xxx_device_info *di, u8 reg,
> +static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index,
>  			       bool single)
>  {
> -	if (di->chip == BQ27425)
> -		return di->bus.read(di, reg - BQ27425_REG_OFFSET, single);
> -	return di->bus.read(di, reg, single);
> -}
> +	/* Reports EINVAL for invalid/missing registers */
> +	if (!di || di->regs[reg_index] == INVALID_REG_ADDR)
> +		return -EINVAL;
>  
> -/*
> - * Higher versions of the chip like BQ27425 and BQ27500
> - * differ from BQ27000 and BQ27200 in calculation of certain
> - * parameters. Hence we need to check for the chip type.
> - */
> -static bool bq27xxx_is_chip_version_higher(struct bq27xxx_device_info *di)
> -{
> -	if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742
> -	    || di->chip == BQ27510)
> -		return true;
> -	return false;
> +	return di->bus.read(di, di->regs[reg_index], single);
>  }
>  
>  /*
> @@ -236,14 +439,7 @@ static int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di)
>  {
>  	int soc;
>  
> -	if (di->chip == BQ27500 || di->chip == BQ27742)
> -		soc = bq27xxx_read(di, BQ27500_REG_SOC, false);
> -	else if (di->chip == BQ27510)
> -		soc = bq27xxx_read(di, BQ27510_REG_SOC, false);
> -	else if (di->chip == BQ27425)
> -		soc = bq27xxx_read(di, BQ27425_REG_SOC, false);
> -	else /* for the bq27000 we read the "relative" SoC register */
> -		soc = bq27xxx_read(di, BQ27000_REG_RSOC, true);
> +	soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false);
>  
>  	if (soc < 0)
>  		dev_dbg(di->dev, "error reading State-of-Charge\n");
> @@ -266,10 +462,10 @@ static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg)
>  		return charge;
>  	}
>  
> -	if (bq27xxx_is_chip_version_higher(di))
> -		charge *= 1000;
> +	if (di->chip == BQ27000 || di->chip == BQ27010)
> +		charge *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
>  	else
> -		charge = charge * 3570 / BQ27XXX_RS;
> +		charge *= 1000;
>  
>  	return charge;
>  }
> @@ -281,57 +477,46 @@ static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg)
>  static inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di)
>  {
>  	int flags;
> -	bool is_bq27500 = di->chip == BQ27500;
> -	bool is_bq27742 = di->chip == BQ27742;
> -	bool is_higher = bq27xxx_is_chip_version_higher(di);
> -	bool flags_1b = !(is_bq27500 || is_bq27742);
>  
> -	flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, flags_1b);
> -	if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI))
> -		return -ENODATA;
> +	if (di->chip == BQ27000 || di->chip == BQ27010) {
> +		flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, true);
> +		if (flags >= 0 && (flags & BQ27000_FLAG_CI))
> +			return -ENODATA;
> +	}
>  
> -	return bq27xxx_battery_read_charge(di, BQ27x00_REG_NAC);
> +	return bq27xxx_battery_read_charge(di, BQ27XXX_REG_NAC);
>  }
>  
>  /*
> - * Return the battery Last measured discharge in µAh
> + * Return the battery Full Charge Capacity in µAh
>   * Or < 0 if something fails.
>   */
> -static inline int bq27xxx_battery_read_lmd(struct bq27xxx_device_info *di)
> +static inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di)
>  {
> -	return bq27xxx_battery_read_charge(di, BQ27x00_REG_LMD);
> +	return bq27xxx_battery_read_charge(di, BQ27XXX_REG_FCC);
>  }
>  
>  /*
> - * Return the battery Initial last measured discharge in µAh
> + * Return the Design Capacity in µAh
>   * Or < 0 if something fails.
>   */
> -static int bq27xxx_battery_read_ilmd(struct bq27xxx_device_info *di)
> +static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
>  {
> -	int ilmd;
> +	int dcap;
>  
> -	if (bq27xxx_is_chip_version_higher(di)) {
> -		if (di->chip == BQ27425)
> -			ilmd = bq27xxx_read(di, BQ27425_REG_DCAP, false);
> -		else if (di->chip == BQ27510)
> -			ilmd = bq27xxx_read(di, BQ27510_REG_DCAP, false);
> -		else
> -			ilmd = bq27xxx_read(di, BQ27500_REG_DCAP, false);
> -	} else {
> -		ilmd = bq27xxx_read(di, BQ27000_REG_ILMD, true);
> -	}
> +	dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
>  
> -	if (ilmd < 0) {
> +	if (dcap < 0) {
>  		dev_dbg(di->dev, "error reading initial last measured discharge\n");
> -		return ilmd;
> +		return dcap;
>  	}
>  
> -	if (bq27xxx_is_chip_version_higher(di))
> -		ilmd *= 1000;
> +	if (di->chip == BQ27000 || di->chip == BQ27010)
> +		dcap *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
>  	else
> -		ilmd = ilmd * 256 * 3570 / BQ27XXX_RS;
> +		dcap *= 1000;
>  
> -	return ilmd;
> +	return dcap;
>  }
>  
>  /*
> @@ -342,16 +527,16 @@ static int bq27xxx_battery_read_energy(struct bq27xxx_device_info *di)
>  {
>  	int ae;
>  
> -	ae = bq27xxx_read(di, BQ27x00_REG_AE, false);
> +	ae = bq27xxx_read(di, BQ27XXX_REG_AE, false);
>  	if (ae < 0) {
>  		dev_dbg(di->dev, "error reading available energy\n");
>  		return ae;
>  	}
>  
> -	if (di->chip == BQ27500)
> -		ae *= 1000;
> +	if (di->chip == BQ27000 || di->chip == BQ27010)
> +		ae *= BQ27XXX_POWER_CONSTANT / BQ27XXX_RS;
>  	else
> -		ae = ae * 29200 / BQ27XXX_RS;
> +		ae *= 1000;
>  
>  	return ae;
>  }
> @@ -364,13 +549,13 @@ static int bq27xxx_battery_read_temperature(struct bq27xxx_device_info *di)
>  {
>  	int temp;
>  
> -	temp = bq27xxx_read(di, BQ27x00_REG_TEMP, false);
> +	temp = bq27xxx_read(di, BQ27XXX_REG_TEMP, false);
>  	if (temp < 0) {
>  		dev_err(di->dev, "error reading temperature\n");
>  		return temp;
>  	}
>  
> -	if (!bq27xxx_is_chip_version_higher(di))
> +	if (di->chip == BQ27000 || di->chip == BQ27010)
>  		temp = 5 * temp / 2;
>  
>  	return temp;
> @@ -384,10 +569,7 @@ static int bq27xxx_battery_read_cyct(struct bq27xxx_device_info *di)
>  {
>  	int cyct;
>  
> -	if (di->chip == BQ27510)
> -		cyct = bq27xxx_read(di, BQ27510_REG_CYCT, false);
> -	else
> -		cyct = bq27xxx_read(di, BQ27x00_REG_CYCT, false);
> +	cyct = bq27xxx_read(di, BQ27XXX_REG_CYCT, false);
>  	if (cyct < 0)
>  		dev_err(di->dev, "error reading cycle count total\n");
>  
> @@ -419,21 +601,32 @@ static int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, u8 reg)
>   * Read an average power register.
>   * Return < 0 if something fails.
>   */
> -static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di, u8 reg)
> +static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di)
>  {
>  	int tval;
>  
> -	tval = bq27xxx_read(di, reg, false);
> +	tval = bq27xxx_read(di, BQ27XXX_REG_AP, false);
>  	if (tval < 0) {
> -		dev_err(di->dev, "error reading power avg rgister  %02x: %d\n",
> -			reg, tval);
> +		dev_err(di->dev, "error reading average power register  %02x: %d\n",
> +			BQ27XXX_REG_AP, tval);
>  		return tval;
>  	}
>  
> -	if (di->chip == BQ27500)
> +	if (di->chip == BQ27000 || di->chip == BQ27010)
> +		return (tval * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS;
> +	else
>  		return tval;
> +}
> +
> +/*
> + * Returns true if a battery over temperature condition is detected
> + */
> +static int bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags)
> +{
> +	if (di->chip == BQ27500 || di->chip == BQ27541)
> +		return flags & (BQ27XXX_FLAG_OTC | BQ27XXX_FLAG_OTD);
>  	else
> -		return (tval * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS;
> +		return flags & BQ27XXX_FLAG_OTC;
>  }
>  
>  /*
> @@ -442,53 +635,43 @@ static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di, u8 reg)
>   */
>  static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
>  {
> -	int tval;
> +	u16 tval;
>  
> -	tval = bq27xxx_read(di, BQ27x00_REG_FLAGS, false);
> +	tval = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
>  	if (tval < 0) {
>  		dev_err(di->dev, "error reading flag register:%d\n", tval);
>  		return tval;
>  	}
>  
> -	if (di->chip == BQ27500) {
> -		if (tval & BQ27500_FLAG_SOCF)
> +	if (di->chip == BQ27000 || di->chip == BQ27010) {
> +		if (tval & BQ27000_FLAG_EDV1)
>  			tval = POWER_SUPPLY_HEALTH_DEAD;
> -		else if (tval & BQ27500_FLAG_OTC)
> -			tval = POWER_SUPPLY_HEALTH_OVERHEAT;
>  		else
>  			tval = POWER_SUPPLY_HEALTH_GOOD;
> -		return tval;
> -	} else if (di->chip == BQ27510) {
> -		if (tval & BQ27500_FLAG_OTC)
> -			return POWER_SUPPLY_HEALTH_OVERHEAT;
> -		return POWER_SUPPLY_HEALTH_GOOD;
>  	} else {
> -		if (tval & BQ27000_FLAG_EDV1)
> +		if (tval & BQ27XXX_FLAG_SOCF)
>  			tval = POWER_SUPPLY_HEALTH_DEAD;
> +		else if (bq27xxx_battery_overtemp(di, tval))
> +			tval = POWER_SUPPLY_HEALTH_OVERHEAT;
>  		else
>  			tval = POWER_SUPPLY_HEALTH_GOOD;
> -		return tval;
>  	}
>  
> -	return -1;
> +	return tval;
>  }
>  
>  static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
>  {
>  	struct bq27xxx_reg_cache cache = {0, };
> -	bool is_bq27500 = di->chip == BQ27500;
> -	bool is_bq27510 = di->chip == BQ27510;
> -	bool is_bq27425 = di->chip == BQ27425;
> -	bool is_bq27742 = di->chip == BQ27742;
> -	bool flags_1b = !(is_bq27500 || is_bq27742);
> +	bool has_ci_flag = di->chip == BQ27000 || di->chip == BQ27010;
> +	bool has_singe_flag = di->chip == BQ27000 || di->chip == BQ27010;
>  
> -	cache.flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, flags_1b);
> +	cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
>  	if ((cache.flags & 0xff) == 0xff)
> -		/* read error */
> -		cache.flags = -1;
> +		cache.flags = -1; /* read error */
>  	if (cache.flags >= 0) {
> -		if (!is_bq27500 && !is_bq27425 && !is_bq27742 && !is_bq27510
> -				&& (cache.flags & BQ27000_FLAG_CI)) {
> +		cache.temperature = bq27xxx_battery_read_temperature(di);
> +		if (has_ci_flag && (cache.flags & BQ27000_FLAG_CI)) {
>  			dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
>  			cache.capacity = -ENODATA;
>  			cache.energy = -ENODATA;
> @@ -498,41 +681,26 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
>  			cache.charge_full = -ENODATA;
>  			cache.health = -ENODATA;
>  		} else {
> +			if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
> +				cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
> +			if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
> +				cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
> +			if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
> +				cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
> +			cache.charge_full = bq27xxx_battery_read_fcc(di);
>  			cache.capacity = bq27xxx_battery_read_soc(di);
> -			if (is_bq27742 || is_bq27510)
> -				cache.time_to_empty =
> -					bq27xxx_battery_read_time(di,
> -							BQ27x00_REG_TTE);
> -			else if (!is_bq27425) {
> +			if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
>  				cache.energy = bq27xxx_battery_read_energy(di);
> -				cache.time_to_empty =
> -					bq27xxx_battery_read_time(di,
> -							BQ27x00_REG_TTE);
> -				cache.time_to_empty_avg =
> -					bq27xxx_battery_read_time(di,
> -							BQ27x00_REG_TTECP);
> -				cache.time_to_full =
> -					bq27xxx_battery_read_time(di,
> -							BQ27x00_REG_TTF);
> -			}
> -			cache.charge_full = bq27xxx_battery_read_lmd(di);
>  			cache.health = bq27xxx_battery_read_health(di);
>  		}
> -		cache.temperature = bq27xxx_battery_read_temperature(di);
> -		if (!is_bq27425)
> +		if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
>  			cache.cycle_count = bq27xxx_battery_read_cyct(di);
> -		if (is_bq27742)
> -			cache.power_avg =
> -				bq27xxx_battery_read_pwr_avg(di,
> -						BQ27742_POWER_AVG);
> -		else
> -			cache.power_avg =
> -				bq27xxx_battery_read_pwr_avg(di,
> -						BQ27x00_POWER_AVG);
> +		if (di->regs[BQ27XXX_REG_AP] != INVALID_REG_ADDR)
> +			cache.power_avg = bq27xxx_battery_read_pwr_avg(di);
>  
>  		/* We only have to read charge design full once */
>  		if (di->charge_design_full <= 0)
> -			di->charge_design_full = bq27xxx_battery_read_ilmd(di);
> +			di->charge_design_full = bq27xxx_battery_read_dcap(di);
>  	}
>  
>  	if (di->cache.capacity != cache.capacity)
> @@ -547,7 +715,8 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
>  static void bq27xxx_battery_poll(struct work_struct *work)
>  {
>  	struct bq27xxx_device_info *di =
> -		container_of(work, struct bq27xxx_device_info, work.work);
> +			container_of(work, struct bq27xxx_device_info,
> +				     work.work);
>  
>  	bq27xxx_battery_update(di);
>  
> @@ -569,23 +738,23 @@ static int bq27xxx_battery_current(struct bq27xxx_device_info *di,
>  	int curr;
>  	int flags;
>  
> -	curr = bq27xxx_read(di, BQ27x00_REG_AI, false);
> +	curr = bq27xxx_read(di, BQ27XXX_REG_AI, false);
>  	if (curr < 0) {
>  		dev_err(di->dev, "error reading current\n");
>  		return curr;
>  	}
>  
> -	if (bq27xxx_is_chip_version_higher(di)) {
> -		/* bq27500 returns signed value */
> -		val->intval = (int)((s16)curr) * 1000;
> -	} else {
> -		flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, false);
> +	if (di->chip == BQ27000 || di->chip == BQ27010) {
> +		flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
>  		if (flags & BQ27000_FLAG_CHGS) {
>  			dev_dbg(di->dev, "negative current!\n");
>  			curr = -curr;
>  		}
>  
> -		val->intval = curr * 3570 / BQ27XXX_RS;
> +		val->intval = curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
> +	} else {
> +		/* Other gauges return signed value */
> +		val->intval = (int)((s16)curr) * 1000;
>  	}
>  
>  	return 0;
> @@ -596,14 +765,7 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
>  {
>  	int status;
>  
> -	if (bq27xxx_is_chip_version_higher(di)) {
> -		if (di->cache.flags & BQ27500_FLAG_FC)
> -			status = POWER_SUPPLY_STATUS_FULL;
> -		else if (di->cache.flags & BQ27500_FLAG_DSC)
> -			status = POWER_SUPPLY_STATUS_DISCHARGING;
> -		else
> -			status = POWER_SUPPLY_STATUS_CHARGING;
> -	} else {
> +	if (di->chip == BQ27000 || di->chip == BQ27010) {
>  		if (di->cache.flags & BQ27000_FLAG_FC)
>  			status = POWER_SUPPLY_STATUS_FULL;
>  		else if (di->cache.flags & BQ27000_FLAG_CHGS)
> @@ -612,6 +774,13 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
>  			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
>  		else
>  			status = POWER_SUPPLY_STATUS_DISCHARGING;
> +	} else {
> +		if (di->cache.flags & BQ27XXX_FLAG_FC)
> +			status = POWER_SUPPLY_STATUS_FULL;
> +		else if (di->cache.flags & BQ27XXX_FLAG_DSC)
> +			status = POWER_SUPPLY_STATUS_DISCHARGING;
> +		else
> +			status = POWER_SUPPLY_STATUS_CHARGING;
>  	}
>  
>  	val->intval = status;
> @@ -624,21 +793,21 @@ static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di,
>  {
>  	int level;
>  
> -	if (bq27xxx_is_chip_version_higher(di)) {
> -		if (di->cache.flags & BQ27500_FLAG_FC)
> +	if (di->chip == BQ27000 || di->chip == BQ27010) {
> +		if (di->cache.flags & BQ27000_FLAG_FC)
>  			level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
> -		else if (di->cache.flags & BQ27500_FLAG_SOC1)
> +		else if (di->cache.flags & BQ27000_FLAG_EDV1)
>  			level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
> -		else if (di->cache.flags & BQ27500_FLAG_SOCF)
> +		else if (di->cache.flags & BQ27000_FLAG_EDVF)
>  			level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
>  		else
>  			level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
>  	} else {
> -		if (di->cache.flags & BQ27000_FLAG_FC)
> +		if (di->cache.flags & BQ27XXX_FLAG_FC)
>  			level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
> -		else if (di->cache.flags & BQ27000_FLAG_EDV1)
> +		else if (di->cache.flags & BQ27XXX_FLAG_SOC1)
>  			level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
> -		else if (di->cache.flags & BQ27000_FLAG_EDVF)
> +		else if (di->cache.flags & BQ27XXX_FLAG_SOCF)
>  			level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
>  		else
>  			level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
> @@ -658,7 +827,7 @@ static int bq27xxx_battery_voltage(struct bq27xxx_device_info *di,
>  {
>  	int volt;
>  
> -	volt = bq27xxx_read(di, BQ27x00_REG_VOLT, false);
> +	volt = bq27xxx_read(di, BQ27XXX_REG_VOLT, false);
>  	if (volt < 0) {
>  		dev_err(di->dev, "error reading voltage\n");
>  		return volt;
> @@ -719,7 +888,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
>  	case POWER_SUPPLY_PROP_TEMP:
>  		ret = bq27xxx_simple_value(di->cache.temperature, val);
>  		if (ret == 0)
> -			val->intval -= 2731;
> +			val->intval -= 2731; /* convert decidegree k to c */
>  		break;
>  	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
>  		ret = bq27xxx_simple_value(di->cache.time_to_empty, val);
> @@ -785,18 +954,27 @@ static int bq27xxx_powersupply_init(struct bq27xxx_device_info *di,
>  
>  	psy_desc->name = name;
>  	psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
> -	if (di->chip == BQ27425) {
> -		psy_desc->properties = bq27425_battery_props;
> -		psy_desc->num_properties = ARRAY_SIZE(bq27425_battery_props);
> -	} else if (di->chip == BQ27742) {
> -		psy_desc->properties = bq27742_battery_props;
> -		psy_desc->num_properties = ARRAY_SIZE(bq27742_battery_props);
> -	} else if (di->chip == BQ27510) {
> -		psy_desc->properties = bq27510_battery_props;
> -		psy_desc->num_properties = ARRAY_SIZE(bq27510_battery_props);
> +	if (di->chip == BQ27000) {
> +		psy_desc->properties = bq27000_battery_props;
> +		psy_desc->num_properties = ARRAY_SIZE(bq27000_battery_props);
> +	} else if (di->chip == BQ27010) {
> +		psy_desc->properties = bq27010_battery_props;
> +		psy_desc->num_properties = ARRAY_SIZE(bq27010_battery_props);
> +	} else if (di->chip == BQ27500) {
> +		psy_desc->properties = bq27500_battery_props;
> +		psy_desc->num_properties = ARRAY_SIZE(bq27500_battery_props);
> +	} else if (di->chip == BQ27530) {
> +		psy_desc->properties = bq27530_battery_props;
> +		psy_desc->num_properties = ARRAY_SIZE(bq27530_battery_props);
> +	} else if (di->chip == BQ27541) {
> +		psy_desc->properties = bq27541_battery_props;
> +		psy_desc->num_properties = ARRAY_SIZE(bq27541_battery_props);
> +	} else if (di->chip == BQ27545) {
> +		psy_desc->properties = bq27545_battery_props;
> +		psy_desc->num_properties = ARRAY_SIZE(bq27545_battery_props);
>  	} else {
> -		psy_desc->properties = bq27x00_battery_props;
> -		psy_desc->num_properties = ARRAY_SIZE(bq27x00_battery_props);
> +		psy_desc->properties = bq27421_battery_props;
> +		psy_desc->num_properties = ARRAY_SIZE(bq27421_battery_props);
>  	}
>  	psy_desc->get_property = bq27xxx_battery_get_property;
>  	psy_desc->external_power_changed = bq27xxx_external_power_changed;
> @@ -911,10 +1089,32 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
>  	di->chip = id->driver_data;
>  	di->bus.read = &bq27xxx_battery_i2c_read;
>  
> +	if (di->chip == BQ27000) {
> +		di->regs = bq27000_regs;
> +	} else if (di->chip == BQ27010) {
> +		di->regs = bq27010_regs;
> +	} else if (di->chip == BQ27500) {
> +		di->regs = bq27500_regs;
> +	} else if (di->chip == BQ27530) {
> +		di->regs = bq27530_regs;
> +	} else if (di->chip == BQ27541) {
> +		di->regs = bq27541_regs;
> +	} else if (di->chip == BQ27545) {
> +		di->regs = bq27545_regs;
> +	} else if (di->chip == BQ27421) {
> +		di->regs = bq27421_regs;
> +	} else {
> +		dev_err(&client->dev, "Unexpected gas gauge: %d\n", di->chip);
> +		di->regs = bq27000_regs;
> +	}
> +
>  	retval = bq27xxx_powersupply_init(di, name);
>  	if (retval)
>  		goto batt_failed;
>  
> +	/* Schedule a polling after about 1 min */
> +	schedule_delayed_work(&di->work, 60 * HZ);
> +
>  	i2c_set_clientdata(client, di);
>  
>  	return 0;
> @@ -941,11 +1141,22 @@ static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
>  }
>  
>  static const struct i2c_device_id bq27xxx_id[] = {
> -	{ "bq27200", BQ27000 },	/* bq27200 is same as bq27000, but with i2c */
> +	{ "bq27200", BQ27000 },
> +	{ "bq27210", BQ27010 },
>  	{ "bq27500", BQ27500 },
> -	{ "bq27425", BQ27425 },
> -	{ "bq27742", BQ27742 },
> -	{ "bq27510", BQ27510 },
> +	{ "bq27510", BQ27500 },
> +	{ "bq27520", BQ27500 },
> +	{ "bq27530", BQ27530 },
> +	{ "bq27531", BQ27530 },
> +	{ "bq27541", BQ27541 },
> +	{ "bq27542", BQ27541 },
> +	{ "bq27546", BQ27541 },
> +	{ "bq27742", BQ27541 },
> +	{ "bq27545", BQ27545 },
> +	{ "bq27421", BQ27421 },
> +	{ "bq27425", BQ27421 },
> +	{ "bq27441", BQ27421 },
> +	{ "bq27621", BQ27421 },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(i2c, bq27xxx_id);
> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
> index a4efb10..45f6a7b 100644
> --- a/include/linux/power/bq27xxx_battery.h
> +++ b/include/linux/power/bq27xxx_battery.h
> @@ -12,7 +12,15 @@
>   *	register to be read. The return value should either be the content of
>   *	the passed register or an error value.
>   */
> -enum bq27xxx_chip { BQ27000 = 1, BQ27500, BQ27425, BQ27742, BQ27510 };
> +enum bq27xxx_chip {
> +	BQ27000 = 1, /* bq27000, bq27200 */
> +	BQ27010, /* bq27010, bq27210 */
> +	BQ27500, /* bq27500, bq27510, bq27520 */
> +	BQ27530, /* bq27530, bq27531 */
> +	BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
> +	BQ27545, /* bq27545 */
> +	BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
> +};
>  
>  struct bq27xxx_platform_data {
>  	const char *name;

In whole patch I see this usage pattern:

 if (chip == 1)
   ...
 else if (chip == 2)
   ...
 else if (chip == 3)
   ...

Maybe it is just syntax taste, but it is not better to use switch
instead lot of if-else construction? What other people prefer? I thought
that in kernel we prefer switch-case instead big if-else. I would like
to know what to use for *new* code/patches so we will same syntax style.

-- 
Pali Rohár
pali.rohar@gmail.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 5/6] power: bq27xxx_battery: Add support for additional bq27xxx family devices
  2015-08-06  8:28   ` Pali Rohár
@ 2015-08-07 15:08     ` Andrew F. Davis
  0 siblings, 0 replies; 9+ messages in thread
From: Andrew F. Davis @ 2015-08-07 15:08 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Sebastian Reichel, Dmitry Eremin-Solenikov, David Woodhouse,
	Dan Murphy, linux-pm, linux-kernel

On 08/06/2015 03:28 AM, Pali Rohár wrote:
> On Wednesday 05 August 2015 11:05:39 Andrew F. Davis wrote:
>> Add support for additional devices and register equivalent family devices
>> including the bq27010, bq27210, bq27500, bq27510, bq27520, bq27530,
>> bq27531, bq27541, bq27542, bq27546, bq27545, bq27441, bq27421, and the
>> bq27641.
>>
>> To facilitate this process the register mapings have been moved to tables
>> and other small cleanups have been made.
>>
>> Signed-off-by: Andrew F. Davis <afd@ti.com>
>> ---
>>   drivers/power/bq27xxx_battery.c       | 627 +++++++++++++++++++++++-----------
>>   include/linux/power/bq27xxx_battery.h |  10 +-
>>   2 files changed, 428 insertions(+), 209 deletions(-)
>>
>> diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c
>> index 1ff88ad..3098609 100644
>> --- a/drivers/power/bq27xxx_battery.c
>> +++ b/drivers/power/bq27xxx_battery.c
>> @@ -17,11 +17,24 @@
>>    * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
>>    *
>>    * Datasheets:
>> - * http://focus.ti.com/docs/prod/folders/print/bq27000.html
>> - * http://focus.ti.com/docs/prod/folders/print/bq27500.html
>> + * http://www.ti.com/product/bq27000
>> + * http://www.ti.com/product/bq27200
>> + * http://www.ti.com/product/bq27010
>> + * http://www.ti.com/product/bq27210
>> + * http://www.ti.com/product/bq27500
>> + * http://www.ti.com/product/bq27510-g3
>> + * http://www.ti.com/product/bq27520-g4
>> + * http://www.ti.com/product/bq27530-g1
>> + * http://www.ti.com/product/bq27531-g1
>> + * http://www.ti.com/product/bq27541-g1
>> + * http://www.ti.com/product/bq27542-g1
>> + * http://www.ti.com/product/bq27546-g1
>> + * http://www.ti.com/product/bq27742-g1
>> + * http://www.ti.com/product/bq27545-g1
>> + * http://www.ti.com/product/bq27421-g1
>>    * http://www.ti.com/product/bq27425-g1
>> - * http://www.ti.com/product/BQ27742-G1
>> - * http://www.ti.com/product/BQ27510-G3
>> + * http://www.ti.com/product/bq27411-g1
>> + * http://www.ti.com/product/bq27621-g1
>>    */
>>
>>   #include <linux/device.h>
>> @@ -43,54 +56,57 @@
>>
>>   #define BQ27XXX_MANUFACTURER	"Texas Instruments"
>>
>> -#define BQ27x00_REG_TEMP	0x06
>> -#define BQ27x00_REG_VOLT	0x08
>> -#define BQ27x00_REG_AI		0x14
>> -#define BQ27x00_REG_FLAGS	0x0A
>> -#define BQ27x00_REG_TTE		0x16
>> -#define BQ27x00_REG_TTF		0x18
>> -#define BQ27x00_REG_TTECP	0x26
>> -#define BQ27x00_REG_NAC		0x0C /* Nominal available capacity */
>> -#define BQ27x00_REG_LMD		0x12 /* Last measured discharge */
>> -#define BQ27x00_REG_CYCT	0x2A /* Cycle count total */
>> -#define BQ27x00_REG_AE		0x22 /* Available energy */
>> -#define BQ27x00_POWER_AVG	0x24
>> -
>> -#define BQ27000_REG_RSOC	0x0B /* Relative State-of-Charge */
>> -#define BQ27000_REG_ILMD	0x76 /* Initial last measured discharge */
>> +/* BQ27XXX Flags */
>> +#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_FC		BIT(9)
>> +#define BQ27XXX_FLAG_OTD	BIT(14)
>> +#define BQ27XXX_FLAG_OTC	BIT(15)
>> +
>> +/* BQ27000 has different layout for Flags register */
>>   #define BQ27000_FLAG_EDVF	BIT(0) /* Final End-of-Discharge-Voltage flag */
>>   #define BQ27000_FLAG_EDV1	BIT(1) /* First End-of-Discharge-Voltage flag */
>>   #define BQ27000_FLAG_CI		BIT(4) /* Capacity Inaccurate flag */
>>   #define BQ27000_FLAG_FC		BIT(5)
>>   #define BQ27000_FLAG_CHGS	BIT(7) /* Charge state flag */
>>
>> -#define BQ27500_REG_SOC		0x2C
>> -#define BQ27500_REG_DCAP	0x3C /* Design capacity */
>> -#define BQ27500_FLAG_DSC	BIT(0)
>> -#define BQ27500_FLAG_SOCF	BIT(1) /* State-of-Charge threshold final */
>> -#define BQ27500_FLAG_SOC1	BIT(2) /* State-of-Charge threshold 1 */
>> -#define BQ27500_FLAG_FC		BIT(9)
>> -#define BQ27500_FLAG_OTC	BIT(15)
>> -
>> -#define BQ27742_POWER_AVG	0x76
>> -
>> -#define BQ27510_REG_SOC		0x20
>> -#define BQ27510_REG_DCAP	0x2E /* Design capacity */
>> -#define BQ27510_REG_CYCT	0x1E /* Cycle count total */
>> -
>> -/* bq27425 register addresses are same as bq27x00 addresses minus 4 */
>> -#define BQ27425_REG_OFFSET	0x04
>> -#define BQ27425_REG_SOC		(0x1C + BQ27425_REG_OFFSET)
>> -#define BQ27425_REG_DCAP	(0x3C + BQ27425_REG_OFFSET)
>> -
>> -#define BQ27XXX_RS			20 /* Resistor sense */
>> -#define BQ27XXX_POWER_CONSTANT		(256 * 29200 / 1000)
>> +#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 */
>>
>>   struct bq27xxx_device_info;
>>   struct bq27xxx_access_methods {
>>   	int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single);
>>   };
>>
>> +#define INVALID_REG_ADDR	0xff
>> +
>> +/*
>> + * bq27xxx_reg_index - Register names
>> + *
>> + * These are indexes into a device's register mapping array.
>> + */
>> +enum bq27xxx_reg_index {
>> +	BQ27XXX_REG_CTRL = 0,	/* Control */
>> +	BQ27XXX_REG_TEMP,	/* Temperature */
>> +	BQ27XXX_REG_INT_TEMP,	/* Internal Temperature */
>> +	BQ27XXX_REG_VOLT,	/* Voltage */
>> +	BQ27XXX_REG_AI,		/* Average Current */
>> +	BQ27XXX_REG_FLAGS,	/* Flags */
>> +	BQ27XXX_REG_TTE,	/* Time-to-Empty */
>> +	BQ27XXX_REG_TTF,	/* Time-to-Full */
>> +	BQ27XXX_REG_TTES,	/* Time-to-Empty Standby */
>> +	BQ27XXX_REG_TTECP,	/* Time-to-Empty at Constant Power */
>> +	BQ27XXX_REG_NAC,	/* Nominal Available Capacity */
>> +	BQ27XXX_REG_FCC,	/* Full Charge Capacity */
>> +	BQ27XXX_REG_CYCT,	/* Cycle Count */
>> +	BQ27XXX_REG_AE,		/* Available Energy */
>> +	BQ27XXX_REG_SOC,	/* State-of-Charge */
>> +	BQ27XXX_REG_DCAP,	/* Design Capacity */
>> +	BQ27XXX_REG_AP,		/* Average Power */
>> +};
>> +
>>   struct bq27xxx_reg_cache {
>>   	int temperature;
>>   	int time_to_empty;
>> @@ -121,9 +137,152 @@ struct bq27xxx_device_info {
>>   	struct bq27xxx_access_methods bus;
>>
>>   	struct mutex lock;
>> +
>> +	u8 *regs;
>> +};
>> +
>> +/* Register mappings */
>> +static u8 bq27000_regs[] = {
>> +	0x00,	/* CONTROL	*/
>> +	0x06,	/* TEMP		*/
>> +	INVALID_REG_ADDR,	/* INT TEMP - NA*/
>> +	0x08,	/* VOLT		*/
>> +	0x14,	/* AVG CURR	*/
>> +	0x0a,	/* FLAGS	*/
>> +	0x16,	/* TTE		*/
>> +	0x18,	/* TTF		*/
>> +	0x1c,	/* TTES		*/
>> +	0x26,	/* TTECP	*/
>> +	0x0c,	/* NAC		*/
>> +	0x12,	/* LMD(FCC)	*/
>> +	0x2a,	/* CYCT		*/
>> +	0x22,	/* AE		*/
>> +	0x0b,	/* SOC(RSOC)	*/
>> +	0x76,	/* DCAP(ILMD)	*/
>> +	0x24,	/* AP		*/
>> +};
>> +
>> +static u8 bq27010_regs[] = {
>> +	0x00,	/* CONTROL	*/
>> +	0x06,	/* TEMP		*/
>> +	INVALID_REG_ADDR,	/* INT TEMP - NA*/
>> +	0x08,	/* VOLT		*/
>> +	0x14,	/* AVG CURR	*/
>> +	0x0a,	/* FLAGS	*/
>> +	0x16,	/* TTE		*/
>> +	0x18,	/* TTF		*/
>> +	0x1c,	/* TTES		*/
>> +	0x26,	/* TTECP	*/
>> +	0x0c,	/* NAC		*/
>> +	0x12,	/* LMD(FCC)	*/
>> +	0x2a,	/* CYCT		*/
>> +	INVALID_REG_ADDR,	/* AE - NA	*/
>> +	0x0b,	/* SOC(RSOC)	*/
>> +	0x76,	/* DCAP(ILMD)	*/
>> +	INVALID_REG_ADDR,	/* AP - NA	*/
>> +};
>> +
>> +static u8 bq27500_regs[] = {
>> +	0x00,	/* CONTROL	*/
>> +	0x06,	/* TEMP		*/
>> +	0x28,	/* INT TEMP	*/
>> +	0x08,	/* VOLT		*/
>> +	0x14,	/* AVG CURR	*/
>> +	0x0a,	/* FLAGS	*/
>> +	0x16,	/* TTE		*/
>> +	INVALID_REG_ADDR,	/* TTF - NA	*/
>> +	0x1a,	/* TTES		*/
>> +	INVALID_REG_ADDR,	/* TTECP - NA	*/
>> +	0x0c,	/* NAC		*/
>> +	0x12,	/* LMD(FCC)	*/
>> +	0x1e,	/* CYCT		*/
>> +	INVALID_REG_ADDR,	/* AE - NA	*/
>> +	0x20,	/* SOC(RSOC)	*/
>> +	0x2e,	/* DCAP(ILMD)	*/
>> +	INVALID_REG_ADDR,	/* AP - NA	*/
>>   };
>>
>> -static enum power_supply_property bq27x00_battery_props[] = {
>> +static u8 bq27530_regs[] = {
>> +	0x00,	/* CONTROL	*/
>> +	0x06,	/* TEMP		*/
>> +	0x32,	/* INT TEMP	*/
>> +	0x08,	/* VOLT		*/
>> +	0x14,	/* AVG CURR	*/
>> +	0x0a,	/* FLAGS	*/
>> +	0x16,	/* TTE		*/
>> +	INVALID_REG_ADDR,	/* TTF - NA	*/
>> +	INVALID_REG_ADDR,	/* TTES - NA	*/
>> +	INVALID_REG_ADDR,	/* TTECP - NA	*/
>> +	0x0c,	/* NAC		*/
>> +	0x12,	/* LMD(FCC)	*/
>> +	0x2a,	/* CYCT		*/
>> +	INVALID_REG_ADDR,	/* AE - NA	*/
>> +	0x2c,	/* SOC(RSOC)	*/
>> +	INVALID_REG_ADDR,	/* DCAP - NA	*/
>> +	0x24,	/* AP		*/
>> +};
>> +
>> +static u8 bq27541_regs[] = {
>> +	0x00,	/* CONTROL	*/
>> +	0x06,	/* TEMP		*/
>> +	0x28,	/* INT TEMP	*/
>> +	0x08,	/* VOLT		*/
>> +	0x14,	/* AVG CURR	*/
>> +	0x0a,	/* FLAGS	*/
>> +	0x16,	/* TTE		*/
>> +	INVALID_REG_ADDR,	/* TTF - NA	*/
>> +	INVALID_REG_ADDR,	/* TTES - NA	*/
>> +	INVALID_REG_ADDR,	/* TTECP - NA	*/
>> +	0x0c,	/* NAC		*/
>> +	0x12,	/* LMD(FCC)	*/
>> +	0x2a,	/* CYCT		*/
>> +	INVALID_REG_ADDR,	/* AE - NA	*/
>> +	0x2c,	/* SOC(RSOC)	*/
>> +	0x3c,	/* DCAP		*/
>> +	0x76,	/* AP		*/
>> +};
>> +
>> +static u8 bq27545_regs[] = {
>> +	0x00,	/* CONTROL	*/
>> +	0x06,	/* TEMP		*/
>> +	0x28,	/* INT TEMP	*/
>> +	0x08,	/* VOLT		*/
>> +	0x14,	/* AVG CURR	*/
>> +	0x0a,	/* FLAGS	*/
>> +	0x16,	/* TTE		*/
>> +	INVALID_REG_ADDR,	/* TTF - NA	*/
>> +	INVALID_REG_ADDR,	/* TTES - NA	*/
>> +	INVALID_REG_ADDR,	/* TTECP - NA	*/
>> +	0x0c,	/* NAC		*/
>> +	0x12,	/* LMD(FCC)	*/
>> +	0x2a,	/* CYCT		*/
>> +	INVALID_REG_ADDR,	/* AE - NA	*/
>> +	0x2c,	/* SOC(RSOC)	*/
>> +	INVALID_REG_ADDR,	/* DCAP - NA */
>> +	0x24,	/* AP		*/
>> +};
>> +
>> +static u8 bq27421_regs[] = {
>> +	0x00,	/* CONTROL	*/
>> +	0x02,	/* TEMP		*/
>> +	0x1e,	/* INT TEMP	*/
>> +	0x04,	/* VOLT		*/
>> +	0x10,	/* AVG CURR	*/
>> +	0x06,	/* FLAGS	*/
>> +	INVALID_REG_ADDR,	/* TTE - NA	*/
>> +	INVALID_REG_ADDR,	/* TTF - NA	*/
>> +	INVALID_REG_ADDR,	/* TTES - NA	*/
>> +	INVALID_REG_ADDR,	/* TTECP - NA	*/
>> +	0x08,	/* NAC		*/
>> +	0x0e,	/* FCC		*/
>> +	INVALID_REG_ADDR,	/* CYCT - NA	*/
>> +	INVALID_REG_ADDR,	/* AE - NA	*/
>> +	0x1c,	/* SOC		*/
>> +	0x3c,	/* DCAP		*/
>> +	0x18,	/* AP		*/
>> +};
>> +
>> +static enum power_supply_property bq27000_battery_props[] = {
>>   	POWER_SUPPLY_PROP_STATUS,
>>   	POWER_SUPPLY_PROP_PRESENT,
>>   	POWER_SUPPLY_PROP_VOLTAGE_NOW,
>> @@ -145,7 +304,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
>>   	POWER_SUPPLY_PROP_MANUFACTURER,
>>   };
>>
>> -static enum power_supply_property bq27425_battery_props[] = {
>> +static enum power_supply_property bq27010_battery_props[] = {
>>   	POWER_SUPPLY_PROP_STATUS,
>>   	POWER_SUPPLY_PROP_PRESENT,
>>   	POWER_SUPPLY_PROP_VOLTAGE_NOW,
>> @@ -153,14 +312,19 @@ static enum power_supply_property bq27425_battery_props[] = {
>>   	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_EMPTY_AVG,
>> +	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_HEALTH,
>>   	POWER_SUPPLY_PROP_MANUFACTURER,
>>   };
>>
>> -static enum power_supply_property bq27742_battery_props[] = {
>> +static enum power_supply_property bq27500_battery_props[] = {
>>   	POWER_SUPPLY_PROP_STATUS,
>>   	POWER_SUPPLY_PROP_PRESENT,
>>   	POWER_SUPPLY_PROP_VOLTAGE_NOW,
>> @@ -174,12 +338,29 @@ static enum power_supply_property bq27742_battery_props[] = {
>>   	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 bq27530_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_POWER_AVG,
>>   	POWER_SUPPLY_PROP_HEALTH,
>> +	POWER_SUPPLY_PROP_CYCLE_COUNT,
>>   	POWER_SUPPLY_PROP_MANUFACTURER,
>>   };
>>
>> -static enum power_supply_property bq27510_battery_props[] = {
>> +static enum power_supply_property bq27541_battery_props[] = {
>>   	POWER_SUPPLY_PROP_STATUS,
>>   	POWER_SUPPLY_PROP_PRESENT,
>>   	POWER_SUPPLY_PROP_VOLTAGE_NOW,
>> @@ -198,6 +379,39 @@ static enum power_supply_property bq27510_battery_props[] = {
>>   	POWER_SUPPLY_PROP_MANUFACTURER,
>>   };
>>
>> +static enum power_supply_property bq27545_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_HEALTH,
>> +	POWER_SUPPLY_PROP_CYCLE_COUNT,
>> +	POWER_SUPPLY_PROP_POWER_AVG,
>> +	POWER_SUPPLY_PROP_MANUFACTURER,
>> +};
>> +
>> +static enum power_supply_property bq27421_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_TECHNOLOGY,
>> +	POWER_SUPPLY_PROP_CHARGE_FULL,
>> +	POWER_SUPPLY_PROP_CHARGE_NOW,
>> +	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
>> +	POWER_SUPPLY_PROP_MANUFACTURER,
>> +};
>> +
>>   static unsigned int poll_interval = 360;
>>   module_param(poll_interval, uint, 0644);
>>   MODULE_PARM_DESC(poll_interval,
>> @@ -207,25 +421,14 @@ MODULE_PARM_DESC(poll_interval,
>>    * Common code for BQ27xxx devices
>>    */
>>
>> -static inline int bq27xxx_read(struct bq27xxx_device_info *di, u8 reg,
>> +static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index,
>>   			       bool single)
>>   {
>> -	if (di->chip == BQ27425)
>> -		return di->bus.read(di, reg - BQ27425_REG_OFFSET, single);
>> -	return di->bus.read(di, reg, single);
>> -}
>> +	/* Reports EINVAL for invalid/missing registers */
>> +	if (!di || di->regs[reg_index] == INVALID_REG_ADDR)
>> +		return -EINVAL;
>>
>> -/*
>> - * Higher versions of the chip like BQ27425 and BQ27500
>> - * differ from BQ27000 and BQ27200 in calculation of certain
>> - * parameters. Hence we need to check for the chip type.
>> - */
>> -static bool bq27xxx_is_chip_version_higher(struct bq27xxx_device_info *di)
>> -{
>> -	if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742
>> -	    || di->chip == BQ27510)
>> -		return true;
>> -	return false;
>> +	return di->bus.read(di, di->regs[reg_index], single);
>>   }
>>
>>   /*
>> @@ -236,14 +439,7 @@ static int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di)
>>   {
>>   	int soc;
>>
>> -	if (di->chip == BQ27500 || di->chip == BQ27742)
>> -		soc = bq27xxx_read(di, BQ27500_REG_SOC, false);
>> -	else if (di->chip == BQ27510)
>> -		soc = bq27xxx_read(di, BQ27510_REG_SOC, false);
>> -	else if (di->chip == BQ27425)
>> -		soc = bq27xxx_read(di, BQ27425_REG_SOC, false);
>> -	else /* for the bq27000 we read the "relative" SoC register */
>> -		soc = bq27xxx_read(di, BQ27000_REG_RSOC, true);
>> +	soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false);
>>
>>   	if (soc < 0)
>>   		dev_dbg(di->dev, "error reading State-of-Charge\n");
>> @@ -266,10 +462,10 @@ static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg)
>>   		return charge;
>>   	}
>>
>> -	if (bq27xxx_is_chip_version_higher(di))
>> -		charge *= 1000;
>> +	if (di->chip == BQ27000 || di->chip == BQ27010)
>> +		charge *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
>>   	else
>> -		charge = charge * 3570 / BQ27XXX_RS;
>> +		charge *= 1000;
>>
>>   	return charge;
>>   }
>> @@ -281,57 +477,46 @@ static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg)
>>   static inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di)
>>   {
>>   	int flags;
>> -	bool is_bq27500 = di->chip == BQ27500;
>> -	bool is_bq27742 = di->chip == BQ27742;
>> -	bool is_higher = bq27xxx_is_chip_version_higher(di);
>> -	bool flags_1b = !(is_bq27500 || is_bq27742);
>>
>> -	flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, flags_1b);
>> -	if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI))
>> -		return -ENODATA;
>> +	if (di->chip == BQ27000 || di->chip == BQ27010) {
>> +		flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, true);
>> +		if (flags >= 0 && (flags & BQ27000_FLAG_CI))
>> +			return -ENODATA;
>> +	}
>>
>> -	return bq27xxx_battery_read_charge(di, BQ27x00_REG_NAC);
>> +	return bq27xxx_battery_read_charge(di, BQ27XXX_REG_NAC);
>>   }
>>
>>   /*
>> - * Return the battery Last measured discharge in µAh
>> + * Return the battery Full Charge Capacity in µAh
>>    * Or < 0 if something fails.
>>    */
>> -static inline int bq27xxx_battery_read_lmd(struct bq27xxx_device_info *di)
>> +static inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di)
>>   {
>> -	return bq27xxx_battery_read_charge(di, BQ27x00_REG_LMD);
>> +	return bq27xxx_battery_read_charge(di, BQ27XXX_REG_FCC);
>>   }
>>
>>   /*
>> - * Return the battery Initial last measured discharge in µAh
>> + * Return the Design Capacity in µAh
>>    * Or < 0 if something fails.
>>    */
>> -static int bq27xxx_battery_read_ilmd(struct bq27xxx_device_info *di)
>> +static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
>>   {
>> -	int ilmd;
>> +	int dcap;
>>
>> -	if (bq27xxx_is_chip_version_higher(di)) {
>> -		if (di->chip == BQ27425)
>> -			ilmd = bq27xxx_read(di, BQ27425_REG_DCAP, false);
>> -		else if (di->chip == BQ27510)
>> -			ilmd = bq27xxx_read(di, BQ27510_REG_DCAP, false);
>> -		else
>> -			ilmd = bq27xxx_read(di, BQ27500_REG_DCAP, false);
>> -	} else {
>> -		ilmd = bq27xxx_read(di, BQ27000_REG_ILMD, true);
>> -	}
>> +	dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
>>
>> -	if (ilmd < 0) {
>> +	if (dcap < 0) {
>>   		dev_dbg(di->dev, "error reading initial last measured discharge\n");
>> -		return ilmd;
>> +		return dcap;
>>   	}
>>
>> -	if (bq27xxx_is_chip_version_higher(di))
>> -		ilmd *= 1000;
>> +	if (di->chip == BQ27000 || di->chip == BQ27010)
>> +		dcap *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
>>   	else
>> -		ilmd = ilmd * 256 * 3570 / BQ27XXX_RS;
>> +		dcap *= 1000;
>>
>> -	return ilmd;
>> +	return dcap;
>>   }
>>
>>   /*
>> @@ -342,16 +527,16 @@ static int bq27xxx_battery_read_energy(struct bq27xxx_device_info *di)
>>   {
>>   	int ae;
>>
>> -	ae = bq27xxx_read(di, BQ27x00_REG_AE, false);
>> +	ae = bq27xxx_read(di, BQ27XXX_REG_AE, false);
>>   	if (ae < 0) {
>>   		dev_dbg(di->dev, "error reading available energy\n");
>>   		return ae;
>>   	}
>>
>> -	if (di->chip == BQ27500)
>> -		ae *= 1000;
>> +	if (di->chip == BQ27000 || di->chip == BQ27010)
>> +		ae *= BQ27XXX_POWER_CONSTANT / BQ27XXX_RS;
>>   	else
>> -		ae = ae * 29200 / BQ27XXX_RS;
>> +		ae *= 1000;
>>
>>   	return ae;
>>   }
>> @@ -364,13 +549,13 @@ static int bq27xxx_battery_read_temperature(struct bq27xxx_device_info *di)
>>   {
>>   	int temp;
>>
>> -	temp = bq27xxx_read(di, BQ27x00_REG_TEMP, false);
>> +	temp = bq27xxx_read(di, BQ27XXX_REG_TEMP, false);
>>   	if (temp < 0) {
>>   		dev_err(di->dev, "error reading temperature\n");
>>   		return temp;
>>   	}
>>
>> -	if (!bq27xxx_is_chip_version_higher(di))
>> +	if (di->chip == BQ27000 || di->chip == BQ27010)
>>   		temp = 5 * temp / 2;
>>
>>   	return temp;
>> @@ -384,10 +569,7 @@ static int bq27xxx_battery_read_cyct(struct bq27xxx_device_info *di)
>>   {
>>   	int cyct;
>>
>> -	if (di->chip == BQ27510)
>> -		cyct = bq27xxx_read(di, BQ27510_REG_CYCT, false);
>> -	else
>> -		cyct = bq27xxx_read(di, BQ27x00_REG_CYCT, false);
>> +	cyct = bq27xxx_read(di, BQ27XXX_REG_CYCT, false);
>>   	if (cyct < 0)
>>   		dev_err(di->dev, "error reading cycle count total\n");
>>
>> @@ -419,21 +601,32 @@ static int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, u8 reg)
>>    * Read an average power register.
>>    * Return < 0 if something fails.
>>    */
>> -static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di, u8 reg)
>> +static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di)
>>   {
>>   	int tval;
>>
>> -	tval = bq27xxx_read(di, reg, false);
>> +	tval = bq27xxx_read(di, BQ27XXX_REG_AP, false);
>>   	if (tval < 0) {
>> -		dev_err(di->dev, "error reading power avg rgister  %02x: %d\n",
>> -			reg, tval);
>> +		dev_err(di->dev, "error reading average power register  %02x: %d\n",
>> +			BQ27XXX_REG_AP, tval);
>>   		return tval;
>>   	}
>>
>> -	if (di->chip == BQ27500)
>> +	if (di->chip == BQ27000 || di->chip == BQ27010)
>> +		return (tval * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS;
>> +	else
>>   		return tval;
>> +}
>> +
>> +/*
>> + * Returns true if a battery over temperature condition is detected
>> + */
>> +static int bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags)
>> +{
>> +	if (di->chip == BQ27500 || di->chip == BQ27541)
>> +		return flags & (BQ27XXX_FLAG_OTC | BQ27XXX_FLAG_OTD);
>>   	else
>> -		return (tval * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS;
>> +		return flags & BQ27XXX_FLAG_OTC;
>>   }
>>
>>   /*
>> @@ -442,53 +635,43 @@ static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di, u8 reg)
>>    */
>>   static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
>>   {
>> -	int tval;
>> +	u16 tval;
>>
>> -	tval = bq27xxx_read(di, BQ27x00_REG_FLAGS, false);
>> +	tval = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
>>   	if (tval < 0) {
>>   		dev_err(di->dev, "error reading flag register:%d\n", tval);
>>   		return tval;
>>   	}
>>
>> -	if (di->chip == BQ27500) {
>> -		if (tval & BQ27500_FLAG_SOCF)
>> +	if (di->chip == BQ27000 || di->chip == BQ27010) {
>> +		if (tval & BQ27000_FLAG_EDV1)
>>   			tval = POWER_SUPPLY_HEALTH_DEAD;
>> -		else if (tval & BQ27500_FLAG_OTC)
>> -			tval = POWER_SUPPLY_HEALTH_OVERHEAT;
>>   		else
>>   			tval = POWER_SUPPLY_HEALTH_GOOD;
>> -		return tval;
>> -	} else if (di->chip == BQ27510) {
>> -		if (tval & BQ27500_FLAG_OTC)
>> -			return POWER_SUPPLY_HEALTH_OVERHEAT;
>> -		return POWER_SUPPLY_HEALTH_GOOD;
>>   	} else {
>> -		if (tval & BQ27000_FLAG_EDV1)
>> +		if (tval & BQ27XXX_FLAG_SOCF)
>>   			tval = POWER_SUPPLY_HEALTH_DEAD;
>> +		else if (bq27xxx_battery_overtemp(di, tval))
>> +			tval = POWER_SUPPLY_HEALTH_OVERHEAT;
>>   		else
>>   			tval = POWER_SUPPLY_HEALTH_GOOD;
>> -		return tval;
>>   	}
>>
>> -	return -1;
>> +	return tval;
>>   }
>>
>>   static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
>>   {
>>   	struct bq27xxx_reg_cache cache = {0, };
>> -	bool is_bq27500 = di->chip == BQ27500;
>> -	bool is_bq27510 = di->chip == BQ27510;
>> -	bool is_bq27425 = di->chip == BQ27425;
>> -	bool is_bq27742 = di->chip == BQ27742;
>> -	bool flags_1b = !(is_bq27500 || is_bq27742);
>> +	bool has_ci_flag = di->chip == BQ27000 || di->chip == BQ27010;
>> +	bool has_singe_flag = di->chip == BQ27000 || di->chip == BQ27010;
>>
>> -	cache.flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, flags_1b);
>> +	cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
>>   	if ((cache.flags & 0xff) == 0xff)
>> -		/* read error */
>> -		cache.flags = -1;
>> +		cache.flags = -1; /* read error */
>>   	if (cache.flags >= 0) {
>> -		if (!is_bq27500 && !is_bq27425 && !is_bq27742 && !is_bq27510
>> -				&& (cache.flags & BQ27000_FLAG_CI)) {
>> +		cache.temperature = bq27xxx_battery_read_temperature(di);
>> +		if (has_ci_flag && (cache.flags & BQ27000_FLAG_CI)) {
>>   			dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
>>   			cache.capacity = -ENODATA;
>>   			cache.energy = -ENODATA;
>> @@ -498,41 +681,26 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
>>   			cache.charge_full = -ENODATA;
>>   			cache.health = -ENODATA;
>>   		} else {
>> +			if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
>> +				cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
>> +			if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
>> +				cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
>> +			if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
>> +				cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
>> +			cache.charge_full = bq27xxx_battery_read_fcc(di);
>>   			cache.capacity = bq27xxx_battery_read_soc(di);
>> -			if (is_bq27742 || is_bq27510)
>> -				cache.time_to_empty =
>> -					bq27xxx_battery_read_time(di,
>> -							BQ27x00_REG_TTE);
>> -			else if (!is_bq27425) {
>> +			if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
>>   				cache.energy = bq27xxx_battery_read_energy(di);
>> -				cache.time_to_empty =
>> -					bq27xxx_battery_read_time(di,
>> -							BQ27x00_REG_TTE);
>> -				cache.time_to_empty_avg =
>> -					bq27xxx_battery_read_time(di,
>> -							BQ27x00_REG_TTECP);
>> -				cache.time_to_full =
>> -					bq27xxx_battery_read_time(di,
>> -							BQ27x00_REG_TTF);
>> -			}
>> -			cache.charge_full = bq27xxx_battery_read_lmd(di);
>>   			cache.health = bq27xxx_battery_read_health(di);
>>   		}
>> -		cache.temperature = bq27xxx_battery_read_temperature(di);
>> -		if (!is_bq27425)
>> +		if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
>>   			cache.cycle_count = bq27xxx_battery_read_cyct(di);
>> -		if (is_bq27742)
>> -			cache.power_avg =
>> -				bq27xxx_battery_read_pwr_avg(di,
>> -						BQ27742_POWER_AVG);
>> -		else
>> -			cache.power_avg =
>> -				bq27xxx_battery_read_pwr_avg(di,
>> -						BQ27x00_POWER_AVG);
>> +		if (di->regs[BQ27XXX_REG_AP] != INVALID_REG_ADDR)
>> +			cache.power_avg = bq27xxx_battery_read_pwr_avg(di);
>>
>>   		/* We only have to read charge design full once */
>>   		if (di->charge_design_full <= 0)
>> -			di->charge_design_full = bq27xxx_battery_read_ilmd(di);
>> +			di->charge_design_full = bq27xxx_battery_read_dcap(di);
>>   	}
>>
>>   	if (di->cache.capacity != cache.capacity)
>> @@ -547,7 +715,8 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
>>   static void bq27xxx_battery_poll(struct work_struct *work)
>>   {
>>   	struct bq27xxx_device_info *di =
>> -		container_of(work, struct bq27xxx_device_info, work.work);
>> +			container_of(work, struct bq27xxx_device_info,
>> +				     work.work);
>>
>>   	bq27xxx_battery_update(di);
>>
>> @@ -569,23 +738,23 @@ static int bq27xxx_battery_current(struct bq27xxx_device_info *di,
>>   	int curr;
>>   	int flags;
>>
>> -	curr = bq27xxx_read(di, BQ27x00_REG_AI, false);
>> +	curr = bq27xxx_read(di, BQ27XXX_REG_AI, false);
>>   	if (curr < 0) {
>>   		dev_err(di->dev, "error reading current\n");
>>   		return curr;
>>   	}
>>
>> -	if (bq27xxx_is_chip_version_higher(di)) {
>> -		/* bq27500 returns signed value */
>> -		val->intval = (int)((s16)curr) * 1000;
>> -	} else {
>> -		flags = bq27xxx_read(di, BQ27x00_REG_FLAGS, false);
>> +	if (di->chip == BQ27000 || di->chip == BQ27010) {
>> +		flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
>>   		if (flags & BQ27000_FLAG_CHGS) {
>>   			dev_dbg(di->dev, "negative current!\n");
>>   			curr = -curr;
>>   		}
>>
>> -		val->intval = curr * 3570 / BQ27XXX_RS;
>> +		val->intval = curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
>> +	} else {
>> +		/* Other gauges return signed value */
>> +		val->intval = (int)((s16)curr) * 1000;
>>   	}
>>
>>   	return 0;
>> @@ -596,14 +765,7 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
>>   {
>>   	int status;
>>
>> -	if (bq27xxx_is_chip_version_higher(di)) {
>> -		if (di->cache.flags & BQ27500_FLAG_FC)
>> -			status = POWER_SUPPLY_STATUS_FULL;
>> -		else if (di->cache.flags & BQ27500_FLAG_DSC)
>> -			status = POWER_SUPPLY_STATUS_DISCHARGING;
>> -		else
>> -			status = POWER_SUPPLY_STATUS_CHARGING;
>> -	} else {
>> +	if (di->chip == BQ27000 || di->chip == BQ27010) {
>>   		if (di->cache.flags & BQ27000_FLAG_FC)
>>   			status = POWER_SUPPLY_STATUS_FULL;
>>   		else if (di->cache.flags & BQ27000_FLAG_CHGS)
>> @@ -612,6 +774,13 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
>>   			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
>>   		else
>>   			status = POWER_SUPPLY_STATUS_DISCHARGING;
>> +	} else {
>> +		if (di->cache.flags & BQ27XXX_FLAG_FC)
>> +			status = POWER_SUPPLY_STATUS_FULL;
>> +		else if (di->cache.flags & BQ27XXX_FLAG_DSC)
>> +			status = POWER_SUPPLY_STATUS_DISCHARGING;
>> +		else
>> +			status = POWER_SUPPLY_STATUS_CHARGING;
>>   	}
>>
>>   	val->intval = status;
>> @@ -624,21 +793,21 @@ static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di,
>>   {
>>   	int level;
>>
>> -	if (bq27xxx_is_chip_version_higher(di)) {
>> -		if (di->cache.flags & BQ27500_FLAG_FC)
>> +	if (di->chip == BQ27000 || di->chip == BQ27010) {
>> +		if (di->cache.flags & BQ27000_FLAG_FC)
>>   			level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
>> -		else if (di->cache.flags & BQ27500_FLAG_SOC1)
>> +		else if (di->cache.flags & BQ27000_FLAG_EDV1)
>>   			level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
>> -		else if (di->cache.flags & BQ27500_FLAG_SOCF)
>> +		else if (di->cache.flags & BQ27000_FLAG_EDVF)
>>   			level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
>>   		else
>>   			level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
>>   	} else {
>> -		if (di->cache.flags & BQ27000_FLAG_FC)
>> +		if (di->cache.flags & BQ27XXX_FLAG_FC)
>>   			level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
>> -		else if (di->cache.flags & BQ27000_FLAG_EDV1)
>> +		else if (di->cache.flags & BQ27XXX_FLAG_SOC1)
>>   			level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
>> -		else if (di->cache.flags & BQ27000_FLAG_EDVF)
>> +		else if (di->cache.flags & BQ27XXX_FLAG_SOCF)
>>   			level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
>>   		else
>>   			level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
>> @@ -658,7 +827,7 @@ static int bq27xxx_battery_voltage(struct bq27xxx_device_info *di,
>>   {
>>   	int volt;
>>
>> -	volt = bq27xxx_read(di, BQ27x00_REG_VOLT, false);
>> +	volt = bq27xxx_read(di, BQ27XXX_REG_VOLT, false);
>>   	if (volt < 0) {
>>   		dev_err(di->dev, "error reading voltage\n");
>>   		return volt;
>> @@ -719,7 +888,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
>>   	case POWER_SUPPLY_PROP_TEMP:
>>   		ret = bq27xxx_simple_value(di->cache.temperature, val);
>>   		if (ret == 0)
>> -			val->intval -= 2731;
>> +			val->intval -= 2731; /* convert decidegree k to c */
>>   		break;
>>   	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
>>   		ret = bq27xxx_simple_value(di->cache.time_to_empty, val);
>> @@ -785,18 +954,27 @@ static int bq27xxx_powersupply_init(struct bq27xxx_device_info *di,
>>
>>   	psy_desc->name = name;
>>   	psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
>> -	if (di->chip == BQ27425) {
>> -		psy_desc->properties = bq27425_battery_props;
>> -		psy_desc->num_properties = ARRAY_SIZE(bq27425_battery_props);
>> -	} else if (di->chip == BQ27742) {
>> -		psy_desc->properties = bq27742_battery_props;
>> -		psy_desc->num_properties = ARRAY_SIZE(bq27742_battery_props);
>> -	} else if (di->chip == BQ27510) {
>> -		psy_desc->properties = bq27510_battery_props;
>> -		psy_desc->num_properties = ARRAY_SIZE(bq27510_battery_props);
>> +	if (di->chip == BQ27000) {
>> +		psy_desc->properties = bq27000_battery_props;
>> +		psy_desc->num_properties = ARRAY_SIZE(bq27000_battery_props);
>> +	} else if (di->chip == BQ27010) {
>> +		psy_desc->properties = bq27010_battery_props;
>> +		psy_desc->num_properties = ARRAY_SIZE(bq27010_battery_props);
>> +	} else if (di->chip == BQ27500) {
>> +		psy_desc->properties = bq27500_battery_props;
>> +		psy_desc->num_properties = ARRAY_SIZE(bq27500_battery_props);
>> +	} else if (di->chip == BQ27530) {
>> +		psy_desc->properties = bq27530_battery_props;
>> +		psy_desc->num_properties = ARRAY_SIZE(bq27530_battery_props);
>> +	} else if (di->chip == BQ27541) {
>> +		psy_desc->properties = bq27541_battery_props;
>> +		psy_desc->num_properties = ARRAY_SIZE(bq27541_battery_props);
>> +	} else if (di->chip == BQ27545) {
>> +		psy_desc->properties = bq27545_battery_props;
>> +		psy_desc->num_properties = ARRAY_SIZE(bq27545_battery_props);
>>   	} else {
>> -		psy_desc->properties = bq27x00_battery_props;
>> -		psy_desc->num_properties = ARRAY_SIZE(bq27x00_battery_props);
>> +		psy_desc->properties = bq27421_battery_props;
>> +		psy_desc->num_properties = ARRAY_SIZE(bq27421_battery_props);
>>   	}
>>   	psy_desc->get_property = bq27xxx_battery_get_property;
>>   	psy_desc->external_power_changed = bq27xxx_external_power_changed;
>> @@ -911,10 +1089,32 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
>>   	di->chip = id->driver_data;
>>   	di->bus.read = &bq27xxx_battery_i2c_read;
>>
>> +	if (di->chip == BQ27000) {
>> +		di->regs = bq27000_regs;
>> +	} else if (di->chip == BQ27010) {
>> +		di->regs = bq27010_regs;
>> +	} else if (di->chip == BQ27500) {
>> +		di->regs = bq27500_regs;
>> +	} else if (di->chip == BQ27530) {
>> +		di->regs = bq27530_regs;
>> +	} else if (di->chip == BQ27541) {
>> +		di->regs = bq27541_regs;
>> +	} else if (di->chip == BQ27545) {
>> +		di->regs = bq27545_regs;
>> +	} else if (di->chip == BQ27421) {
>> +		di->regs = bq27421_regs;
>> +	} else {
>> +		dev_err(&client->dev, "Unexpected gas gauge: %d\n", di->chip);
>> +		di->regs = bq27000_regs;
>> +	}
>> +
>>   	retval = bq27xxx_powersupply_init(di, name);
>>   	if (retval)
>>   		goto batt_failed;
>>
>> +	/* Schedule a polling after about 1 min */
>> +	schedule_delayed_work(&di->work, 60 * HZ);
>> +
>>   	i2c_set_clientdata(client, di);
>>
>>   	return 0;
>> @@ -941,11 +1141,22 @@ static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
>>   }
>>
>>   static const struct i2c_device_id bq27xxx_id[] = {
>> -	{ "bq27200", BQ27000 },	/* bq27200 is same as bq27000, but with i2c */
>> +	{ "bq27200", BQ27000 },
>> +	{ "bq27210", BQ27010 },
>>   	{ "bq27500", BQ27500 },
>> -	{ "bq27425", BQ27425 },
>> -	{ "bq27742", BQ27742 },
>> -	{ "bq27510", BQ27510 },
>> +	{ "bq27510", BQ27500 },
>> +	{ "bq27520", BQ27500 },
>> +	{ "bq27530", BQ27530 },
>> +	{ "bq27531", BQ27530 },
>> +	{ "bq27541", BQ27541 },
>> +	{ "bq27542", BQ27541 },
>> +	{ "bq27546", BQ27541 },
>> +	{ "bq27742", BQ27541 },
>> +	{ "bq27545", BQ27545 },
>> +	{ "bq27421", BQ27421 },
>> +	{ "bq27425", BQ27421 },
>> +	{ "bq27441", BQ27421 },
>> +	{ "bq27621", BQ27421 },
>>   	{},
>>   };
>>   MODULE_DEVICE_TABLE(i2c, bq27xxx_id);
>> diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
>> index a4efb10..45f6a7b 100644
>> --- a/include/linux/power/bq27xxx_battery.h
>> +++ b/include/linux/power/bq27xxx_battery.h
>> @@ -12,7 +12,15 @@
>>    *	register to be read. The return value should either be the content of
>>    *	the passed register or an error value.
>>    */
>> -enum bq27xxx_chip { BQ27000 = 1, BQ27500, BQ27425, BQ27742, BQ27510 };
>> +enum bq27xxx_chip {
>> +	BQ27000 = 1, /* bq27000, bq27200 */
>> +	BQ27010, /* bq27010, bq27210 */
>> +	BQ27500, /* bq27500, bq27510, bq27520 */
>> +	BQ27530, /* bq27530, bq27531 */
>> +	BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
>> +	BQ27545, /* bq27545 */
>> +	BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
>> +};
>>
>>   struct bq27xxx_platform_data {
>>   	const char *name;
>
> In whole patch I see this usage pattern:
>
>   if (chip == 1)
>     ...
>   else if (chip == 2)
>     ...
>   else if (chip == 3)
>     ...
>
> Maybe it is just syntax taste, but it is not better to use switch
> instead lot of if-else construction? What other people prefer? I thought
> that in kernel we prefer switch-case instead big if-else. I would like
> to know what to use for *new* code/patches so we will same syntax style.
>

I would prefer the switch-case myself, I chose the if-else to match the 
existing style in this driver, I can change it if needed or I can do 
that in a later patch series.

-- 
Andrew F. Davis

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-08-07 15:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-05 16:05 [PATCH v3 0/6] Add support for additional bq27xxx devices Andrew F. Davis
2015-08-05 16:05 ` [PATCH v3 1/6] power: bq27x00_battery: Remove unneeded i2c MODULE_ALIAS Andrew F. Davis
2015-08-05 16:05 ` [PATCH v3 2/6] power: bq27x00_battery: Renaming for consistency Andrew F. Davis
2015-08-05 16:05 ` [PATCH v3 3/6] power: bq27xxx_battery: Platform initialization must declare a device Andrew F. Davis
2015-08-05 16:05 ` [PATCH v3 4/6] power: bq27xxx_battery: Fix typos and change naming for state of charge functions Andrew F. Davis
2015-08-05 16:05 ` [PATCH v3 5/6] power: bq27xxx_battery: Add support for additional bq27xxx family devices Andrew F. Davis
2015-08-06  8:28   ` Pali Rohár
2015-08-07 15:08     ` Andrew F. Davis
2015-08-05 16:05 ` [PATCH v3 6/6] power: bq27xxx_battery: Cleanup health checking Andrew F. Davis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).