lkml.org 
[lkml]   [2022]   [Oct]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 045/159] iio: dac: ad5593r: Fix i2c read protocol requirements
    Date
    From: Michael Hennerich <michael.hennerich@analog.com>

    commit 558a25f903b4af6361b7fbeea08a6446a0745653 upstream.

    For reliable operation across the full range of supported
    interface rates, the AD5593R needs a STOP condition between
    address write, and data read (like show in the datasheet Figure 40)
    so in turn i2c_smbus_read_word_swapped cannot be used.

    While at it, a simple helper was added to make the code simpler.

    Fixes: 56ca9db862bf ("iio: dac: Add support for the AD5592R/AD5593R ADCs/DACs")
    Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
    Signed-off-by: Nuno Sá <nuno.sa@analog.com>
    Cc: <Stable@vger.kernel.org>
    Link: https://lore.kernel.org/r/20220913073413.140475-2-nuno.sa@analog.com
    Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/iio/dac/ad5593r.c | 46 +++++++++++++++++++++++++++-------------------
    1 file changed, 27 insertions(+), 19 deletions(-)

    --- a/drivers/iio/dac/ad5593r.c
    +++ b/drivers/iio/dac/ad5593r.c
    @@ -14,6 +14,8 @@
    #include <linux/module.h>
    #include <linux/of.h>

    +#include <asm/unaligned.h>
    +
    #define AD5593R_MODE_CONF (0 << 4)
    #define AD5593R_MODE_DAC_WRITE (1 << 4)
    #define AD5593R_MODE_ADC_READBACK (4 << 4)
    @@ -21,6 +23,24 @@
    #define AD5593R_MODE_GPIO_READBACK (6 << 4)
    #define AD5593R_MODE_REG_READBACK (7 << 4)

    +static int ad5593r_read_word(struct i2c_client *i2c, u8 reg, u16 *value)
    +{
    + int ret;
    + u8 buf[2];
    +
    + ret = i2c_smbus_write_byte(i2c, reg);
    + if (ret < 0)
    + return ret;
    +
    + ret = i2c_master_recv(i2c, buf, sizeof(buf));
    + if (ret < 0)
    + return ret;
    +
    + *value = get_unaligned_be16(buf);
    +
    + return 0;
    +}
    +
    static int ad5593r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value)
    {
    struct i2c_client *i2c = to_i2c_client(st->dev);
    @@ -39,13 +59,7 @@ static int ad5593r_read_adc(struct ad559
    if (val < 0)
    return (int) val;

    - val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_ADC_READBACK);
    - if (val < 0)
    - return (int) val;
    -
    - *value = (u16) val;
    -
    - return 0;
    + return ad5593r_read_word(i2c, AD5593R_MODE_ADC_READBACK, value);
    }

    static int ad5593r_reg_write(struct ad5592r_state *st, u8 reg, u16 value)
    @@ -59,25 +73,19 @@ static int ad5593r_reg_write(struct ad55
    static int ad5593r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
    {
    struct i2c_client *i2c = to_i2c_client(st->dev);
    - s32 val;
    -
    - val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_REG_READBACK | reg);
    - if (val < 0)
    - return (int) val;

    - *value = (u16) val;
    -
    - return 0;
    + return ad5593r_read_word(i2c, AD5593R_MODE_REG_READBACK | reg, value);
    }

    static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value)
    {
    struct i2c_client *i2c = to_i2c_client(st->dev);
    - s32 val;
    + u16 val;
    + int ret;

    - val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_GPIO_READBACK);
    - if (val < 0)
    - return (int) val;
    + ret = ad5593r_read_word(i2c, AD5593R_MODE_GPIO_READBACK, &val);
    + if (ret)
    + return ret;

    *value = (u8) val;


    \
     
     \ /
      Last update: 2022-10-24 13:49    [W:4.478 / U:0.084 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site