/* NEW DEFINES FOR REGS */ #define ALVIUM_REG_SIZE_SHIFT 8 #define ALVIUM_REG_ADDR_MASK 0xff #define ALVIUM_REG_8BIT(n) ((1U << ALVIUM_REG_SIZE_SHIFT) | (n)) #define ALVIUM_REG_16BIT(n) ((2U << ALVIUM_REG_SIZE_SHIFT) | (n)) #define ALVIUM_REG_32BIT(n) ((4U << ALVIUM_REG_SIZE_SHIFT) | (n)) #define ALVIUM_REG_64BIT(n) ((8U << ALVIUM_REG_SIZE_SHIFT) | (n)) #define ALVIUM_BCRM_EXPOSURE_AUTO_8RW ALVIUM_REG_8BIT(0x01a0) #define ALVIUM_BCRM_REG_ADDR ALVIUM_REG_16BIT(0x0014) #define ALVIUM_BCRM_REG_VERSION ALVIUM_REG_32BIT(0x0000) #define ALVIUM_BCRM_DEVICE_FIRMWARE_VERSION ALVIUM_REG_64BIT(0x0010) #define ALVIUM_BCRM_WRITE_HANDSHAKE_8RW ALVIUM_REG_8BIT(0x0018) /* NEW READ FUNCTION */ static int __always_unused alvium_read(struct alvium_dev *alvium, u16 addr, void *val) { struct i2c_client *client = alvium->i2c_client; struct i2c_msg msgs[2] = {0}; u8 addr_buf[2] = {0}; u8 *data_buf = NULL; u16 reg = 0; u32 len = 0; int ret; reg = (addr & ALVIUM_REG_ADDR_MASK); len = (addr >> ALVIUM_REG_SIZE_SHIFT); if (WARN_ON(len > 8)) return -EINVAL; data_buf = kmalloc_array(len, sizeof(u8), GFP_KERNEL); put_unaligned_be16(reg, addr_buf); msgs[0].addr = client->addr; msgs[0].flags = 0; msgs[0].len = ARRAY_SIZE(addr_buf); msgs[0].buf = addr_buf; msgs[1].addr = client->addr; msgs[1].flags = I2C_M_RD; msgs[1].len = len; msgs[1].buf = data_buf; ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); if (ret != ARRAY_SIZE(msgs)) return -EIO; switch (len) { case 1: *(u8 *)val = data_buf[0]; break; case 2: *(u16 *)val = get_unaligned_be16(data_buf); break; case 4: *(u32 *)val = get_unaligned_be32(data_buf); break; case 8: *(u64 *)val = get_unaligned_be64(data_buf); break; default: return -EINVAL; } return 0; } /* NEW WRITE FUNCTION */ static int __always_unused alvium_write(struct alvium_dev *alvium, u16 addr, void *val) { struct i2c_client *client = alvium->i2c_client; struct i2c_msg msgs[2] = {0}; u8 addr_buf[2] = {0}; u8 *data_buf = NULL; u16 reg = 0; u32 len = 0; int ret; reg = (addr & ALVIUM_REG_ADDR_MASK); len = (addr >> ALVIUM_REG_SIZE_SHIFT); if (WARN_ON(len > 8)) return -EINVAL; data_buf = kmalloc_array(len, sizeof(u8), GFP_KERNEL); put_unaligned_be16(reg, addr_buf); switch (len) { case 1: data_buf = val; break; case 2: put_unaligned_be16(*(u64 *)val, data_buf); break; case 4: put_unaligned_be32(*(u32 *)val, data_buf); break; case 8: put_unaligned_be64(*(u16 *)val, data_buf); break; default: return -EINVAL; } msgs[0].addr = client->addr; msgs[0].flags = 0; msgs[0].len = ARRAY_SIZE(addr_buf); msgs[0].buf = addr_buf; msgs[1].addr = client->addr; msgs[1].flags = 0; msgs[1].len = len; msgs[1].buf = data_buf; ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); if (ret != ARRAY_SIZE(msgs)) return -EIO; return 0; } # USAGE ret = alvium_read(alvium, ALVIUM_BCRM_REG_VERSION, &tmp); ret = alvium_write(alvium, ALVIUM_BCRM_WRITE_HANDSHAKE_8RW, &test);