Em Sun, 19 Feb 2017 19:29:18 +0100 Frank Schäfer <fschaefer.oss@xxxxxxxxxxxxxx> escreveu: > Use i2c_smbus_read_word_data() instead of i2c_master_send() and > i2c_master_recv() for reading the ID of Micorn sensors. > Bytes need to be swapped afterwards, because i2c_smbus_read_word_data() > assumes that the received bytes are little-endian byte order (as specified > by smbus), while Micron sensors with 16 bit register width use big endian > byte order. > > Signed-off-by: Frank Schäfer <fschaefer.oss@xxxxxxxxxxxxxx> > --- > drivers/media/usb/em28xx/em28xx-camera.c | 28 ++++------------------------ > 1 file changed, 4 insertions(+), 24 deletions(-) > > diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c > index 7b4129ab1cf9..4839479624e7 100644 > --- a/drivers/media/usb/em28xx/em28xx-camera.c > +++ b/drivers/media/usb/em28xx/em28xx-camera.c > @@ -106,8 +106,6 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) > { > int ret, i; > char *name; > - u8 reg; > - __be16 id_be; > u16 id; > > struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; > @@ -115,10 +113,8 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) > dev->em28xx_sensor = EM28XX_NOSENSOR; > for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { > client->addr = micron_sensor_addrs[i]; > - /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ > /* Read chip ID from register 0x00 */ > - reg = 0x00; > - ret = i2c_master_send(client, ®, 1); > + ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */ > if (ret < 0) { > if (ret != -ENXIO) > dev_err(&dev->intf->dev, > @@ -126,24 +122,9 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) > client->addr << 1, ret); > continue; > } > - ret = i2c_master_recv(client, (u8 *)&id_be, 2); > - if (ret < 0) { > - dev_err(&dev->intf->dev, > - "couldn't read from i2c device 0x%02x: error %i\n", > - client->addr << 1, ret); > - continue; > - } > - id = be16_to_cpu(id_be); > + id = swab16(ret); /* LE -> BE */ That's wrong! You can't assume that CPU is BE, as some archs use LE. You should, instead, call le16_to_cpu(), to be sure that it will be doing the right thing. Something like: id = le16_to_cpu((__le16)ret); Regards, Thanks, Mauro