On Tue, Jun 23, 2020 at 08:36:54PM +0300, [email protected] wrote:
> From: Alexandru Tachici <[email protected]>
> 
> PmBus devices support Block Write-Block Read Process
> Call described in SMBus specification v 2.0 with the
> exception that Block writes and reads are permitted to
> have up 255 data bytes instead of max 32 bytes (SMBus).
> 
> This patch adds Block WR process call support for ADM1266.
> 
> Signed-off-by: Alexandru Tachici <[email protected]>
> ---
>  drivers/hwmon/pmbus/Kconfig   |  1 +
>  drivers/hwmon/pmbus/adm1266.c | 79 +++++++++++++++++++++++++++++++++++
>  2 files changed, 80 insertions(+)
> 
> diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
> index 6949483aa732..dc6971a7c49e 100644
> --- a/drivers/hwmon/pmbus/Kconfig
> +++ b/drivers/hwmon/pmbus/Kconfig
> @@ -28,6 +28,7 @@ config SENSORS_PMBUS
>  
>  config SENSORS_ADM1266
>       tristate "Analog Devices ADM1266 Sequencer"
> +     select CRC8
>       help
>         If you say yes here you get hardware monitoring support for Analog
>         Devices ADM1266 Cascadable Super Sequencer.
> diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c
> index a7ef048a9a5c..381d89a8569f 100644
> --- a/drivers/hwmon/pmbus/adm1266.c
> +++ b/drivers/hwmon/pmbus/adm1266.c
> @@ -6,6 +6,7 @@
>   * Copyright 2020 Analog Devices Inc.
>   */
>  
> +#include <linux/crc8.h>
>  #include <linux/i2c.h>
>  #include <linux/init.h>
>  #include <linux/kernel.h>
> @@ -14,6 +15,82 @@
>  
>  #include "pmbus.h"
>  
> +#define ADM1266_PMBUS_BLOCK_MAX              255
> +
> +DECLARE_CRC8_TABLE(pmbus_crc_table);
> +
> +/* Different from Block Read as it sends data and waits for the slave to

   /*
    * Proper multi-line comment
    */

> + * return a value dependent on that data. The protocol is simply a Write 
> Block
> + * followed by a Read Block without the Read-Block command field and the
> + * Write-Block STOP bit.
> + */

static

> +int pmbus_block_xfer(struct i2c_client *client, u8 cmd, u8 w_len,
> +                  u8 *data_w, u8 *data_r)
> +{
> +     u8 write_buf[ADM1266_PMBUS_BLOCK_MAX + 2];
> +     struct i2c_msg msgs[2] = {
> +             {
> +                     .addr = client->addr,
> +                     .flags = 0,
> +                     .buf = write_buf,
> +                     .len = w_len + 2,
> +             },
> +             {
> +                     .addr = client->addr,
> +                     .flags = I2C_M_RD,
> +                     .len = ADM1266_PMBUS_BLOCK_MAX + 2,
> +             }
> +     };
> +     u8 addr = 0;
> +     u8 crc = 0;

Unnecessary initialization for both variables

> +     int ret;
> +
> +     msgs[0].buf[0] = cmd;
> +     msgs[0].buf[1] = w_len;
> +     memcpy(&msgs[0].buf[2], data_w, w_len);
> +
> +     msgs[0].buf = i2c_get_dma_safe_msg_buf(&msgs[0], 1);
> +     if (!msgs[0].buf)
> +             return -ENOMEM;
> +
> +     msgs[1].buf = i2c_get_dma_safe_msg_buf(&msgs[1], 1);
> +     if (!msgs[1].buf) {
> +             i2c_put_dma_safe_msg_buf(msgs[0].buf, &msgs[0], false);
> +             return -ENOMEM;
> +     }

AFAICS i2c_get_dma_safe_msg_buf() is supposed to be used by i2c bus drivers,
not by device drivers. If this is needed for the target architecture,
it should be implemented in the bus driver, not here.

> +
> +     ret = i2c_transfer(client->adapter, msgs, 2);
> +     if (ret != 2) {
> +             ret = -EPROTO;

Should retain error if ret < 0, and only return EPROTO if the return value
is 0 or 1.

> +             goto cleanup;
> +     }
> +
> +     if (client->flags & I2C_CLIENT_PEC) {
> +             addr = i2c_8bit_addr_from_msg(&msgs[0]);
> +             crc = crc8(pmbus_crc_table, &addr, 1, crc);
> +             crc = crc8(pmbus_crc_table, msgs[0].buf,  msgs[0].len, crc);
> +
> +             addr = i2c_8bit_addr_from_msg(&msgs[1]);
> +             crc = crc8(pmbus_crc_table, &addr, 1, crc);
> +             crc = crc8(pmbus_crc_table, msgs[1].buf,  msgs[1].buf[0] + 1,
> +                        crc);
> +
> +             if (crc != msgs[1].buf[msgs[1].buf[0] + 1]) {
> +                     ret = -EBADMSG;
> +                     goto cleanup;
> +             }
> +     }
> +
> +     memcpy(data_r, &msgs[1].buf[1], msgs[1].buf[0]);
> +     ret = msgs[1].buf[0];
> +
> +cleanup:
> +     i2c_put_dma_safe_msg_buf(msgs[0].buf, &msgs[0], true);
> +     i2c_put_dma_safe_msg_buf(msgs[1].buf, &msgs[1], true);
> +
> +     return ret;
> +}
    > +
>  static int adm1266_probe(struct i2c_client *client,
>                        const struct i2c_device_id *id)
>  {
> @@ -24,6 +101,8 @@ static int adm1266_probe(struct i2c_client *client,
>       info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info),
>                           GFP_KERNEL);
>  
> +     crc8_populate_msb(pmbus_crc_table, 0x7);
> +
>       info->pages = 17;
>       info->format[PSC_VOLTAGE_OUT] = linear;
>       funcs = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;

Reply via email to