Skip to contentSkip to conversation

bq27x00_battery: Add new properties

PATCH In review Anton Vorontsov 5 participants 15 messages Jan 31, 2011

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 bq27x00_battery: Add new properties

Forwarding this to lkml and bq27x00 hackers.

Comments, Reviewed-by or Acked-by?

----- Forwarded message from Pali Rohár <[email protected]> -----

Date: Wed, 26 Jan 2011 21:44:08 +0100
From: Pali Rohár <[email protected]>
To: Anton Vorontsov <[email protected]>
Cc: David Woodhouse <[email protected]>
Subject: Re: [PATCH] bq27x00_battery

This patch add support for properties POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_ENERGY_NOW, POWER_SUPPLY_PROP_ONLINE in module bq27x00_battery.

drivers/power/bq27x00_battery.c +120 -2
@@ -3,9 +3,14 @@
  *
  * Copyright (C) 2008 Rodolfo Giometti <[email protected]>
  * Copyright (C) 2008 Eurotech S.p.A. <[email protected]>
+ * Copyright (C) 2011 Pali Rohár <[email protected]>
  *
  * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
  *
+ * Datasheets:
+ * http://focus.ti.com/docs/prod/folders/print/bq27000.html
+ * http://focus.ti.com/docs/prod/folders/print/bq27500.html
+ *
  * This package is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -27,8 +32,9 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
-#define DRIVER_VERSION			"1.1.0"
+#define DRIVER_VERSION			"1.2.0"
 
+#define BQ27x00_REG_MODE		0x00
 #define BQ27x00_REG_TEMP		0x06
 #define BQ27x00_REG_VOLT		0x08
 #define BQ27x00_REG_AI			0x14
@@ -36,10 +42,14 @@
 #define BQ27x00_REG_TTE			0x16
 #define BQ27x00_REG_TTF			0x18
 #define BQ27x00_REG_TTECP		0x26
+#define BQ27x00_REG_NAC			0x0C /* Nominal available capaciy */
+#define BQ27x00_REG_LMD			0x12 /* Last measured discharge */
+#define BQ27x00_REG_AE			0x22 /* Available Enery */
 
 #define BQ27000_RS			20 /* Resistor sense */
 #define BQ27000_REG_RSOC		0x0B /* Relative State-of-Charge */
 #define BQ27000_FLAG_CHGS		BIT(7)
+#define BQ27000_FLAG_FC			BIT(5)
 
 #define BQ27500_REG_SOC			0x2C
 #define BQ27500_FLAG_DSC		BIT(0)
@@ -75,7 +85,11 @@ static enum power_supply_property bq27x0
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
 	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
 	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
@@ -92,6 +106,24 @@ static int bq27x00_read(u8 reg, int *rt_
 }
 
 /*
+ * Return the GPIO status (0 or 1)
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_gpio(struct bq27x00_device_info *di)
+{
+	int ret;
+	int gpio = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_MODE, &gpio, 0, di);
+	if (ret) {
+		dev_err(di->dev, "error reading GPIO status\n");
+		return ret;
+	}
+
+	return (gpio & 0x40) >> 6;
+}
+
+/*
  * Return the battery temperature in tenths of degree Celsius
  * Or < 0 if something fails.
  */
@@ -188,6 +220,75 @@ static int bq27x00_battery_rsoc(struct b
 	return rsoc;
 }
 
+/*
+ * Return the battery Nominal available capaciy in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_nac(struct bq27x00_device_info *di)
+{
+	int ret;
+	int nac = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_NAC, &nac, 0, di);
+	if (ret) {
+		dev_err(di->dev, "error reading nominal available capaciy\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500)
+		nac *= 1000;
+	else
+		nac = nac * 3570 / BQ27000_RS;
+
+	return nac;
+}
+
+/*
+ * Return the battery Last measured discharge in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_lmd(struct bq27x00_device_info *di)
+{
+	int ret;
+	int lmd = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_LMD, &lmd, 0, di);
+	if (ret) {
+		dev_err(di->dev, "error reading last measured discharge\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500)
+		lmd *= 1000;
+	else
+		lmd = lmd * 3570 / BQ27000_RS;
+
+	return lmd;
+}
+
+/*
+ * Return the battery Available energy in µWh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_energy(struct bq27x00_device_info *di)
+{
+	int ret;
+	int ae = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_LMD, &ae, 0, di);
+	if (ret) {
+		dev_err(di->dev, "error reading available energy\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500)
+		ae *= 1000;
+	else
+		ae = ae * 29200 / BQ27000_RS;
+
+	return ae;
+}
+
 static int bq27x00_battery_status(struct bq27x00_device_info *di,
 				  union power_supply_propval *val)
 {
@@ -209,7 +310,9 @@ static int bq27x00_battery_status(struct
 		else
 			status = POWER_SUPPLY_STATUS_CHARGING;
 	} else {
-		if (flags & BQ27000_FLAG_CHGS)
+		if (flags & BQ27000_FLAG_FC)
+			status = POWER_SUPPLY_STATUS_FULL;
+		else if (flags & BQ27000_FLAG_CHGS)
 			status = POWER_SUPPLY_STATUS_CHARGING;
 		else
 			status = POWER_SUPPLY_STATUS_DISCHARGING;
@@ -256,6 +359,9 @@ static int bq27x00_battery_get_property(
 	case POWER_SUPPLY_PROP_STATUS:
 		ret = bq27x00_battery_status(di, val);
 		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = bq27x00_battery_gpio(di);
+		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = bq27x00_battery_voltage(di);
@@ -268,6 +374,15 @@ static int bq27x00_battery_get_property(
 	case POWER_SUPPLY_PROP_CAPACITY:
 		val->intval = bq27x00_battery_rsoc(di);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		val->intval = bq27x00_battery_nac(di);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = bq27x00_battery_lmd(di);
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_NOW:
+		val->intval = bq27x00_battery_energy(di);
+		break;
 	case POWER_SUPPLY_PROP_TEMP:
 		val->intval = bq27x00_battery_temperature(di);
 		break;
@@ -472,4 +587,7 @@ module_exit(bq27x00_battery_exit);
 
 MODULE_AUTHOR("Rodolfo Giometti <[email protected]>");
 MODULE_DESCRIPTION("BQ27x00 battery monitor driver");
+MODULE_ALIAS("i2c:bq27000");
+MODULE_ALIAS("i2c:bq27200");
+MODULE_ALIAS("i2c:bq27500");
 MODULE_LICENSE("GPL");

----- End forwarded message -----

#1 lore raw
Quoted 22 lines · Anton Vorontsov

Forwarding this to lkml and bq27x00 hackers.

Comments, Reviewed-by or Acked-by?

----- Forwarded message from Pali Rohár <[email protected]> -----

Date: Wed, 26 Jan 2011 21:44:08 +0100
From: Pali Rohár <[email protected]>
To: Anton Vorontsov <[email protected]>
Cc: David Woodhouse <[email protected]>
Subject: Re: [PATCH] bq27x00_battery

This patch add support for properties POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_ENERGY_NOW, POWER_SUPPLY_PROP_ONLINE in module bq27x00_battery.

drivers/power/bq27x00_battery.c line 6

Quoted 4 lines
drivers/power/bq27x00_battery.c +1 -0
@@ -3,9 +3,14 @@
  *
  * Copyright (C) 2008 Rodolfo Giometti <[email protected]>
  * Copyright (C) 2008 Eurotech S.p.A. <[email protected]>
+ * Copyright (C) 2011 Pali Rohár <[email protected]>

I think you should put your copyright on the changes you did:
i.e. GPIO settings and so on. Example:

* GPIO setting/management and ... by Pali Rohár <[email protected]>
* Copyright (C) 2011

drivers/power/bq27x00_battery.c line 13

Quoted 7 lines
drivers/power/bq27x00_battery.c +4 -0
  *
  * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
  *
+ * Datasheets:
+ * http://focus.ti.com/docs/prod/folders/print/bq27000.html
+ * http://focus.ti.com/docs/prod/folders/print/bq27500.html
+ *

Don't mix copyright messages with info ones. Put these info at the end of this into text.

Quoted 45 lines
drivers/power/bq27x00_battery.c +10 -1
  * This package is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -27,8 +32,9 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
-#define DRIVER_VERSION			"1.1.0"
+#define DRIVER_VERSION			"1.2.0"
 
+#define BQ27x00_REG_MODE		0x00
 #define BQ27x00_REG_TEMP		0x06
 #define BQ27x00_REG_VOLT		0x08
 #define BQ27x00_REG_AI			0x14
@@ -36,10 +42,14 @@
 #define BQ27x00_REG_TTE			0x16
 #define BQ27x00_REG_TTF			0x18
 #define BQ27x00_REG_TTECP		0x26
+#define BQ27x00_REG_NAC			0x0C /* Nominal available capaciy */
+#define BQ27x00_REG_LMD			0x12 /* Last measured discharge */
+#define BQ27x00_REG_AE			0x22 /* Available Enery */
 
 #define BQ27000_RS			20 /* Resistor sense */
 #define BQ27000_REG_RSOC		0x0B /* Relative State-of-Charge */
 #define BQ27000_FLAG_CHGS		BIT(7)
+#define BQ27000_FLAG_FC			BIT(5)
 
 #define BQ27500_REG_SOC			0x2C
 #define BQ27500_FLAG_DSC		BIT(0)
@@ -75,7 +85,11 @@ static enum power_supply_property bq27x0
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
 	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
 	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
@@ -92,6 +106,24 @@ static int bq27x00_read(u8 reg, int *rt_
 }
 
 /*

drivers/power/bq27x00_battery.c static int bq27x00_read(u8 reg, int *rt_ · line 118

Quoted 10 lines
drivers/power/bq27x00_battery.c +10 -0
+ * Return the GPIO status (0 or 1)
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_gpio(struct bq27x00_device_info *di)
+{
+	int ret;
+	int gpio = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_MODE, &gpio, 0, di);
+	if (ret) {

I think you should use ret < 0.

drivers/power/bq27x00_battery.c static int bq27x00_read(u8 reg, int *rt_ · line 123

Quoted 5 lines
drivers/power/bq27x00_battery.c +5 -0
+		dev_err(di->dev, "error reading GPIO status\n");
+		return ret;
+	}
+
+	return (gpio & 0x40) >> 6;

Why not using:

!!(gpio & 0x40)

or

(gpio & 0x40) ? 1 : 0

? I think it could be more readable... :)

However, I don't understand why you fix gpio=0... it's your machine depending settings? In these case you should use the platform_data mechanism to properly setup the GPIO.

Quoted 7 lines
drivers/power/bq27x00_battery.c +3 -0
+}
+
+/*
  * Return the battery temperature in tenths of degree Celsius
  * Or < 0 if something fails.
  */

drivers/power/bq27x00_battery.c static int bq27x00_battery_rsoc(struct b · line 227

Quoted 8 lines
drivers/power/bq27x00_battery.c +5 -0
@@ -188,6 +220,75 @@ static int bq27x00_battery_rsoc(struct b
 	return rsoc;
 }
 
+/*
+ * Return the battery Nominal available capaciy in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_nac(struct bq27x00_device_info *di)

Let me suggest using bq27x00_battery_nac_uAh as function name...

drivers/power/bq27x00_battery.c static int bq27x00_battery_rsoc(struct b · line 233

Quoted 6 lines
drivers/power/bq27x00_battery.c +6 -0
+{
+	int ret;
+	int nac = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_NAC, &nac, 0, di);
+	if (ret) {

Ditto.

Quoted 7 lines
drivers/power/bq27x00_battery.c +7 -0
+		dev_err(di->dev, "error reading nominal available capaciy\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500)
+		nac *= 1000;
+	else

drivers/power/bq27x00_battery.c static int bq27x00_battery_rsoc(struct b · line 250

Quoted 10 lines
drivers/power/bq27x00_battery.c +10 -0
+		nac = nac * 3570 / BQ27000_RS;
+
+	return nac;
+}
+
+/*
+ * Return the battery Last measured discharge in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_lmd(struct bq27x00_device_info *di)

bq27x00_battery_lmd_uAh

drivers/power/bq27x00_battery.c static int bq27x00_battery_rsoc(struct b · line 256

Quoted 6 lines
drivers/power/bq27x00_battery.c +6 -0
+{
+	int ret;
+	int lmd = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_LMD, &lmd, 0, di);
+	if (ret) {

Ditto.

Quoted 7 lines
drivers/power/bq27x00_battery.c +7 -0
+		dev_err(di->dev, "error reading last measured discharge\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500)
+		lmd *= 1000;
+	else

drivers/power/bq27x00_battery.c static int bq27x00_battery_rsoc(struct b · line 273

Quoted 10 lines
drivers/power/bq27x00_battery.c +10 -0
+		lmd = lmd * 3570 / BQ27000_RS;
+
+	return lmd;
+}
+
+/*
+ * Return the battery Available energy in µWh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_energy(struct bq27x00_device_info *di)

bq27x00_battery_energy_uWh

drivers/power/bq27x00_battery.c static int bq27x00_battery_rsoc(struct b · line 279

Quoted 6 lines
drivers/power/bq27x00_battery.c +6 -0
+{
+	int ret;
+	int ae = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_LMD, &ae, 0, di);
+	if (ret) {

Ditto.

Quoted 62 lines
drivers/power/bq27x00_battery.c +30 -2
+		dev_err(di->dev, "error reading available energy\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500)
+		ae *= 1000;
+	else
+		ae = ae * 29200 / BQ27000_RS;
+
+	return ae;
+}
+
 static int bq27x00_battery_status(struct bq27x00_device_info *di,
 				  union power_supply_propval *val)
 {
@@ -209,7 +310,9 @@ static int bq27x00_battery_status(struct
 		else
 			status = POWER_SUPPLY_STATUS_CHARGING;
 	} else {
-		if (flags & BQ27000_FLAG_CHGS)
+		if (flags & BQ27000_FLAG_FC)
+			status = POWER_SUPPLY_STATUS_FULL;
+		else if (flags & BQ27000_FLAG_CHGS)
 			status = POWER_SUPPLY_STATUS_CHARGING;
 		else
 			status = POWER_SUPPLY_STATUS_DISCHARGING;
@@ -256,6 +359,9 @@ static int bq27x00_battery_get_property(
 	case POWER_SUPPLY_PROP_STATUS:
 		ret = bq27x00_battery_status(di, val);
 		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = bq27x00_battery_gpio(di);
+		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = bq27x00_battery_voltage(di);
@@ -268,6 +374,15 @@ static int bq27x00_battery_get_property(
 	case POWER_SUPPLY_PROP_CAPACITY:
 		val->intval = bq27x00_battery_rsoc(di);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		val->intval = bq27x00_battery_nac(di);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = bq27x00_battery_lmd(di);
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_NOW:
+		val->intval = bq27x00_battery_energy(di);
+		break;
 	case POWER_SUPPLY_PROP_TEMP:
 		val->intval = bq27x00_battery_temperature(di);
 		break;
@@ -472,4 +587,7 @@ module_exit(bq27x00_battery_exit);
 
 MODULE_AUTHOR("Rodolfo Giometti <[email protected]>");
 MODULE_DESCRIPTION("BQ27x00 battery monitor driver");
+MODULE_ALIAS("i2c:bq27000");
+MODULE_ALIAS("i2c:bq27200");
+MODULE_ALIAS("i2c:bq27500");
 MODULE_LICENSE("GPL");
 
----- End forwarded message -----
Signature · 5 lines
GNU/Linux Solutions                  e-mail: [email protected]
Linux Device Driver                          [email protected]
Embedded Systems                     phone:  +39 349 2432127
UNIX programming                     skype:  rodolfo.giometti
Freelance ICT Italia - Consulente ICT Italia - www.consulenti-ict.it
#2 lore raw
Quoted 1 line · Rodolfo Giometti

On Mon, Jan 31, 2011 at 04:51:47PM +0300, Anton Vorontsov wrote:

[...]

Quoted 6 lines

Why not using:

   !!(gpio & 0x40)

or

Quoted 7 lines
   (gpio & 0x40) ? 1 : 0

? I think it could be more readable... :)

However, I don't understand why you fix gpio=0... it's your machine depending settings? In these case you should use the platform_data mechanism to properly setup the GPIO.

I agree. It looks like a machine-specific configuration, and exporting this GPIO as 'ONLINE' property may break other users.

Instead, I would suggest adding gpiolib support into this driver, and passing 'int online_gpio' via platform data. That way you can pass any GPIOs to this driver, not only bq's.

Pali, you can just split GPIO and 'ONLINE' property additions into a separate patch for now, so we can apply the rest of the changes, and hold on the GPIO stuff.

[...]

Quoted 3 lines
Quoted 1 line

+static int bq27x00_battery_nac(struct bq27x00_device_info *di)

Let me suggest using bq27x00_battery_nac_uAh as function name...

Regarding these suffixes. I'm not sure. This seems a bit too verbose. So I'd prefer to not introduce these.

Though, whatever you guys like... I'm fine either way.

[...]

Quoted 5 lines

drivers/power/bq27x00_battery.c module_exit(bq27x00_battery_exit); · line 592

Quoted 5 lines

MODULE_AUTHOR("Rodolfo Giometti <[email protected]>"); MODULE_DESCRIPTION("BQ27x00 battery monitor driver");

drivers/power/bq27x00_battery.c +3 -0
+MODULE_ALIAS("i2c:bq27000");
+MODULE_ALIAS("i2c:bq27200");
+MODULE_ALIAS("i2c:bq27500");

Btw, this is actually another bugfix. Pali, you might want to separate it into yet another patch.

Thanks!

Signature · 2 lines
Anton Vorontsov
Email: [email protected]
#3 lore raw

2011/1/31 Anton Vorontsov <[email protected]>:

Quoted 20 lines · Rodolfo Giometti
Quoted 1 line · Anton Vorontsov

[...]

Quoted 6 lines

Why not using:

   !!(gpio & 0x40)

or

Quoted 7 lines

   (gpio & 0x40) ? 1 : 0

? I think it could be more readable... :)

However, I don't understand why you fix gpio=0... it's your machine depending settings? In these case you should use the platform_data mechanism to properly setup the GPIO.

I agree. It looks like a machine-specific configuration, and exporting this GPIO as 'ONLINE' property may break other users.

Quoted 7 lines

Instead, I would suggest adding gpiolib support into this driver, and passing 'int online_gpio' via platform data. That way you can pass any GPIOs to this driver, not only bq's.

Pali, you can just split GPIO and 'ONLINE' property additions into a separate patch for now, so we can apply the rest of the changes, and hold on the GPIO stuff.

Ok, I delete GPIO and ONLINE additions from this patch.

Quoted 10 lines

[...]

Quoted 3 lines
Quoted 1 line

+static int bq27x00_battery_nac(struct bq27x00_device_info *di)

Let me suggest using bq27x00_battery_nac_uAh as function name...

Regarding these suffixes. I'm not sure. This seems a bit too verbose. So I'd prefer to not introduce these.

Though, whatever you guys like... I'm fine either way.

It think it is not needed to rename functions. In Documentation/power/power_supply_class.txt is written that default units are µA, µV, µAh, ... and functions in my patch return values in these correct units.

Quoted 10 lines

[...]

Quoted 5 lines

drivers/power/bq27x00_battery.c module_exit(bq27x00_battery_exit); · line 592

Quoted 5 lines

 MODULE_AUTHOR("Rodolfo Giometti <[email protected]>"); MODULE_DESCRIPTION("BQ27x00 battery monitor driver");

drivers/power/bq27x00_battery.c +3 -0
+MODULE_ALIAS("i2c:bq27000");
+MODULE_ALIAS("i2c:bq27200");
+MODULE_ALIAS("i2c:bq27500");

Btw, this is actually another bugfix. Pali, you might want to separate it into yet another patch.

Ok, I separate aliases to new patch.

Quoted 7 lines

Thanks!

--
Anton Vorontsov
Email: [email protected]

Signature · 2 lines
Pali Rohár
[email protected]
#4 lore raw
Quoted 58 lines · Pali Rohár

2011/1/31 Anton Vorontsov <[email protected]>:

Quoted 20 lines · Rodolfo Giometti
Quoted 1 line · Anton Vorontsov

[...]

Quoted 6 lines

Why not using:

   !!(gpio & 0x40)

or

Quoted 7 lines
   (gpio & 0x40) ? 1 : 0

? I think it could be more readable... :)

However, I don't understand why you fix gpio=0... it's your machine depending settings? In these case you should use the platform_data mechanism to properly setup the GPIO.

I agree. It looks like a machine-specific configuration, and exporting this GPIO as 'ONLINE' property may break other users.

Quoted 7 lines

Instead, I would suggest adding gpiolib support into this driver, and passing 'int online_gpio' via platform data. That way you can pass any GPIOs to this driver, not only bq's.

Pali, you can just split GPIO and 'ONLINE' property additions into a separate patch for now, so we can apply the rest of the changes, and hold on the GPIO stuff.

Ok, I delete GPIO and ONLINE additions from this patch.

Quoted 10 lines

[...]

Quoted 3 lines
Quoted 1 line

+static int bq27x00_battery_nac(struct bq27x00_device_info *di)

Let me suggest using bq27x00_battery_nac_uAh as function name...

Regarding these suffixes. I'm not sure. This seems a bit too verbose. So I'd prefer to not introduce these.

Though, whatever you guys like... I'm fine either way.

It think it is not needed to rename functions. In Documentation/power/power_supply_class.txt is written that default units are µA, µV, µAh, ... and functions in my patch return values in these correct units.

Quoted 10 lines

[...]

Quoted 5 lines

drivers/power/bq27x00_battery.c module_exit(bq27x00_battery_exit); · line 592

Quoted 5 lines

MODULE_AUTHOR("Rodolfo Giometti <[email protected]>"); MODULE_DESCRIPTION("BQ27x00 battery monitor driver");

drivers/power/bq27x00_battery.c +3 -0
+MODULE_ALIAS("i2c:bq27000");
+MODULE_ALIAS("i2c:bq27200");
+MODULE_ALIAS("i2c:bq27500");

Btw, this is actually another bugfix. Pali, you might want to separate it into yet another patch.

Quoted 2 lines

Ok, I separate aliases to new patch.

The bq27000 is not an I2C device.

- Lars

Quoted 10 lines
Quoted 7 lines

Thanks!

--
Anton Vorontsov
Email: [email protected]

#5 lore raw
Quoted 11 lines · Lars-Peter Clausen
Quoted 9 lines · Pali Roh??r

2011/1/31 Anton Vorontsov <[email protected]>:

Quoted 8 lines · Rodolfo Giometti
Quoted 4 lines

drivers/power/bq27x00_battery.c module_exit(bq27x00_battery_exit); · line 592

Quoted 4 lines
drivers/power/bq27x00_battery.c +3 -0
+MODULE_ALIAS("i2c:bq27000");
+MODULE_ALIAS("i2c:bq27200");
+MODULE_ALIAS("i2c:bq27500");

Btw, this is actually another bugfix. Pali, you might want to separate it into yet another patch.

Quoted 3 lines
Quoted 1 line

Ok, I separate aliases to new patch.

The bq27000 is not an I2C device.

Also, even if it were an I2C device this isn't how I2C devices get their module loading information set up - they use MODULE_DEVICE_TABLE().

#6 lore raw

2011/1/31 Mark Brown <[email protected]>:

Quoted 12 lines · Lars-Peter Clausen
Quoted 10 lines · Pali Roh??r
Quoted 9 lines

2011/1/31 Anton Vorontsov <[email protected]>:

Quoted 8 lines · Rodolfo Giometti
Quoted 4 lines

drivers/power/bq27x00_battery.c module_exit(bq27x00_battery_exit); · line 592

Quoted 4 lines
drivers/power/bq27x00_battery.c +3 -0
+MODULE_ALIAS("i2c:bq27000");
+MODULE_ALIAS("i2c:bq27200");
+MODULE_ALIAS("i2c:bq27500");

Btw, this is actually another bugfix. Pali, you might want to separate it into yet another patch.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

Ok, I separate aliases to new patch.

The bq27000 is not an I2C device.

Also, even if it were an I2C device this isn't how I2C devices get their module loading information set up - they use MODULE_DEVICE_TABLE().

If bq27000 is not I2C device it will remove line. My patch was primary for Nokia N900 - RX51 board and it has battery bq27200 which is i2c device. For autoloading this module I used MODULE_ALIAS("i2c:bq27200") which works fine. Aliases was used in other i2c modules for Nokia N900 too.

Can you give me example how to use MODULE_DEVICE_TABLE (if alias is not good solution)?

Signature · 2 lines
Pali Rohár
[email protected]
#7 lore raw
Quoted 2 lines · Pali Rohár

Can you give me example how to use MODULE_DEVICE_TABLE (if alias is not good solution)?

git grep MODULE_DEVICE_TABLE\(i2c

provides quite a few examples.

#8 lore raw

2011/1/31 Mark Brown <[email protected]>:

Quoted 9 lines · Pali Rohár
Quoted 3 lines

Can you give me example how to use MODULE_DEVICE_TABLE (if alias is not good solution)?

git grep MODULE_DEVICE_TABLE\(i2c

provides quite a few examples.

Thanks. I removed MODULE_ALIAS and added MODULE_DEVICE_TABLE. modinfo tell me that module has alias too (same as my defined).

Signature · 2 lines
Pali Rohár
[email protected]
Tested-by
#9 lore raw

This patch adds MODULE_DEVICE_TABLE for module bq27x00_battery.

drivers/power/bq27x00_battery.c 2011-01-31 20:57:05.000000000 +0100 renamed from drivers/power/bq27x00_battery.c 2011-01-31 20:58:11.000000000 +0100 +1 -0
@@ -596,6 +596,7 @@ static const struct i2c_device_id bq27x0
        { "bq27500", BQ27500 },
        {},
 };
+MODULE_DEVICE_TABLE(i2c, bq27x00_id);
 
 static struct i2c_driver bq27x00_battery_driver = {
        .driver = {
#10 lore raw
Quoted 4 lines · Pali Rohár

This patch adds MODULE_DEVICE_TABLE for module bq27x00_battery.

Lars, if that's OK for you, please take Pali's patches via your tree. I can merge it into battery-2.6.git on request (and after review, of course).

Thanks!

Quoted 11 lines
drivers/power/bq27x00_battery.c 2011-01-31 20:57:05.000000000 +0100 renamed from drivers/power/bq27x00_battery.c 2011-01-31 20:58:11.000000000 +0100 +1 -0
@@ -596,6 +596,7 @@ static const struct i2c_device_id bq27x0
        { "bq27500", BQ27500 },
        {},
 };
+MODULE_DEVICE_TABLE(i2c, bq27x00_id);
 
 static struct i2c_driver bq27x00_battery_driver = {
        .driver = {
Signature · 2 lines
Anton Vorontsov
Email: [email protected]
#11 lore raw
Quoted 12 lines · Anton Vorontsov
Quoted 4 lines · Pali Rohár

This patch adds MODULE_DEVICE_TABLE for module bq27x00_battery.

Lars, if that's OK for you, please take Pali's patches via your tree. I can merge it into battery-2.6.git on request (and after review, of course).

Thanks!

I'll do. Thanks

- Lars

Quoted 12 lines
Quoted 11 lines
drivers/power/bq27x00_battery.c 2011-01-31 20:57:05.000000000 +0100 renamed from drivers/power/bq27x00_battery.c 2011-01-31 20:58:11.000000000 +0100 +1 -0
@@ -596,6 +596,7 @@ static const struct i2c_device_id bq27x0
        { "bq27500", BQ27500 },
        {},
 };
+MODULE_DEVICE_TABLE(i2c, bq27x00_id);
 
 static struct i2c_driver bq27x00_battery_driver = {
        .driver = {
Tested-by
#12 lore raw
In reply to Pali Rohár

Here is new patch. It is possible to merge it then with changes on git?

===

This patch add support for reporting properties POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_ENERGY_NOW in module bq27x00_battery.

drivers/power/bq27x00_battery.c 2011-01-31 18:43:16.000000000 +0100 renamed from drivers/power/bq27x00_battery.c 2011-01-31 17:45:01.000000000 +0100 +14 -1
@@ -4,6 +4,11 @@
  * Copyright (C) 2008 Rodolfo Giometti <[email protected]>
  * Copyright (C) 2008 Eurotech S.p.A. <[email protected]>
  *
+ * Support for reporting properties: POWER_SUPPLY_PROP_CHARGE_NOW,
+ * POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ * POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_ENERGY_NOW
+ *   Copyright (C) 2011 Pali Rohár <[email protected]>
+ *
  * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
  *
  * This package is free software; you can redistribute it and/or modify
@@ -15,6 +20,13 @@
  * 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
+ */
+
 #include <linux/module.h>
 #include <linux/param.h>
 #include <linux/jiffies.h>
@@ -27,7 +39,7 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
-#define DRIVER_VERSION                 "1.1.0"
+#define DRIVER_VERSION                 "1.2.0"
 
 #define BQ27x00_REG_TEMP               0x06
 #define BQ27x00_REG_VOLT               0x08
@@ -36,12 +48,19 @@
 #define BQ27x00_REG_TTE                        0x16
 #define BQ27x00_REG_TTF                        0x18
 #define BQ27x00_REG_TTECP              0x26
+#define BQ27x00_REG_NAC                        0x0C /* Nominal

available capaciy */
+#define BQ27x00_REG_LMD 0x12 /* Last measured
discharge */
+#define BQ27x00_REG_CYCT 0x2A /* Cycle count total */
+#define BQ27x00_REG_AE 0x22 /* Available enery */

 #define BQ27000_RS                     20 /* Resistor sense */
 #define BQ27000_REG_RSOC               0x0B /* Relative State-of-Charge */
+#define BQ27000_REG_ILMD               0x76 /* Initial last measured

discharge */
#define BQ27000_FLAG_CHGS BIT(7)
+#define BQ27000_FLAG_FC BIT(5)

#define BQ27500_REG_SOC 0x2C
+#define BQ27500_REG_DCAP 0x3C /* Design capacity */
#define BQ27500_FLAG_DSC BIT(0)
#define BQ27500_FLAG_FC BIT(9)

@@ -75,6 +94,11 @@ static enum power_supply_property bq27x0
POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CAPACITY,

+       POWER_SUPPLY_PROP_CHARGE_NOW,
+       POWER_SUPPLY_PROP_CHARGE_FULL,
+       POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+       POWER_SUPPLY_PROP_CHARGE_COUNTER,
+       POWER_SUPPLY_PROP_ENERGY_NOW,

POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
@@ -188,6 +212,119 @@ static int bq27x00_battery_rsoc(struct b

        return rsoc;

}

+/*
+ * Return the battery Nominal available capaciy in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_nac(struct bq27x00_device_info *di) +{
+ int ret;
+ int nac = 0;
+
+ ret = bq27x00_read(BQ27x00_REG_NAC, &nac, 0, di);
+ if (ret) {
+ dev_err(di->dev, "error reading nominal available capacity\n");
+ return ret;
+ }
+
+ if (di->chip == BQ27500)
+ nac *= 1000;
+ else
+ nac = nac * 3570 / BQ27000_RS;
+
+ return nac;
+}
+
+/*
+ * Return the battery Last measured discharge in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_lmd(struct bq27x00_device_info *di) +{
+ int ret;
+ int lmd = 0;
+
+ ret = bq27x00_read(BQ27x00_REG_LMD, &lmd, 0, di);
+ if (ret) {
+ dev_err(di->dev, "error reading last measured discharge\n");
+ return ret;
+ }
+
+ if (di->chip == BQ27500)
+ lmd *= 1000;
+ else
+ lmd = lmd * 3570 / BQ27000_RS;
+
+ return lmd;
+}
+
+/*
+ * Return the battery Initial last measured discharge in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_ilmd(struct bq27x00_device_info *di) +{
+ int ret;
+ int ilmd = 0;
+
+ if (di->chip == BQ27500)
+ ret = bq27x00_read(BQ27500_REG_DCAP, &ilmd, 0, di);
+ else
+ ret = bq27x00_read(BQ27000_REG_ILMD, &ilmd, 0, di);
+ if (ret) {
+ dev_err(di->dev, "error reading initial last measured
discharge\n");
+ return ret;
+ }
+
+ if (di->chip == BQ27500)
+ ilmd *= 1000;
+ else
+ ilmd = ilmd * 256 * 3570 / BQ27000_RS;
+
+ return ilmd;
+}
+
+/*
+ * Return the battery Cycle count total
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_cyct(struct bq27x00_device_info *di) +{
+ int ret;
+ int cyct = 0;
+
+ ret = bq27x00_read(BQ27x00_REG_CYCT, &cyct, 0, di);
+ if (ret) {
+ dev_err(di->dev, "error reading cycle count total\n");
+ return ret;
+ }
+
+ return cyct;
+}
+
+/*
+ * Return the battery Available energy in µWh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_energy(struct bq27x00_device_info *di) +{
+ int ret;
+ int ae = 0;
+
+ ret = bq27x00_read(BQ27x00_REG_LMD, &ae, 0, di);
+ if (ret) {
+ dev_err(di->dev, "error reading available energy\n");
+ return ret;
+ }
+
+ if (di->chip == BQ27500)
+ ae *= 1000;
+ else
+ ae = ae * 29200 / BQ27000_RS;
+
+ return ae;
+}
+
static int bq27x00_battery_status(struct bq27x00_device_info *di,
union power_supply_propval *val)
{
@@ -209,7 +346,9 @@ static int bq27x00_battery_status(struct

                else
                        status = POWER_SUPPLY_STATUS_CHARGING;
        } else {

- if (flags & BQ27000_FLAG_CHGS)
+ if (flags & BQ27000_FLAG_FC)
+ status = POWER_SUPPLY_STATUS_FULL;
+ else if (flags & BQ27000_FLAG_CHGS)

                        status = POWER_SUPPLY_STATUS_CHARGING;
                else
                        status = POWER_SUPPLY_STATUS_DISCHARGING;
@@ -268,6 +407,21 @@ static int bq27x00_battery_get_property(
        case POWER_SUPPLY_PROP_CAPACITY:
                val->intval = bq27x00_battery_rsoc(di);
                break;

+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = bq27x00_battery_nac(di);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ val->intval = bq27x00_battery_lmd(di);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = bq27x00_battery_ilmd(di);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+ val->intval = bq27x00_battery_cyct(di);
+ break;
+ case POWER_SUPPLY_PROP_ENERGY_NOW:
+ val->intval = bq27x00_battery_energy(di);

+               break;
        case POWER_SUPPLY_PROP_TEMP:
                val->intval = bq27x00_battery_temperature(di);
                break;
#13 lore raw

Hi Pali

Your mail-client seems to mess up the patches whitespace(tabs converted to spaces, trailing whitespace truncated, etc). Could you resend the patches properly formated? I guess there is an option in your mail-client somewhere to disable it from chaning the messages whitespace. Otherwise you could try to use the git send-email tool.

- Lars

Quoted 239 lines · Pali Rohár

Here is new patch. It is possible to merge it then with changes on git?

===

This patch add support for reporting properties POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_ENERGY_NOW in module bq27x00_battery.

drivers/power/bq27x00_battery.c 2011-01-31 18:43:16.000000000 +0100 renamed from drivers/power/bq27x00_battery.c 2011-01-31 17:45:01.000000000 +0100 +14 -1
@@ -4,6 +4,11 @@
  * Copyright (C) 2008 Rodolfo Giometti <[email protected]>
  * Copyright (C) 2008 Eurotech S.p.A. <[email protected]>
  *
+ * Support for reporting properties: POWER_SUPPLY_PROP_CHARGE_NOW,
+ * POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ * POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_ENERGY_NOW
+ *   Copyright (C) 2011 Pali Rohár <[email protected]>
+ *
  * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
  *
  * This package is free software; you can redistribute it and/or modify
@@ -15,6 +20,13 @@
  * 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
+ */
+
 #include <linux/module.h>
 #include <linux/param.h>
 #include <linux/jiffies.h>
@@ -27,7 +39,7 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
-#define DRIVER_VERSION                 "1.1.0"
+#define DRIVER_VERSION                 "1.2.0"
 
 #define BQ27x00_REG_TEMP               0x06
 #define BQ27x00_REG_VOLT               0x08
@@ -36,12 +48,19 @@
 #define BQ27x00_REG_TTE                        0x16
 #define BQ27x00_REG_TTF                        0x18
 #define BQ27x00_REG_TTECP              0x26
+#define BQ27x00_REG_NAC                        0x0C /* Nominal

available capaciy */
+#define BQ27x00_REG_LMD 0x12 /* Last measured
discharge */

drivers/power/bq27x00_battery.c 2011-01-31 18:43:16.000000000 +0100 renamed from drivers/power/bq27x00_battery.c 2011-01-31 17:45:01.000000000 +0100 +3 -0
+#define BQ27x00_REG_CYCT               0x2A /* Cycle count total */
+#define BQ27x00_REG_AE                 0x22 /* Available enery */
 
 #define BQ27000_RS                     20 /* Resistor sense */
 #define BQ27000_REG_RSOC               0x0B /* Relative State-of-Charge */
+#define BQ27000_REG_ILMD               0x76 /* Initial last measured

discharge */
#define BQ27000_FLAG_CHGS BIT(7)

drivers/power/bq27x00_battery.c 2011-01-31 18:43:16.000000000 +0100 renamed from drivers/power/bq27x00_battery.c 2011-01-31 17:45:01.000000000 +0100 +120 -0
+#define BQ27000_FLAG_FC                        BIT(5)
 
 #define BQ27500_REG_SOC                        0x2C
+#define BQ27500_REG_DCAP               0x3C /* Design capacity */
 #define BQ27500_FLAG_DSC               BIT(0)
 #define BQ27500_FLAG_FC                        BIT(9)
@@ -75,6 +94,11 @@ static enum power_supply_property bq27x0
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_CURRENT_NOW,
        POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_CHARGE_NOW,
+       POWER_SUPPLY_PROP_CHARGE_FULL,
+       POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+       POWER_SUPPLY_PROP_CHARGE_COUNTER,
+       POWER_SUPPLY_PROP_ENERGY_NOW,
        POWER_SUPPLY_PROP_TEMP,
        POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
        POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
@@ -188,6 +212,119 @@ static int bq27x00_battery_rsoc(struct b
        return rsoc;
 }
 
+/*
+ * Return the battery Nominal available capaciy in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_nac(struct bq27x00_device_info *di)
+{
+       int ret;
+       int nac = 0;
+
+       ret = bq27x00_read(BQ27x00_REG_NAC, &nac, 0, di);
+       if (ret) {
+               dev_err(di->dev, "error reading nominal available capacity\n");
+               return ret;
+       }
+
+       if (di->chip == BQ27500)
+               nac *= 1000;
+       else
+               nac = nac * 3570 / BQ27000_RS;
+
+       return nac;
+}
+
+/*
+ * Return the battery Last measured discharge in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_lmd(struct bq27x00_device_info *di)
+{
+       int ret;
+       int lmd = 0;
+
+       ret = bq27x00_read(BQ27x00_REG_LMD, &lmd, 0, di);
+       if (ret) {
+               dev_err(di->dev, "error reading last measured discharge\n");
+               return ret;
+       }
+
+       if (di->chip == BQ27500)
+               lmd *= 1000;
+       else
+               lmd = lmd * 3570 / BQ27000_RS;
+
+       return lmd;
+}
+
+/*
+ * Return the battery Initial last measured discharge in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_ilmd(struct bq27x00_device_info *di)
+{
+       int ret;
+       int ilmd = 0;
+
+       if (di->chip == BQ27500)
+               ret = bq27x00_read(BQ27500_REG_DCAP, &ilmd, 0, di);
+       else
+               ret = bq27x00_read(BQ27000_REG_ILMD, &ilmd, 0, di);
+       if (ret) {
+               dev_err(di->dev, "error reading initial last measured
 discharge\n");
+               return ret;
+       }
+
+       if (di->chip == BQ27500)
+               ilmd *= 1000;
+       else
+               ilmd = ilmd * 256 * 3570 / BQ27000_RS;
+
+       return ilmd;
+}
+
+/*
+ * Return the battery Cycle count total
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_cyct(struct bq27x00_device_info *di)
+{
+       int ret;
+       int cyct = 0;
+
+       ret = bq27x00_read(BQ27x00_REG_CYCT, &cyct, 0, di);
+       if (ret) {
+               dev_err(di->dev, "error reading cycle count total\n");
+               return ret;
+       }
+
+       return cyct;
+}
+
+/*
+ * Return the battery Available energy in µWh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_energy(struct bq27x00_device_info *di)
+{
+       int ret;
+       int ae = 0;
+
+       ret = bq27x00_read(BQ27x00_REG_LMD, &ae, 0, di);
+       if (ret) {
+               dev_err(di->dev, "error reading available energy\n");
+               return ret;
+       }
+
+       if (di->chip == BQ27500)
+               ae *= 1000;
+       else
+               ae = ae * 29200 / BQ27000_RS;
+
+       return ae;
+}
+
 static int bq27x00_battery_status(struct bq27x00_device_info *di,
                                  union power_supply_propval *val)

{

drivers/power/bq27x00_battery.c 2011-01-31 18:43:16.000000000 +0100 renamed from drivers/power/bq27x00_battery.c 2011-01-31 17:45:01.000000000 +0100 +18 -1
@@ -209,7 +346,9 @@ static int bq27x00_battery_status(struct
                else
                        status = POWER_SUPPLY_STATUS_CHARGING;
        } else {
-               if (flags & BQ27000_FLAG_CHGS)
+               if (flags & BQ27000_FLAG_FC)
+                       status = POWER_SUPPLY_STATUS_FULL;
+               else if (flags & BQ27000_FLAG_CHGS)
                        status = POWER_SUPPLY_STATUS_CHARGING;
                else
                        status = POWER_SUPPLY_STATUS_DISCHARGING;
@@ -268,6 +407,21 @@ static int bq27x00_battery_get_property(
        case POWER_SUPPLY_PROP_CAPACITY:
                val->intval = bq27x00_battery_rsoc(di);
                break;
+       case POWER_SUPPLY_PROP_CHARGE_NOW:
+               val->intval = bq27x00_battery_nac(di);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_FULL:
+               val->intval = bq27x00_battery_lmd(di);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+               val->intval = bq27x00_battery_ilmd(di);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+               val->intval = bq27x00_battery_cyct(di);
+               break;
+       case POWER_SUPPLY_PROP_ENERGY_NOW:
+               val->intval = bq27x00_battery_energy(di);
+               break;
        case POWER_SUPPLY_PROP_TEMP:
                val->intval = bq27x00_battery_temperature(di);
                break;
Tested-by
#14 lore raw

This patch add support for reporting properties POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_ENERGY_NOW in module bq27x00_battery.

drivers/power/bq27x00_battery.c +156 -2
@@ -4,6 +4,11 @@
  * Copyright (C) 2008 Rodolfo Giometti <[email protected]>
  * Copyright (C) 2008 Eurotech S.p.A. <[email protected]>
  *
+ * Support for reporting properties: POWER_SUPPLY_PROP_CHARGE_NOW,
+ * POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ * POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_ENERGY_NOW
+ *   Copyright (C) 2011 Pali Rohár <[email protected]>
+ *
  * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
  *
  * This package is free software; you can redistribute it and/or modify
@@ -15,6 +20,13 @@
  * 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
+ */
+
 #include <linux/module.h>
 #include <linux/param.h>
 #include <linux/jiffies.h>
@@ -27,7 +39,7 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
-#define DRIVER_VERSION			"1.1.0"
+#define DRIVER_VERSION			"1.2.0"
 
 #define BQ27x00_REG_TEMP		0x06
 #define BQ27x00_REG_VOLT		0x08
@@ -36,12 +48,19 @@
 #define BQ27x00_REG_TTE			0x16
 #define BQ27x00_REG_TTF			0x18
 #define BQ27x00_REG_TTECP		0x26
+#define BQ27x00_REG_NAC			0x0C /* Nominal available capaciy */
+#define BQ27x00_REG_LMD			0x12 /* Last measured discharge */
+#define BQ27x00_REG_CYCT		0x2A /* Cycle count total */
+#define BQ27x00_REG_AE			0x22 /* Available enery */
 
 #define BQ27000_RS			20 /* Resistor sense */
 #define BQ27000_REG_RSOC		0x0B /* Relative State-of-Charge */
+#define BQ27000_REG_ILMD		0x76 /* Initial last measured discharge */
 #define BQ27000_FLAG_CHGS		BIT(7)
+#define BQ27000_FLAG_FC			BIT(5)
 
 #define BQ27500_REG_SOC			0x2C
+#define BQ27500_REG_DCAP		0x3C /* Design capacity */
 #define BQ27500_FLAG_DSC		BIT(0)
 #define BQ27500_FLAG_FC			BIT(9)
 
@@ -75,6 +94,11 @@ static enum power_supply_property bq27x0
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_COUNTER,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
@@ -188,6 +212,119 @@ static int bq27x00_battery_rsoc(struct b
 	return rsoc;
 }
 
+/*
+ * Return the battery Nominal available capaciy in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_nac(struct bq27x00_device_info *di)
+{
+	int ret;
+	int nac = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_NAC, &nac, 0, di);
+	if (ret) {
+		dev_err(di->dev, "error reading nominal available capacity\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500)
+		nac *= 1000;
+	else
+		nac = nac * 3570 / BQ27000_RS;
+
+	return nac;
+}
+
+/*
+ * Return the battery Last measured discharge in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_lmd(struct bq27x00_device_info *di)
+{
+	int ret;
+	int lmd = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_LMD, &lmd, 0, di);
+	if (ret) {
+		dev_err(di->dev, "error reading last measured discharge\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500)
+		lmd *= 1000;
+	else
+		lmd = lmd * 3570 / BQ27000_RS;
+
+	return lmd;
+}
+
+/*
+ * Return the battery Initial last measured discharge in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_ilmd(struct bq27x00_device_info *di)
+{
+	int ret;
+	int ilmd = 0;
+
+	if (di->chip == BQ27500)
+		ret = bq27x00_read(BQ27500_REG_DCAP, &ilmd, 0, di);
+	else
+		ret = bq27x00_read(BQ27000_REG_ILMD, &ilmd, 0, di);
+	if (ret) {
+		dev_err(di->dev, "error reading initial last measured discharge\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500)
+		ilmd *= 1000;
+	else
+		ilmd = ilmd * 256 * 3570 / BQ27000_RS;
+
+	return ilmd;
+}
+
+/*
+ * Return the battery Cycle count total
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_cyct(struct bq27x00_device_info *di)
+{
+	int ret;
+	int cyct = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_CYCT, &cyct, 0, di);
+	if (ret) {
+		dev_err(di->dev, "error reading cycle count total\n");
+		return ret;
+	}
+
+	return cyct;
+}
+
+/*
+ * Return the battery Available energy in µWh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_energy(struct bq27x00_device_info *di)
+{
+	int ret;
+	int ae = 0;
+
+	ret = bq27x00_read(BQ27x00_REG_LMD, &ae, 0, di);
+	if (ret) {
+		dev_err(di->dev, "error reading available energy\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500)
+		ae *= 1000;
+	else
+		ae = ae * 29200 / BQ27000_RS;
+
+	return ae;
+}
+
 static int bq27x00_battery_status(struct bq27x00_device_info *di,
 				  union power_supply_propval *val)
 {
@@ -209,7 +346,9 @@ static int bq27x00_battery_status(struct
 		else
 			status = POWER_SUPPLY_STATUS_CHARGING;
 	} else {
-		if (flags & BQ27000_FLAG_CHGS)
+		if (flags & BQ27000_FLAG_FC)
+			status = POWER_SUPPLY_STATUS_FULL;
+		else if (flags & BQ27000_FLAG_CHGS)
 			status = POWER_SUPPLY_STATUS_CHARGING;
 		else
 			status = POWER_SUPPLY_STATUS_DISCHARGING;
@@ -268,6 +407,21 @@ static int bq27x00_battery_get_property(
 	case POWER_SUPPLY_PROP_CAPACITY:
 		val->intval = bq27x00_battery_rsoc(di);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		val->intval = bq27x00_battery_nac(di);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = bq27x00_battery_lmd(di);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+		val->intval = bq27x00_battery_ilmd(di);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+		val->intval = bq27x00_battery_cyct(di);
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_NOW:
+		val->intval = bq27x00_battery_energy(di);
+		break;
 	case POWER_SUPPLY_PROP_TEMP:
 		val->intval = bq27x00_battery_temperature(di);
 		break;