Re: [PATCH] iio: (max1363) support SMBus for 8-bit devices
From: Jonathan Cameron
Date: Sun Oct 20 2013 - 16:39:22 EST
On 10/20/13 19:02, Vivien Didelot wrote:
> The driver currently supports only I2C access. But some devices with an
> accuracy of 8-bit are compatible with the SMBus byte access routines.
>
> This patch wraps the send and receive routines depending on the chip
> accuracy and fonctionnalities of its adapter.
>
> For instance, this allows us to use a MAX11603 on a ICH7 controller.
>
> This patch also simplifies the max1363_write_basic_config() routine to
> use the struct max1363_state fields directly.
>
> Signed-off-by: Vivien Didelot <vivien.didelot@xxxxxxxxxxxxxxxxxxxx>
Sensible change given I am guessing you have a usecase that needs to
run it as described. I've slightly changed the description to make it clear that
this is applies for all supported 8 bit devices.
> ---
> drivers/iio/adc/max1363.c | 76 +++++++++++++++++++++++++++++++++++------------
> 1 file changed, 57 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
> index cc07b37..6118dce 100644
> --- a/drivers/iio/adc/max1363.c
> +++ b/drivers/iio/adc/max1363.c
> @@ -165,6 +165,8 @@ struct max1363_chip_info {
> * @thresh_low: low threshold values
> * @vref: Reference voltage regulator
> * @vref_uv: Actual (external or internal) reference voltage
> + * @send: function used to send data to the chip
> + * @recv: function used to receive data from the chip
> */
> struct max1363_state {
> struct i2c_client *client;
> @@ -186,6 +188,10 @@ struct max1363_state {
> s16 thresh_low[8];
> struct regulator *vref;
> u32 vref_uv;
> + int (*send)(const struct i2c_client *client,
> + const char *buf, int count);
> + int (*recv)(const struct i2c_client *client,
> + char *buf, int count);
> };
>
> #define MAX1363_MODE_SINGLE(_num, _mask) { \
> @@ -311,13 +317,37 @@ static const struct max1363_mode
> return NULL;
> }
>
> -static int max1363_write_basic_config(struct i2c_client *client,
> - unsigned char d1,
> - unsigned char d2)
> +static int max1363_smbus_send(const struct i2c_client *client, const char *buf,
> + int count)
> {
> - u8 tx_buf[2] = {d1, d2};
> + int i, err;
>
> - return i2c_master_send(client, tx_buf, 2);
> + for (i = err = 0; err == 0 && i < count; ++i)
> + err = i2c_smbus_write_byte(client, buf[i]);
> +
> + return err ? err : count;
> +}
> +
> +static int max1363_smbus_recv(const struct i2c_client *client, char *buf,
> + int count)
> +{
> + int i, ret;
> +
> + for (i = 0; i < count; ++i) {
> + ret = i2c_smbus_read_byte(client);
> + if (ret < 0)
> + return ret;
> + buf[i] = ret;
> + }
> +
> + return count;
> +}
> +
> +static int max1363_write_basic_config(struct max1363_state *st)
> +{
> + u8 tx_buf[2] = { st->setupbyte, st->configbyte };
> +
> + return st->send(st->client, tx_buf, 2);
> }
>
> static int max1363_set_scan_mode(struct max1363_state *st)
> @@ -327,9 +357,7 @@ static int max1363_set_scan_mode(struct max1363_state *st)
> | MAX1363_SE_DE_MASK);
> st->configbyte |= st->current_mode->conf;
>
> - return max1363_write_basic_config(st->client,
> - st->setupbyte,
> - st->configbyte);
> + return max1363_write_basic_config(st);
> }
>
> static int max1363_read_single_chan(struct iio_dev *indio_dev,
> @@ -366,7 +394,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
> }
> if (st->chip_info->bits != 8) {
> /* Get reading */
> - data = i2c_master_recv(client, rxbuf, 2);
> + data = st->recv(client, rxbuf, 2);
> if (data < 0) {
> ret = data;
> goto error_ret;
> @@ -375,7 +403,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
> ((1 << st->chip_info->bits) - 1);
> } else {
> /* Get reading */
> - data = i2c_master_recv(client, rxbuf, 1);
> + data = st->recv(client, rxbuf, 1);
> if (data < 0) {
> ret = data;
> goto error_ret;
> @@ -772,11 +800,11 @@ static irqreturn_t max1363_event_handler(int irq, void *private)
> u8 tx[2] = { st->setupbyte,
> MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0 };
>
> - i2c_master_recv(st->client, &rx, 1);
> + st->recv(st->client, &rx, 1);
> mask = rx;
> for_each_set_bit(loc, &mask, 8)
> iio_push_event(indio_dev, max1363_event_codes[loc], timestamp);
> - i2c_master_send(st->client, tx, 2);
> + st->send(st->client, tx, 2);
>
> return IRQ_HANDLED;
> }
> @@ -812,9 +840,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled)
> st->setupbyte &= ~MAX1363_SETUP_MONITOR_SETUP;
> st->configbyte &= ~MAX1363_SCAN_MASK;
> st->monitor_on = false;
> - return max1363_write_basic_config(st->client,
> - st->setupbyte,
> - st->configbyte);
> + return max1363_write_basic_config(st);
> }
>
> /* Ensure we are in the relevant mode */
> @@ -876,7 +902,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled)
> }
>
>
> - ret = i2c_master_send(st->client, tx_buf, len);
> + ret = st->send(st->client, tx_buf, len);
> if (ret < 0)
> goto error_ret;
> if (ret != len) {
> @@ -893,7 +919,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled)
> */
> tx_buf[0] = st->setupbyte;
> tx_buf[1] = MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0;
> - ret = i2c_master_send(st->client, tx_buf, 2);
> + ret = st->send(st->client, tx_buf, 2);
> if (ret < 0)
> goto error_ret;
> if (ret != 2) {
> @@ -1481,9 +1507,9 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
> if (rxbuf == NULL)
> goto done;
> if (st->chip_info->bits != 8)
> - b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
> + b_sent = st->recv(st->client, rxbuf, numvals * 2);
> else
> - b_sent = i2c_master_recv(st->client, rxbuf, numvals);
> + b_sent = st->recv(st->client, rxbuf, numvals);
> if (b_sent < 0)
> goto done_free;
>
> @@ -1550,6 +1576,18 @@ static int max1363_probe(struct i2c_client *client,
> st->vref_uv = vref_uv;
> }
>
> + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
> + st->send = i2c_master_send;
> + st->recv = i2c_master_recv;
> + } else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)
> + && st->chip_info->bits == 8) {
> + st->send = max1363_smbus_send;
> + st->recv = max1363_smbus_recv;
> + } else {
> + ret = -EOPNOTSUPP;
> + goto error_disable_reg;
> + }
> +
> ret = max1363_alloc_scan_masks(indio_dev);
> if (ret)
> goto error_disable_reg;
>
--
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/