ACK: [PATCH v2 1/1][SRU][Focal] regmap-i2c: add 16-bit width registers support
Kamal Mostafa
kamal at canonical.com
Thu May 14 16:10:17 UTC 2020
This patch (for focal) looks okay to me.
Acked-by: Kamal Mostafa <kamal at canonical.com>
-Kamal
On Thu, May 14, 2020 at 06:39:56PM +0800, AceLan Kao wrote:
> BugLink: https://bugs.launchpad.net/bugs/1876699
>
> This allows to access data with 16-bit width of registers
> via i2c SMBus block functions.
>
> The multi-command sequence of the reading function is not safe
> and may read the wrong data from other address if other commands
> are sent in-between the SMBus commands in the read function.
>
> Read performance:
> 32768 bytes (33 kB, 32 KiB) copied, 11.4869 s, 2.9 kB/s
> Write performance(with 1-byte page):
> 32768 bytes (33 kB, 32 KiB) copied, 129.591 s, 0.3 kB/s
>
> The implementation is inspired by below commit
> https://patchwork.ozlabs.org/patch/545292/
>
> v2: add more descriptions about the issue that maybe introduced
> by this commit
>
> Signed-off-by: AceLan Kao <acelan.kao at canonical.com>
> Link: https://lore.kernel.org/r/20200424123358.144850-1-acelan.kao@canonical.com
> Signed-off-by: Mark Brown <broonie at kernel.org>
> (cherry picked from commit 82f25bd73c0bee4d29df47007a4f7290695b7db7
> linux-next)
> Signed-off-by: AceLan Kao <acelan.kao at canonical.com>
> ---
> drivers/base/regmap/regmap-i2c.c | 61 ++++++++++++++++++++++++++++++++
> 1 file changed, 61 insertions(+)
>
> diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
> index 008f8da69d97..62b95a9212ae 100644
> --- a/drivers/base/regmap/regmap-i2c.c
> +++ b/drivers/base/regmap/regmap-i2c.c
> @@ -246,6 +246,63 @@ static const struct regmap_bus regmap_i2c_smbus_i2c_block = {
> .max_raw_write = I2C_SMBUS_BLOCK_MAX,
> };
>
> +static int regmap_i2c_smbus_i2c_write_reg16(void *context, const void *data,
> + size_t count)
> +{
> + struct device *dev = context;
> + struct i2c_client *i2c = to_i2c_client(dev);
> +
> + if (count < 2)
> + return -EINVAL;
> +
> + count--;
> + return i2c_smbus_write_i2c_block_data(i2c, ((u8 *)data)[0], count,
> + (u8 *)data + 1);
> +}
> +
> +static int regmap_i2c_smbus_i2c_read_reg16(void *context, const void *reg,
> + size_t reg_size, void *val,
> + size_t val_size)
> +{
> + struct device *dev = context;
> + struct i2c_client *i2c = to_i2c_client(dev);
> + int ret, count, len = val_size;
> +
> + if (reg_size != 2)
> + return -EINVAL;
> +
> + ret = i2c_smbus_write_byte_data(i2c, ((u16 *)reg)[0] & 0xff,
> + ((u16 *)reg)[0] >> 8);
> + if (ret < 0)
> + return ret;
> +
> + count = 0;
> + do {
> + /* Current Address Read */
> + ret = i2c_smbus_read_byte(i2c);
> + if (ret < 0)
> + break;
> +
> + *((u8 *)val++) = ret;
> + count++;
> + len--;
> + } while (len > 0);
> +
> + if (count == val_size)
> + return 0;
> + else if (ret < 0)
> + return ret;
> + else
> + return -EIO;
> +}
> +
> +static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = {
> + .write = regmap_i2c_smbus_i2c_write_reg16,
> + .read = regmap_i2c_smbus_i2c_read_reg16,
> + .max_raw_read = I2C_SMBUS_BLOCK_MAX,
> + .max_raw_write = I2C_SMBUS_BLOCK_MAX,
> +};
> +
> static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
> const struct regmap_config *config)
> {
> @@ -255,6 +312,10 @@ static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
> i2c_check_functionality(i2c->adapter,
> I2C_FUNC_SMBUS_I2C_BLOCK))
> return ®map_i2c_smbus_i2c_block;
> + else if (config->val_bits == 8 && config->reg_bits == 16 &&
> + i2c_check_functionality(i2c->adapter,
> + I2C_FUNC_SMBUS_I2C_BLOCK))
> + return ®map_i2c_smbus_i2c_block_reg16;
> else if (config->val_bits == 16 && config->reg_bits == 8 &&
> i2c_check_functionality(i2c->adapter,
> I2C_FUNC_SMBUS_WORD_DATA))
> --
> 2.25.1
>
>
> --
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
More information about the kernel-team
mailing list