[rfc/patch 04/15] power: bq27200: simplify read by using smbus

From: Felipe Balbi
Date: Sun Jul 12 2009 - 14:30:51 EST


the chip supports smbus protocol, so let's use it and simply
register read/write.

Signed-off-by: Felipe Balbi <me@xxxxxxxxxxxxxxx>
---
drivers/power/bq27200_battery.c | 135 ++++++++-------------------------------
1 files changed, 28 insertions(+), 107 deletions(-)

diff --git a/drivers/power/bq27200_battery.c b/drivers/power/bq27200_battery.c
index 3eb0f5a..eddb731 100644
--- a/drivers/power/bq27200_battery.c
+++ b/drivers/power/bq27200_battery.c
@@ -32,22 +32,14 @@
#define BQ27200_REG_AI 0x14
#define BQ27200_REG_FLAGS 0x0A

-struct bq27200_device_info;
-struct bq27200_access_methods {
- int (*read)(u8 reg, int *rt_value, int b_single,
- struct bq27200_device_info *di);
-};
-
struct bq27200_device_info {
- struct device *dev;
+ struct power_supply bat;
+ struct i2c_client *client;
+
+ int charge_rsoc;
int voltage_uV;
int current_uA;
int temp_C;
- int charge_rsoc;
- struct bq27200_access_methods *bus;
- struct power_supply bat;
-
- struct i2c_client *client;
};

#define to_bq27200_device_info(x) container_of((x), \
@@ -65,15 +57,15 @@ static enum power_supply_property bq27200_props[] = {
* Common code for BQ27200 devices
*/

-static int bq27200_read(u8 reg, int *rt_value, int b_single,
- struct bq27200_device_info *di)
+static inline int bq27200_read(struct bq27200_device_info *di, u8 reg)
{
- int ret;
-
- ret = di->bus->read(reg, rt_value, b_single, di);
- *rt_value = be16_to_cpu(*rt_value);
+ return i2c_smbus_read_word_data(di->client, reg);
+}

- return ret;
+static inline int bq27200_write(struct bq27200_device_info *di,
+ u8 reg, u8 data)
+{
+ return i2c_smbus_write_word_data(di->client, reg, data);
}

/*
@@ -83,15 +75,14 @@ static int bq27200_read(u8 reg, int *rt_value, int b_single,
static int bq27200_temperature(struct bq27200_device_info *di)
{
int ret;
- int temp = 0;

- ret = bq27200_read(BQ27200_REG_TEMP, &temp, 0, di);
- if (ret) {
- dev_err(di->dev, "error reading temperature\n");
+ ret = bq27200_read(di, BQ27200_REG_TEMP);
+ if (ret < 0) {
+ dev_err(&di->client->dev, "error reading temperature\n");
return ret;
}

- return (temp >> 2) - 273;
+ return (ret >> 2) - 273;
}

/*
@@ -101,15 +92,12 @@ static int bq27200_temperature(struct bq27200_device_info *di)
static int bq27200_voltage(struct bq27200_device_info *di)
{
int ret;
- int volt = 0;

- ret = bq27200_read(BQ27200_REG_VOLT, &volt, 0, di);
- if (ret) {
- dev_err(di->dev, "error reading voltage\n");
- return ret;
- }
+ ret = bq27200_read(di, BQ27200_REG_VOLT);
+ if (ret < 0)
+ dev_err(&di->client->dev, "error reading voltage\n");

- return volt;
+ return ret;
}

/*
@@ -120,25 +108,14 @@ static int bq27200_voltage(struct bq27200_device_info *di)
static int bq27200_current(struct bq27200_device_info *di)
{
int ret;
- int curr = 0;
- int flags = 0;

- ret = bq27200_read(BQ27200_REG_AI, &curr, 0, di);
- if (ret) {
- dev_err(di->dev, "error reading current\n");
- return 0;
- }
- ret = bq27200_read(BQ27200_REG_FLAGS, &flags, 0, di);
+ ret = bq27200_read(di, BQ27200_REG_AI);
if (ret < 0) {
- dev_err(di->dev, "error reading flags\n");
+ dev_err(&di->client->dev, "error reading current\n");
return 0;
}
- if ((flags & (1 << 7)) != 0) {
- dev_dbg(di->dev, "negative current!\n");
- return -curr;
- }

- return curr;
+ return ret;
}

/*
@@ -148,15 +125,14 @@ static int bq27200_current(struct bq27200_device_info *di)
static int bq27200_rsoc(struct bq27200_device_info *di)
{
int ret;
- int rsoc = 0;

- ret = bq27200_read(BQ27200_REG_RSOC, &rsoc, 1, di);
- if (ret) {
- dev_err(di->dev, "error reading relative State-of-Charge\n");
+ ret = bq27200_read(di, BQ27200_REG_RSOC);
+ if (ret < 0) {
+ dev_err(&di->client->dev, "error reading relative State-of-Charge\n");
return ret;
}

- return rsoc >> 8;
+ return ret >> 8;
}

static int bq27200_get_property(struct power_supply *psy,
@@ -197,51 +173,10 @@ static void bq27200_powersupply_init(struct bq27200_device_info *di)
di->bat.external_power_changed = NULL;
}

-static int _bq27200_read(u8 reg, int *rt_value, int b_single,
- struct bq27200_device_info *di)
-{
- struct i2c_client *client = di->client;
- struct i2c_msg msg[1];
- unsigned char data[2];
- int err;
-
- if (!client->adapter)
- return -ENODEV;
-
- msg->addr = client->addr;
- msg->flags = 0;
- msg->len = 1;
- msg->buf = data;
-
- data[0] = reg;
- err = i2c_transfer(client->adapter, msg, 1);
-
- if (err >= 0) {
- if (!b_single)
- msg->len = 2;
- else
- msg->len = 1;
-
- msg->flags = I2C_M_RD;
- err = i2c_transfer(client->adapter, msg, 1);
- if (err >= 0) {
- if (!b_single)
- *rt_value = get_unaligned_be16(data);
- else
- *rt_value = data[0];
-
- return 0;
- }
- }
-
- return err;
-}
-
static int bq27200_battery_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct bq27200_device_info *di;
- struct bq27200_access_methods *bus;
int retval = 0;

di = kzalloc(sizeof(*di), GFP_KERNEL);
@@ -251,19 +186,9 @@ static int bq27200_battery_probe(struct i2c_client *client,
goto batt_failed_1;
}

- bus = kzalloc(sizeof(*bus), GFP_KERNEL);
- if (!bus) {
- dev_err(&client->dev, "failed to allocate access method "
- "data\n");
- retval = -ENOMEM;
- goto batt_failed_2;
- }
-
i2c_set_clientdata(client, di);
- di->dev = &client->dev;
+ di->client = client;
di->bat.name = client->name;
- bus->read = _bq27200_read;
- di->bus = bus;
di->client = client;

bq27200_powersupply_init(di);
@@ -271,14 +196,11 @@ static int bq27200_battery_probe(struct i2c_client *client,
retval = power_supply_register(&client->dev, &di->bat);
if (retval) {
dev_err(&client->dev, "failed to register battery\n");
- goto batt_failed_3;
+ goto batt_failed_2;
}

return 0;

-batt_failed_3:
- kfree(bus);
-
batt_failed_2:
kfree(di);

@@ -291,7 +213,6 @@ static int bq27200_battery_remove(struct i2c_client *client)
struct bq27200_device_info *di = i2c_get_clientdata(client);

power_supply_unregister(&di->bat);
- kfree(di->bat.name);
kfree(di);

return 0;
--
1.6.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/