Skip to content

Commit

Permalink
Input: ad714x - read the interrupt status registers in a row
Browse files Browse the repository at this point in the history
The interrupt status registers should be read in row to avoid invalid data.

Alter "read" method for both bus options to allow reading several registers
in a row and make sure we read interrupt status registers properly.

Read sequence saves 50% of bus transactions compared to single register
reads. So use it also for the result registers, which are also located
in a row.

Also update copyright notice.

Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
  • Loading branch information
Michael Hennerich authored and Dmitry Torokhov committed Aug 22, 2011
1 parent c0409fe commit 9eff794
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 41 deletions.
11 changes: 7 additions & 4 deletions drivers/input/misc/ad714x-i2c.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* AD714X CapTouch Programmable Controller driver (I2C bus)
*
* Copyright 2009 Analog Devices Inc.
* Copyright 2009-2011 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
Expand Down Expand Up @@ -47,9 +47,10 @@ static int ad714x_i2c_write(struct ad714x_chip *chip,
}

static int ad714x_i2c_read(struct ad714x_chip *chip,
unsigned short reg, unsigned short *data)
unsigned short reg, unsigned short *data, size_t len)
{
struct i2c_client *client = to_i2c_client(chip->dev);
int i;
int error;

chip->xfer_buf[0] = cpu_to_be16(reg);
Expand All @@ -58,14 +59,16 @@ static int ad714x_i2c_read(struct ad714x_chip *chip,
sizeof(*chip->xfer_buf));
if (error >= 0)
error = i2c_master_recv(client, (u8 *)chip->xfer_buf,
sizeof(*chip->xfer_buf));
len * sizeof(*chip->xfer_buf));

if (unlikely(error < 0)) {
dev_err(&client->dev, "I2C read error: %d\n", error);
return error;
}

*data = be16_to_cpup(chip->xfer_buf);
for (i = 0; i < len; i++)
data[i] = be16_to_cpu(chip->xfer_buf[i]);

return 0;
}

Expand Down
11 changes: 7 additions & 4 deletions drivers/input/misc/ad714x-spi.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* AD714X CapTouch Programmable Controller driver (SPI bus)
*
* Copyright 2009 Analog Devices Inc.
* Copyright 2009-2011 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
Expand Down Expand Up @@ -31,11 +31,12 @@ static int ad714x_spi_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume);

static int ad714x_spi_read(struct ad714x_chip *chip,
unsigned short reg, unsigned short *data)
unsigned short reg, unsigned short *data, size_t len)
{
struct spi_device *spi = to_spi_device(chip->dev);
struct spi_message message;
struct spi_transfer xfer[2];
int i;
int error;

spi_message_init(&message);
Expand All @@ -48,7 +49,7 @@ static int ad714x_spi_read(struct ad714x_chip *chip,
spi_message_add_tail(&xfer[0], &message);

xfer[1].rx_buf = &chip->xfer_buf[1];
xfer[1].len = sizeof(chip->xfer_buf[1]);
xfer[1].len = sizeof(chip->xfer_buf[1]) * len;
spi_message_add_tail(&xfer[1], &message);

error = spi_sync(spi, &message);
Expand All @@ -57,7 +58,9 @@ static int ad714x_spi_read(struct ad714x_chip *chip,
return error;
}

*data = be16_to_cpu(chip->xfer_buf[1]);
for (i = 0; i < len; i++)
data[i] = be16_to_cpu(chip->xfer_buf[i + 1]);

return 0;
}

Expand Down
62 changes: 32 additions & 30 deletions drivers/input/misc/ad714x.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* AD714X CapTouch Programmable Controller driver supporting AD7142/3/7/8/7A
*
* Copyright 2009 Analog Devices Inc.
* Copyright 2009-2011 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
Expand Down Expand Up @@ -123,6 +123,7 @@ struct ad714x_driver_data {
* information to integrate all things which will be private data
* of spi/i2c device
*/

static void ad714x_use_com_int(struct ad714x_chip *ad714x,
int start_stage, int end_stage)
{
Expand All @@ -131,11 +132,11 @@ static void ad714x_use_com_int(struct ad714x_chip *ad714x,

mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1);

ad714x->read(ad714x, STG_COM_INT_EN_REG, &data);
ad714x->read(ad714x, STG_COM_INT_EN_REG, &data, 1);
data |= 1 << end_stage;
ad714x->write(ad714x, STG_COM_INT_EN_REG, data);

ad714x->read(ad714x, STG_HIGH_INT_EN_REG, &data);
ad714x->read(ad714x, STG_HIGH_INT_EN_REG, &data, 1);
data &= ~mask;
ad714x->write(ad714x, STG_HIGH_INT_EN_REG, data);
}
Expand All @@ -148,11 +149,11 @@ static void ad714x_use_thr_int(struct ad714x_chip *ad714x,

mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1);

ad714x->read(ad714x, STG_COM_INT_EN_REG, &data);
ad714x->read(ad714x, STG_COM_INT_EN_REG, &data, 1);
data &= ~(1 << end_stage);
ad714x->write(ad714x, STG_COM_INT_EN_REG, data);

ad714x->read(ad714x, STG_HIGH_INT_EN_REG, &data);
ad714x->read(ad714x, STG_HIGH_INT_EN_REG, &data, 1);
data |= mask;
ad714x->write(ad714x, STG_HIGH_INT_EN_REG, data);
}
Expand Down Expand Up @@ -250,13 +251,16 @@ static void ad714x_slider_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
int i;

ad714x->read(ad714x, CDC_RESULT_S0 + hw->start_stage,
&ad714x->adc_reg[hw->start_stage],
hw->end_stage - hw->start_stage + 1);

for (i = hw->start_stage; i <= hw->end_stage; i++) {
ad714x->read(ad714x, CDC_RESULT_S0 + i, &ad714x->adc_reg[i]);
ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
&ad714x->amb_reg[i]);
&ad714x->amb_reg[i], 1);

ad714x->sensor_val[i] = abs(ad714x->adc_reg[i] -
ad714x->amb_reg[i]);
ad714x->sensor_val[i] =
abs(ad714x->adc_reg[i] - ad714x->amb_reg[i]);
}
}

Expand Down Expand Up @@ -419,13 +423,16 @@ static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
int i;

ad714x->read(ad714x, CDC_RESULT_S0 + hw->start_stage,
&ad714x->adc_reg[hw->start_stage],
hw->end_stage - hw->start_stage + 1);

for (i = hw->start_stage; i <= hw->end_stage; i++) {
ad714x->read(ad714x, CDC_RESULT_S0 + i, &ad714x->adc_reg[i]);
ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
&ad714x->amb_reg[i]);
&ad714x->amb_reg[i], 1);
if (ad714x->adc_reg[i] > ad714x->amb_reg[i])
ad714x->sensor_val[i] = ad714x->adc_reg[i] -
ad714x->amb_reg[i];
ad714x->sensor_val[i] =
ad714x->adc_reg[i] - ad714x->amb_reg[i];
else
ad714x->sensor_val[i] = 0;
}
Expand Down Expand Up @@ -570,13 +577,16 @@ static void touchpad_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
int i;

ad714x->read(ad714x, CDC_RESULT_S0 + hw->x_start_stage,
&ad714x->adc_reg[hw->x_start_stage],
hw->x_end_stage - hw->x_start_stage + 1);

for (i = hw->x_start_stage; i <= hw->x_end_stage; i++) {
ad714x->read(ad714x, CDC_RESULT_S0 + i, &ad714x->adc_reg[i]);
ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
&ad714x->amb_reg[i]);
&ad714x->amb_reg[i], 1);
if (ad714x->adc_reg[i] > ad714x->amb_reg[i])
ad714x->sensor_val[i] = ad714x->adc_reg[i] -
ad714x->amb_reg[i];
ad714x->sensor_val[i] =
ad714x->adc_reg[i] - ad714x->amb_reg[i];
else
ad714x->sensor_val[i] = 0;
}
Expand Down Expand Up @@ -862,7 +872,7 @@ static int ad714x_hw_detect(struct ad714x_chip *ad714x)
{
unsigned short data;

ad714x->read(ad714x, AD714X_PARTID_REG, &data);
ad714x->read(ad714x, AD714X_PARTID_REG, &data, 1);
switch (data & 0xFFF0) {
case AD7142_PARTID:
ad714x->product = 0x7142;
Expand Down Expand Up @@ -919,14 +929,12 @@ static void ad714x_hw_init(struct ad714x_chip *ad714x)
ad714x->write(ad714x, AD714X_SYSCFG_REG + i,
ad714x->hw->sys_cfg_reg[i]);
for (i = 0; i < SYS_CFGREG_NUM; i++)
ad714x->read(ad714x, AD714X_SYSCFG_REG + i, &data);
ad714x->read(ad714x, AD714X_SYSCFG_REG + i, &data, 1);

ad714x->write(ad714x, AD714X_STG_CAL_EN_REG, 0xFFF);

/* clear all interrupts */
ad714x->read(ad714x, STG_LOW_INT_STA_REG, &data);
ad714x->read(ad714x, STG_HIGH_INT_STA_REG, &data);
ad714x->read(ad714x, STG_COM_INT_STA_REG, &data);
ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);
}

static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
Expand All @@ -936,9 +944,7 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data)

mutex_lock(&ad714x->mutex);

ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state);
ad714x->read(ad714x, STG_HIGH_INT_STA_REG, &ad714x->h_state);
ad714x->read(ad714x, STG_COM_INT_STA_REG, &ad714x->c_state);
ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);

for (i = 0; i < ad714x->hw->button_num; i++)
ad714x_button_state_machine(ad714x, i);
Expand Down Expand Up @@ -1225,8 +1231,6 @@ EXPORT_SYMBOL(ad714x_disable);

int ad714x_enable(struct ad714x_chip *ad714x)
{
unsigned short data;

dev_dbg(ad714x->dev, "%s enter\n", __func__);

mutex_lock(&ad714x->mutex);
Expand All @@ -1240,9 +1244,7 @@ int ad714x_enable(struct ad714x_chip *ad714x)
* otherwise we will get no chance to enter falling-edge irq again
*/

ad714x->read(ad714x, STG_LOW_INT_STA_REG, &data);
ad714x->read(ad714x, STG_HIGH_INT_STA_REG, &data);
ad714x->read(ad714x, STG_COM_INT_STA_REG, &data);
ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);

mutex_unlock(&ad714x->mutex);

Expand Down
6 changes: 3 additions & 3 deletions drivers/input/misc/ad714x.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* AD714X CapTouch Programmable Controller driver (bus interfaces)
*
* Copyright 2009 Analog Devices Inc.
* Copyright 2009-2011 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
Expand All @@ -18,12 +18,12 @@ struct ad714x_platform_data;
struct ad714x_driver_data;
struct ad714x_chip;

typedef int (*ad714x_read_t)(struct ad714x_chip *, unsigned short, unsigned short *);
typedef int (*ad714x_read_t)(struct ad714x_chip *, unsigned short, unsigned short *, size_t);
typedef int (*ad714x_write_t)(struct ad714x_chip *, unsigned short, unsigned short);

struct ad714x_chip {
unsigned short h_state;
unsigned short l_state;
unsigned short h_state;
unsigned short c_state;
unsigned short adc_reg[STAGE_NUM];
unsigned short amb_reg[STAGE_NUM];
Expand Down

0 comments on commit 9eff794

Please sign in to comment.