162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * drivers/media/i2c/ccs/ccs-reg-access.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Generic driver for MIPI CCS/SMIA/SMIA++ compliant camera sensors 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2020 Intel Corporation 862306a36Sopenharmony_ci * Copyright (C) 2011--2012 Nokia Corporation 962306a36Sopenharmony_ci * Contact: Sakari Ailus <sakari.ailus@linux.intel.com> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <asm/unaligned.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/delay.h> 1562306a36Sopenharmony_ci#include <linux/i2c.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "ccs.h" 1862306a36Sopenharmony_ci#include "ccs-limits.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic u32 float_to_u32_mul_1000000(struct i2c_client *client, u32 phloat) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci s32 exp; 2362306a36Sopenharmony_ci u64 man; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci if (phloat >= 0x80000000) { 2662306a36Sopenharmony_ci dev_err(&client->dev, "this is a negative number\n"); 2762306a36Sopenharmony_ci return 0; 2862306a36Sopenharmony_ci } 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci if (phloat == 0x7f800000) 3162306a36Sopenharmony_ci return ~0; /* Inf. */ 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci if ((phloat & 0x7f800000) == 0x7f800000) { 3462306a36Sopenharmony_ci dev_err(&client->dev, "NaN or other special number\n"); 3562306a36Sopenharmony_ci return 0; 3662306a36Sopenharmony_ci } 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci /* Valid cases begin here */ 3962306a36Sopenharmony_ci if (phloat == 0) 4062306a36Sopenharmony_ci return 0; /* Valid zero */ 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci if (phloat > 0x4f800000) 4362306a36Sopenharmony_ci return ~0; /* larger than 4294967295 */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* 4662306a36Sopenharmony_ci * Unbias exponent (note how phloat is now guaranteed to 4762306a36Sopenharmony_ci * have 0 in the high bit) 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_ci exp = ((int32_t)phloat >> 23) - 127; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* Extract mantissa, add missing '1' bit and it's in MHz */ 5262306a36Sopenharmony_ci man = ((phloat & 0x7fffff) | 0x800000) * 1000000ULL; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (exp < 0) 5562306a36Sopenharmony_ci man >>= -exp; 5662306a36Sopenharmony_ci else 5762306a36Sopenharmony_ci man <<= exp; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci man >>= 23; /* Remove mantissa bias */ 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return man & 0xffffffff; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* 6662306a36Sopenharmony_ci * Read a 8/16/32-bit i2c register. The value is returned in 'val'. 6762306a36Sopenharmony_ci * Returns zero if successful, or non-zero otherwise. 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_cistatic int ____ccs_read_addr(struct ccs_sensor *sensor, u16 reg, u16 len, 7062306a36Sopenharmony_ci u32 *val) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); 7362306a36Sopenharmony_ci struct i2c_msg msg; 7462306a36Sopenharmony_ci unsigned char data_buf[sizeof(u32)] = { 0 }; 7562306a36Sopenharmony_ci unsigned char offset_buf[sizeof(u16)]; 7662306a36Sopenharmony_ci int r; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (len > sizeof(data_buf)) 7962306a36Sopenharmony_ci return -EINVAL; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci msg.addr = client->addr; 8262306a36Sopenharmony_ci msg.flags = 0; 8362306a36Sopenharmony_ci msg.len = sizeof(offset_buf); 8462306a36Sopenharmony_ci msg.buf = offset_buf; 8562306a36Sopenharmony_ci put_unaligned_be16(reg, offset_buf); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci r = i2c_transfer(client->adapter, &msg, 1); 8862306a36Sopenharmony_ci if (r != 1) { 8962306a36Sopenharmony_ci if (r >= 0) 9062306a36Sopenharmony_ci r = -EBUSY; 9162306a36Sopenharmony_ci goto err; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci msg.len = len; 9562306a36Sopenharmony_ci msg.flags = I2C_M_RD; 9662306a36Sopenharmony_ci msg.buf = &data_buf[sizeof(data_buf) - len]; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci r = i2c_transfer(client->adapter, &msg, 1); 9962306a36Sopenharmony_ci if (r != 1) { 10062306a36Sopenharmony_ci if (r >= 0) 10162306a36Sopenharmony_ci r = -EBUSY; 10262306a36Sopenharmony_ci goto err; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci *val = get_unaligned_be32(data_buf); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci return 0; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cierr: 11062306a36Sopenharmony_ci dev_err(&client->dev, "read from offset 0x%x error %d\n", reg, r); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci return r; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* Read a register using 8-bit access only. */ 11662306a36Sopenharmony_cistatic int ____ccs_read_addr_8only(struct ccs_sensor *sensor, u16 reg, 11762306a36Sopenharmony_ci u16 len, u32 *val) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci unsigned int i; 12062306a36Sopenharmony_ci int rval; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci *val = 0; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci for (i = 0; i < len; i++) { 12562306a36Sopenharmony_ci u32 val8; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci rval = ____ccs_read_addr(sensor, reg + i, 1, &val8); 12862306a36Sopenharmony_ci if (rval < 0) 12962306a36Sopenharmony_ci return rval; 13062306a36Sopenharmony_ci *val |= val8 << ((len - i - 1) << 3); 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci return 0; 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ciunsigned int ccs_reg_width(u32 reg) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci if (reg & CCS_FL_16BIT) 13962306a36Sopenharmony_ci return sizeof(u16); 14062306a36Sopenharmony_ci if (reg & CCS_FL_32BIT) 14162306a36Sopenharmony_ci return sizeof(u32); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci return sizeof(u8); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic u32 ireal32_to_u32_mul_1000000(struct i2c_client *client, u32 val) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci if (val >> 10 > U32_MAX / 15625) { 14962306a36Sopenharmony_ci dev_warn(&client->dev, "value %u overflows!\n", val); 15062306a36Sopenharmony_ci return U32_MAX; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci return ((val >> 10) * 15625) + 15462306a36Sopenharmony_ci (val & GENMASK(9, 0)) * 15625 / 1024; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ciu32 ccs_reg_conv(struct ccs_sensor *sensor, u32 reg, u32 val) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (reg & CCS_FL_FLOAT_IREAL) { 16262306a36Sopenharmony_ci if (CCS_LIM(sensor, CLOCK_CAPA_TYPE_CAPABILITY) & 16362306a36Sopenharmony_ci CCS_CLOCK_CAPA_TYPE_CAPABILITY_IREAL) 16462306a36Sopenharmony_ci val = ireal32_to_u32_mul_1000000(client, val); 16562306a36Sopenharmony_ci else 16662306a36Sopenharmony_ci val = float_to_u32_mul_1000000(client, val); 16762306a36Sopenharmony_ci } else if (reg & CCS_FL_IREAL) { 16862306a36Sopenharmony_ci val = ireal32_to_u32_mul_1000000(client, val); 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return val; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/* 17562306a36Sopenharmony_ci * Read a 8/16/32-bit i2c register. The value is returned in 'val'. 17662306a36Sopenharmony_ci * Returns zero if successful, or non-zero otherwise. 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_cistatic int __ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val, 17962306a36Sopenharmony_ci bool only8, bool conv) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci unsigned int len = ccs_reg_width(reg); 18262306a36Sopenharmony_ci int rval; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci if (!only8) 18562306a36Sopenharmony_ci rval = ____ccs_read_addr(sensor, CCS_REG_ADDR(reg), len, val); 18662306a36Sopenharmony_ci else 18762306a36Sopenharmony_ci rval = ____ccs_read_addr_8only(sensor, CCS_REG_ADDR(reg), len, 18862306a36Sopenharmony_ci val); 18962306a36Sopenharmony_ci if (rval < 0) 19062306a36Sopenharmony_ci return rval; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci if (!conv) 19362306a36Sopenharmony_ci return 0; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci *val = ccs_reg_conv(sensor, reg, *val); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return 0; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic int __ccs_read_data(struct ccs_reg *regs, size_t num_regs, 20162306a36Sopenharmony_ci u32 reg, u32 *val) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci unsigned int width = ccs_reg_width(reg); 20462306a36Sopenharmony_ci size_t i; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci for (i = 0; i < num_regs; i++, regs++) { 20762306a36Sopenharmony_ci u8 *data; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci if (regs->addr + regs->len < CCS_REG_ADDR(reg) + width) 21062306a36Sopenharmony_ci continue; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (regs->addr > CCS_REG_ADDR(reg)) 21362306a36Sopenharmony_ci break; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci data = ®s->value[CCS_REG_ADDR(reg) - regs->addr]; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci switch (width) { 21862306a36Sopenharmony_ci case sizeof(u8): 21962306a36Sopenharmony_ci *val = *data; 22062306a36Sopenharmony_ci break; 22162306a36Sopenharmony_ci case sizeof(u16): 22262306a36Sopenharmony_ci *val = get_unaligned_be16(data); 22362306a36Sopenharmony_ci break; 22462306a36Sopenharmony_ci case sizeof(u32): 22562306a36Sopenharmony_ci *val = get_unaligned_be32(data); 22662306a36Sopenharmony_ci break; 22762306a36Sopenharmony_ci default: 22862306a36Sopenharmony_ci WARN_ON(1); 22962306a36Sopenharmony_ci return -EINVAL; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci return 0; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return -ENOENT; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic int ccs_read_data(struct ccs_sensor *sensor, u32 reg, u32 *val) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci if (!__ccs_read_data(sensor->sdata.sensor_read_only_regs, 24162306a36Sopenharmony_ci sensor->sdata.num_sensor_read_only_regs, 24262306a36Sopenharmony_ci reg, val)) 24362306a36Sopenharmony_ci return 0; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci return __ccs_read_data(sensor->mdata.module_read_only_regs, 24662306a36Sopenharmony_ci sensor->mdata.num_module_read_only_regs, 24762306a36Sopenharmony_ci reg, val); 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic int ccs_read_addr_raw(struct ccs_sensor *sensor, u32 reg, u32 *val, 25162306a36Sopenharmony_ci bool force8, bool quirk, bool conv, bool data) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci int rval; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (data) { 25662306a36Sopenharmony_ci rval = ccs_read_data(sensor, reg, val); 25762306a36Sopenharmony_ci if (!rval) 25862306a36Sopenharmony_ci return 0; 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (quirk) { 26262306a36Sopenharmony_ci *val = 0; 26362306a36Sopenharmony_ci rval = ccs_call_quirk(sensor, reg_access, false, ®, val); 26462306a36Sopenharmony_ci if (rval == -ENOIOCTLCMD) 26562306a36Sopenharmony_ci return 0; 26662306a36Sopenharmony_ci if (rval < 0) 26762306a36Sopenharmony_ci return rval; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci if (force8) 27062306a36Sopenharmony_ci return __ccs_read_addr(sensor, reg, val, true, conv); 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci return __ccs_read_addr(sensor, reg, val, 27462306a36Sopenharmony_ci ccs_needs_quirk(sensor, 27562306a36Sopenharmony_ci CCS_QUIRK_FLAG_8BIT_READ_ONLY), 27662306a36Sopenharmony_ci conv); 27762306a36Sopenharmony_ci} 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ciint ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci return ccs_read_addr_raw(sensor, reg, val, false, true, true, true); 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ciint ccs_read_addr_8only(struct ccs_sensor *sensor, u32 reg, u32 *val) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci return ccs_read_addr_raw(sensor, reg, val, true, true, true, true); 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ciint ccs_read_addr_noconv(struct ccs_sensor *sensor, u32 reg, u32 *val) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci return ccs_read_addr_raw(sensor, reg, val, false, true, false, true); 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic int ccs_write_retry(struct i2c_client *client, struct i2c_msg *msg) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci unsigned int retries; 29762306a36Sopenharmony_ci int r; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci for (retries = 0; retries < 10; retries++) { 30062306a36Sopenharmony_ci /* 30162306a36Sopenharmony_ci * Due to unknown reason sensor stops responding. This 30262306a36Sopenharmony_ci * loop is a temporaty solution until the root cause 30362306a36Sopenharmony_ci * is found. 30462306a36Sopenharmony_ci */ 30562306a36Sopenharmony_ci r = i2c_transfer(client->adapter, msg, 1); 30662306a36Sopenharmony_ci if (r != 1) { 30762306a36Sopenharmony_ci usleep_range(1000, 2000); 30862306a36Sopenharmony_ci continue; 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci if (retries) 31262306a36Sopenharmony_ci dev_err(&client->dev, 31362306a36Sopenharmony_ci "sensor i2c stall encountered. retries: %d\n", 31462306a36Sopenharmony_ci retries); 31562306a36Sopenharmony_ci return 0; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci return r; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ciint ccs_write_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 val) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); 32462306a36Sopenharmony_ci struct i2c_msg msg; 32562306a36Sopenharmony_ci unsigned char data[6]; 32662306a36Sopenharmony_ci unsigned int len = ccs_reg_width(reg); 32762306a36Sopenharmony_ci int r; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci if (len > sizeof(data) - 2) 33062306a36Sopenharmony_ci return -EINVAL; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci msg.addr = client->addr; 33362306a36Sopenharmony_ci msg.flags = 0; /* Write */ 33462306a36Sopenharmony_ci msg.len = 2 + len; 33562306a36Sopenharmony_ci msg.buf = data; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci put_unaligned_be16(CCS_REG_ADDR(reg), data); 33862306a36Sopenharmony_ci put_unaligned_be32(val << (8 * (sizeof(val) - len)), data + 2); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci dev_dbg(&client->dev, "writing reg 0x%4.4x value 0x%*.*x (%u)\n", 34162306a36Sopenharmony_ci CCS_REG_ADDR(reg), ccs_reg_width(reg) << 1, 34262306a36Sopenharmony_ci ccs_reg_width(reg) << 1, val, val); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci r = ccs_write_retry(client, &msg); 34562306a36Sopenharmony_ci if (r) 34662306a36Sopenharmony_ci dev_err(&client->dev, 34762306a36Sopenharmony_ci "wrote 0x%x to offset 0x%x error %d\n", val, 34862306a36Sopenharmony_ci CCS_REG_ADDR(reg), r); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci return r; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci/* 35462306a36Sopenharmony_ci * Write to a 8/16-bit register. 35562306a36Sopenharmony_ci * Returns zero if successful, or non-zero otherwise. 35662306a36Sopenharmony_ci */ 35762306a36Sopenharmony_ciint ccs_write_addr(struct ccs_sensor *sensor, u32 reg, u32 val) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci int rval; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci rval = ccs_call_quirk(sensor, reg_access, true, ®, &val); 36262306a36Sopenharmony_ci if (rval == -ENOIOCTLCMD) 36362306a36Sopenharmony_ci return 0; 36462306a36Sopenharmony_ci if (rval < 0) 36562306a36Sopenharmony_ci return rval; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci return ccs_write_addr_no_quirk(sensor, reg, val); 36862306a36Sopenharmony_ci} 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci#define MAX_WRITE_LEN 32U 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ciint ccs_write_data_regs(struct ccs_sensor *sensor, struct ccs_reg *regs, 37362306a36Sopenharmony_ci size_t num_regs) 37462306a36Sopenharmony_ci{ 37562306a36Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); 37662306a36Sopenharmony_ci unsigned char buf[2 + MAX_WRITE_LEN]; 37762306a36Sopenharmony_ci struct i2c_msg msg = { 37862306a36Sopenharmony_ci .addr = client->addr, 37962306a36Sopenharmony_ci .buf = buf, 38062306a36Sopenharmony_ci }; 38162306a36Sopenharmony_ci size_t i; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci for (i = 0; i < num_regs; i++, regs++) { 38462306a36Sopenharmony_ci unsigned char *regdata = regs->value; 38562306a36Sopenharmony_ci unsigned int j; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci for (j = 0; j < regs->len; 38862306a36Sopenharmony_ci j += msg.len - 2, regdata += msg.len - 2) { 38962306a36Sopenharmony_ci char printbuf[(MAX_WRITE_LEN << 1) + 39062306a36Sopenharmony_ci 1 /* \0 */] = { 0 }; 39162306a36Sopenharmony_ci int rval; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci msg.len = min(regs->len - j, MAX_WRITE_LEN); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci bin2hex(printbuf, regdata, msg.len); 39662306a36Sopenharmony_ci dev_dbg(&client->dev, 39762306a36Sopenharmony_ci "writing msr reg 0x%4.4x value 0x%s\n", 39862306a36Sopenharmony_ci regs->addr + j, printbuf); 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci put_unaligned_be16(regs->addr + j, buf); 40162306a36Sopenharmony_ci memcpy(buf + 2, regdata, msg.len); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci msg.len += 2; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci rval = ccs_write_retry(client, &msg); 40662306a36Sopenharmony_ci if (rval) { 40762306a36Sopenharmony_ci dev_err(&client->dev, 40862306a36Sopenharmony_ci "error writing %u octets to address 0x%4.4x\n", 40962306a36Sopenharmony_ci msg.len, regs->addr + j); 41062306a36Sopenharmony_ci return rval; 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci } 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci return 0; 41662306a36Sopenharmony_ci} 417