Skip to content

Commit

Permalink
hwmon: lis3: use block read to access data registers
Browse files Browse the repository at this point in the history
Add optional blockread function to interface driver. If available
the chip driver uses it for data register access. For 12 bit device
it reads 6 bytes to get 3*16bit data. For 8 bit device it reads out
5 bytes since every second byte is dummy.
This optimizes bus usage and reduces number of operations and
interrupts needed for one data update.

Signed-off-by: Samu Onkalo <samu.p.onkalo@nokia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Acked-by: Eric Piel <eric.piel@tremplin-utc.net>
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
  • Loading branch information
Samu Onkalo authored and Guenter Roeck committed Oct 25, 2010
1 parent 477bc91 commit f10a540
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 3 deletions.
21 changes: 18 additions & 3 deletions drivers/hwmon/lis3lv02d.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,24 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
int position[3];
int i;

position[0] = lis3->read_data(lis3, OUTX);
position[1] = lis3->read_data(lis3, OUTY);
position[2] = lis3->read_data(lis3, OUTZ);
if (lis3->blkread) {
if (lis3_dev.whoami == WAI_12B) {
u16 data[3];
lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
for (i = 0; i < 3; i++)
position[i] = (s16)le16_to_cpu(data[i]);
} else {
u8 data[5];
/* Data: x, dummy, y, dummy, z */
lis3->blkread(lis3, OUTX, 5, data);
for (i = 0; i < 3; i++)
position[i] = (s8)data[i * 2];
}
} else {
position[0] = lis3->read_data(lis3, OUTX);
position[1] = lis3->read_data(lis3, OUTY);
position[2] = lis3->read_data(lis3, OUTZ);
}

for (i = 0; i < 3; i++)
position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
Expand Down
1 change: 1 addition & 0 deletions drivers/hwmon/lis3lv02d.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ struct lis3lv02d {
int (*init) (struct lis3lv02d *lis3);
int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);

int *odrs; /* Supported output data rates */
Expand Down
13 changes: 13 additions & 0 deletions drivers/hwmon/lis3lv02d_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
return 0;
}

static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
u8 *v)
{
struct i2c_client *c = lis3->bus_priv;
reg |= (1 << 7); /* 7th bit enables address auto incrementation */
return i2c_smbus_read_i2c_block_data(c, reg, len, v);
}

static int lis3_i2c_init(struct lis3lv02d *lis3)
{
u8 reg;
Expand Down Expand Up @@ -102,6 +110,11 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
lis3_dev.reg_ctrl = lis3_reg_ctrl;

if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
(i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_I2C_BLOCK)))
lis3_dev.blkread = lis3_i2c_blockread;

if (pdata->axis_x)
lis3lv02d_axis_map.x = pdata->axis_x;

Expand Down
1 change: 1 addition & 0 deletions include/linux/lis3lv02d.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ struct lis3lv02d_platform_data {
s8 axis_y;
s8 axis_z;
#define LIS3_USE_REGULATOR_CTRL 0x01
#define LIS3_USE_BLOCK_READ 0x02
u16 driver_features;
int default_rate;
int (*setup_resources)(void);
Expand Down

0 comments on commit f10a540

Please sign in to comment.