From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755357AbbBBKJm (ORCPT ); Mon, 2 Feb 2015 05:09:42 -0500 Received: from cantor2.suse.de ([195.135.220.15]:41129 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754554AbbBBKJh (ORCPT ); Mon, 2 Feb 2015 05:09:37 -0500 Date: Mon, 2 Feb 2015 11:09:31 +0100 From: Jean Delvare To: Guenter Roeck Cc: Mark Brown , Robert Rosengren , linux-kernel@vger.kernel.org, Greg Kroah-Hartman Subject: Re: [PATCH] regmap: Fix i2c word access when using SMBus access functions Message-ID: <20150202110931.7671a200@endymion.delvare> In-Reply-To: <1422834481-6936-1-git-send-email-linux@roeck-us.net> References: <1422834481-6936-1-git-send-email-linux@roeck-us.net> Organization: SUSE Linux X-Mailer: Claws Mail 3.10.1 (GTK+ 2.24.23; x86_64-suse-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Guenter, On Sun, 1 Feb 2015 15:48:01 -0800, Guenter Roeck wrote: > SMBUs access functions assume that 16 bit values are formatted as Correct spelling is SMBus (lowercase U.) Also I think "16 bit" is better spelled "16-bit" (more occurrences below.) > little endian numbers. The direct i2c access functions in regmap, > however, assume that 16 bit values are formatted as big endian numbers. > As a result, the current code returns different values if an i2c chip's > 16 bit registers are accessed through i2c access functions vs. SMBus > access functions. > > Use regmap_smbus_read_word_swapped and regmap_smbus_write_word_swapped > for 16 bit SMBus accesses unless a chip is registered with val_format_endian > set to REGMAP_ENDIAN_LITTLE. In the latter case, keep using > regmap_smbus_write_word_data and regmap_smbus_read_word_data. > > Cc: Jean Delvare > Signed-off-by: Guenter Roeck > --- > Might be a candidate for -stable, though as far as I can see there is currently > no driver in the upstream kernel using regmap for 16-bit i2c accesses. > > drivers/base/regmap/regmap-i2c.c | 41 +++++++++++++++++++++++++++++++++++++++- > 1 file changed, 40 insertions(+), 1 deletion(-) > > diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c > index 053150a..865f4f8 100644 > --- a/drivers/base/regmap/regmap-i2c.c > +++ b/drivers/base/regmap/regmap-i2c.c > @@ -87,6 +87,42 @@ static struct regmap_bus regmap_smbus_word = { > .reg_read = regmap_smbus_word_reg_read, > }; > > +static int regmap_smbus_word_read_swapped(void *context, unsigned int reg, > + unsigned int *val) > +{ > + struct device *dev = context; > + struct i2c_client *i2c = to_i2c_client(dev); > + int ret; > + > + if (reg > 0xff) > + return -EINVAL; > + > + ret = i2c_smbus_read_word_swapped(i2c, reg); > + if (ret < 0) > + return ret; > + > + *val = ret; > + > + return 0; > +} > + > +static int regmap_smbus_word_write_swapped(void *context, unsigned int reg, > + unsigned int val) > +{ > + struct device *dev = context; > + struct i2c_client *i2c = to_i2c_client(dev); > + > + if (val > 0xffff || reg > 0xff) > + return -EINVAL; > + > + return i2c_smbus_write_word_swapped(i2c, reg, val); > +} > + > +static struct regmap_bus regmap_smbus_word_swapped = { > + .reg_write = regmap_smbus_word_write_swapped, > + .reg_read = regmap_smbus_word_read_swapped, > +}; > + > static int regmap_i2c_write(void *context, const void *data, size_t count) > { > struct device *dev = context; > @@ -180,7 +216,10 @@ static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, > else if (config->val_bits == 16 && config->reg_bits == 8 && > i2c_check_functionality(i2c->adapter, > I2C_FUNC_SMBUS_WORD_DATA)) > - return ®map_smbus_word; > + if (config->val_format_endian == REGMAP_ENDIAN_LITTLE) > + return ®map_smbus_word; > + else > + return ®map_smbus_word_swapped; Indentation looks wrong. > else if (config->val_bits == 8 && config->reg_bits == 8 && > i2c_check_functionality(i2c->adapter, > I2C_FUNC_SMBUS_BYTE_DATA)) The code itself looks sane, although I am not a regmap expert. Reviewed-by: Jean Delvare -- Jean Delvare SUSE L3 Support