This is a note to let you know that I've just added the patch titled usb: typec: tps6598x: handle block writes separately with plain-I2C to my usb git tree which can be found at git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git in the usb-next branch. The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.) The patch will also be merged in the next major kernel release during the merge window. If you have any questions about this process, please let me know. >From 8a863a608d47fa5d9dd15cf841817f73f804cf91 Mon Sep 17 00:00:00 2001 From: Nikolaus Voss <nikolaus.voss@xxxxxxxxxxxxxxxxxxxxx> Date: Wed, 20 Feb 2019 16:11:38 +0100 Subject: usb: typec: tps6598x: handle block writes separately with plain-I2C adapters Commit 1a2f474d328f handles block _reads_ separately with plain-I2C adapters, but the problem described with regmap-i2c not handling SMBus block transfers (i.e. read and writes) correctly also exists with writes. As workaround, this patch adds a block write function the same way 1a2f474d328f adds a block read function. Fixes: 1a2f474d328f ("usb: typec: tps6598x: handle block reads separately with plain-I2C adapters") Fixes: 0a4c005bd171 ("usb: typec: driver for TI TPS6598x USB Power Delivery controllers") Signed-off-by: Nikolaus Voss <nikolaus.voss@xxxxxxxxxxxxxxxxxxxxx> Cc: stable <stable@xxxxxxxxxxxxxxx> Reviewed-by: Guenter Roeck <linux@xxxxxxxxxxxx> Acked-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/usb/typec/tps6598x.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c index 9947c87d2a1e..c674abe3cf99 100644 --- a/drivers/usb/typec/tps6598x.c +++ b/drivers/usb/typec/tps6598x.c @@ -126,6 +126,20 @@ tps6598x_block_read(struct tps6598x *tps, u8 reg, void *val, size_t len) return 0; } +static int tps6598x_block_write(struct tps6598x *tps, u8 reg, + void *val, size_t len) +{ + u8 data[TPS_MAX_LEN + 1]; + + if (!tps->i2c_protocol) + return regmap_raw_write(tps->regmap, reg, val, len); + + data[0] = len; + memcpy(&data[1], val, len); + + return regmap_raw_write(tps->regmap, reg, data, sizeof(data)); +} + static inline int tps6598x_read16(struct tps6598x *tps, u8 reg, u16 *val) { return tps6598x_block_read(tps, reg, val, sizeof(u16)); @@ -143,23 +157,23 @@ static inline int tps6598x_read64(struct tps6598x *tps, u8 reg, u64 *val) static inline int tps6598x_write16(struct tps6598x *tps, u8 reg, u16 val) { - return regmap_raw_write(tps->regmap, reg, &val, sizeof(u16)); + return tps6598x_block_write(tps, reg, &val, sizeof(u16)); } static inline int tps6598x_write32(struct tps6598x *tps, u8 reg, u32 val) { - return regmap_raw_write(tps->regmap, reg, &val, sizeof(u32)); + return tps6598x_block_write(tps, reg, &val, sizeof(u32)); } static inline int tps6598x_write64(struct tps6598x *tps, u8 reg, u64 val) { - return regmap_raw_write(tps->regmap, reg, &val, sizeof(u64)); + return tps6598x_block_write(tps, reg, &val, sizeof(u64)); } static inline int tps6598x_write_4cc(struct tps6598x *tps, u8 reg, const char *val) { - return regmap_raw_write(tps->regmap, reg, &val, sizeof(u32)); + return tps6598x_block_write(tps, reg, &val, sizeof(u32)); } static int tps6598x_read_partner_identity(struct tps6598x *tps) @@ -245,8 +259,8 @@ static int tps6598x_exec_cmd(struct tps6598x *tps, const char *cmd, return -EBUSY; if (in_len) { - ret = regmap_raw_write(tps->regmap, TPS_REG_DATA1, - in_data, in_len); + ret = tps6598x_block_write(tps, TPS_REG_DATA1, + in_data, in_len); if (ret) return ret; } -- 2.20.1