Re: [PATCH v4 2/7] hwmon: pmbus: adm1266: Add Block process call

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jun 23, 2020 at 08:36:54PM +0300, alexandru.tachici@xxxxxxxxxx wrote:
> From: Alexandru Tachici <alexandru.tachici@xxxxxxxxxx>
> 
> 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 <alexandru.tachici@xxxxxxxxxx>
> ---
>  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;



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux