return (hash >> (32 - bits)) & 0xffffffffUL;
}
+/* Helper function to read data blocks from i2c clients with 8 or 16 bit
+ * address width, 8 bit register width and auto incrementation been activated */
+static int em28xx_i2c_read_block(struct em28xx *dev, u16 addr, bool addr_w16,
+ u16 len, u8 *data)
+{
+ int remain = len, rsize, rsize_max, ret;
+ u8 buf[2];
+
+ /* Sanity check */
+ if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1))
+ return -EINVAL;
+ /* Select address */
+ buf[0] = addr >> 8;
+ buf[1] = addr & 0xff;
+ ret = i2c_master_send(&dev->i2c_client, buf + !addr_w16, 1 + addr_w16);
+ if (ret < 0)
+ return ret;
+ /* Read data */
+ if (dev->board.is_em2800)
+ rsize_max = 4;
+ else
+ rsize_max = 64;
+ while (remain > 0) {
+ if (remain > rsize_max)
+ rsize = rsize_max;
+ else
+ rsize = remain;
+
+ ret = i2c_master_recv(&dev->i2c_client, data, rsize);
+ if (ret < 0)
+ return ret;
+
+ remain -= rsize;
+ data += rsize;
+ }
+
+ return len;
+}
+
static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
{
- unsigned char buf[2], *p = eedata;
+ unsigned char buf, *p = eedata;
struct em28xx_eeprom *em_eeprom = (void *)eedata;
- int i, err, size = len, block, block_max;
+ int i, err;
dev->i2c_client.addr = 0xa0 >> 1;
/* Check if board has eeprom */
- err = i2c_master_recv(&dev->i2c_client, buf, 0);
+ err = i2c_master_recv(&dev->i2c_client, &buf, 0);
if (err < 0) {
em28xx_info("board has no eeprom\n");
memset(eedata, 0, len);
return -ENODEV;
}
- /* Select address memory address 0x00(00) */
- buf[0] = 0;
- buf[1] = 0;
- err = i2c_master_send(&dev->i2c_client, buf, 1 + dev->eeprom_addrwidth_16bit);
- if (err != 1 + dev->eeprom_addrwidth_16bit) {
+ /* Read EEPROM content */
+ err = em28xx_i2c_read_block(dev, 0x0000, dev->eeprom_addrwidth_16bit,
+ len, p);
+ if (err != len) {
em28xx_errdev("failed to read eeprom (err=%d)\n", err);
return err;
}
- /* Read eeprom content */
- if (dev->board.is_em2800)
- block_max = 4;
- else
- block_max = 64;
- while (size > 0) {
- if (size > block_max)
- block = block_max;
- else
- block = size;
-
- if (block !=
- (err = i2c_master_recv(&dev->i2c_client, p, block))) {
- em28xx_errdev("i2c eeprom read error (err=%d)\n", err);
- return err;
- }
- size -= block;
- p += block;
- }
-
/* Display eeprom content */
for (i = 0; i < len; i++) {
if (0 == (i % 16)) {