mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
iio: dac: ad5593r: Fix i2c read protocol requirements
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: 56ca9db862
("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>
This commit is contained in:
parent
d9d0c0725a
commit
558a25f903
@ -13,6 +13,8 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mod_devicetable.h>
|
#include <linux/mod_devicetable.h>
|
||||||
|
|
||||||
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
#define AD5593R_MODE_CONF (0 << 4)
|
#define AD5593R_MODE_CONF (0 << 4)
|
||||||
#define AD5593R_MODE_DAC_WRITE (1 << 4)
|
#define AD5593R_MODE_DAC_WRITE (1 << 4)
|
||||||
#define AD5593R_MODE_ADC_READBACK (4 << 4)
|
#define AD5593R_MODE_ADC_READBACK (4 << 4)
|
||||||
@ -20,6 +22,24 @@
|
|||||||
#define AD5593R_MODE_GPIO_READBACK (6 << 4)
|
#define AD5593R_MODE_GPIO_READBACK (6 << 4)
|
||||||
#define AD5593R_MODE_REG_READBACK (7 << 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)
|
static int ad5593r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value)
|
||||||
{
|
{
|
||||||
struct i2c_client *i2c = to_i2c_client(st->dev);
|
struct i2c_client *i2c = to_i2c_client(st->dev);
|
||||||
@ -38,13 +58,7 @@ static int ad5593r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value)
|
|||||||
if (val < 0)
|
if (val < 0)
|
||||||
return (int) val;
|
return (int) val;
|
||||||
|
|
||||||
val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_ADC_READBACK);
|
return ad5593r_read_word(i2c, AD5593R_MODE_ADC_READBACK, value);
|
||||||
if (val < 0)
|
|
||||||
return (int) val;
|
|
||||||
|
|
||||||
*value = (u16) val;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ad5593r_reg_write(struct ad5592r_state *st, u8 reg, u16 value)
|
static int ad5593r_reg_write(struct ad5592r_state *st, u8 reg, u16 value)
|
||||||
@ -58,25 +72,19 @@ static int ad5593r_reg_write(struct ad5592r_state *st, u8 reg, u16 value)
|
|||||||
static int ad5593r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
|
static int ad5593r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
|
||||||
{
|
{
|
||||||
struct i2c_client *i2c = to_i2c_client(st->dev);
|
struct i2c_client *i2c = to_i2c_client(st->dev);
|
||||||
s32 val;
|
|
||||||
|
|
||||||
val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_REG_READBACK | reg);
|
return ad5593r_read_word(i2c, AD5593R_MODE_REG_READBACK | reg, value);
|
||||||
if (val < 0)
|
|
||||||
return (int) val;
|
|
||||||
|
|
||||||
*value = (u16) val;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value)
|
static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value)
|
||||||
{
|
{
|
||||||
struct i2c_client *i2c = to_i2c_client(st->dev);
|
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);
|
ret = ad5593r_read_word(i2c, AD5593R_MODE_GPIO_READBACK, &val);
|
||||||
if (val < 0)
|
if (ret)
|
||||||
return (int) val;
|
return ret;
|
||||||
|
|
||||||
*value = (u8) val;
|
*value = (u8) val;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user