static int ir35221_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct pmbus_driver_info *info; u8 buf[I2C_SMBUS_BLOCK_MAX]; int ret; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_READ_BLOCK_DATA)) return -ENODEV; ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf); if (ret < 0) { dev_err(&client->dev, "Failed to read PMBUS_MFR_ID\n"); return ret; } if (ret != 2 || strncmp(buf, "RI", strlen("RI"))) { dev_err(&client->dev, "MFR_ID unrecognised\n"); return -ENODEV; } ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf); if (ret < 0) { dev_err(&client->dev, "Failed to read PMBUS_MFR_MODEL\n"); return ret; } if (ret != 2 || !(buf[0] == 0x6c && buf[1] == 0x00)) { dev_err(&client->dev, "MFR_MODEL unrecognised\n"); return -ENODEV; } info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), GFP_KERNEL); if (!info) return -ENOMEM; info->read_word_data = ir35221_read_word_data; info->pages = 2; info->format[PSC_VOLTAGE_IN] = linear; info->format[PSC_VOLTAGE_OUT] = linear; info->format[PSC_CURRENT_IN] = linear; info->format[PSC_CURRENT_OUT] = linear; info->format[PSC_POWER] = linear; info->format[PSC_TEMPERATURE] = linear; info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP; info->func[1] = info->func[0]; return pmbus_do_probe(client, id, info); }
int oob_nic_get_mac(oob_nic *dev, uint8_t mac[6]) { int rc; uint8_t buf[64]; rc = i2c_smbus_read_block_data(dev->on_file, NIC_READ_MAC_CMD, buf); if (rc < 0) { rc = errno; LOG_ERR(rc, "Failed to get MAC on %d-%x", dev->on_bus, dev->on_addr); return -rc; } if (rc != NIC_READ_MAC_RES_LEN) { LOG_ERR(EFAULT, "Unexpected response len (%d) for get MAC on %d-%x", rc, dev->on_bus, dev->on_addr); return -EFAULT; } if (buf[0] != NIC_READ_MAC_RES_OPT) { LOG_ERR(EFAULT, "Unexpected response opt code (0x%x) get MAC on %d-%x", buf[0], dev->on_bus, dev->on_addr); return -EFAULT; } memcpy(mac, &buf[1], 6); LOG_DBG("Get MAC on %d-%x: %x:%x:%x:%x:%x:%x", dev->on_bus, dev->on_addr, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); return 0; }
void icspll_update_client(struct i2c_client *client) { struct icspll_data *data = client->data; int i, len; down(&data->update_lock); if ((jiffies - data->last_updated > HZ + HZ / 2) || (jiffies < data->last_updated) || !data->valid) { len = i2c_smbus_read_block_data(client, 0x00, tempdata); #ifdef DEBUG printk("icspll.o: read returned %d values\n", len); #endif if (len > ICSPLL_SIZE) len = ICSPLL_SIZE; for (i = 0; i < len; i++) data->data[i] = tempdata[i]; data->last_updated = jiffies; data->valid = 1; } up(&data->update_lock); }
static int elan_smbus_initialize(struct i2c_client *client) { u8 check[ETP_SMBUS_HELLOPACKET_LEN] = { 0x55, 0x55, 0x55, 0x55, 0x55 }; u8 values[ETP_SMBUS_HELLOPACKET_LEN] = { 0, 0, 0, 0, 0 }; int len, error; /* Get hello packet */ len = i2c_smbus_read_block_data(client, ETP_SMBUS_HELLOPACKET_CMD, values); if (len != ETP_SMBUS_HELLOPACKET_LEN) { dev_err(&client->dev, "hello packet length fail: %d\n", len); error = len < 0 ? len : -EIO; return error; } /* compare hello packet */ if (memcmp(values, check, ETP_SMBUS_HELLOPACKET_LEN)) { dev_err(&client->dev, "hello packet fail [%*px]\n", ETP_SMBUS_HELLOPACKET_LEN, values); return -ENXIO; } /* enable tp */ error = i2c_smbus_write_byte(client, ETP_SMBUS_ENABLE_TP); if (error) { dev_err(&client->dev, "failed to enable touchpad: %d\n", error); return error; } return 0; }
int oob_nic_get_status(oob_nic *dev, oob_nic_status *status) { int rc; uint8_t buf[64]; rc = i2c_smbus_read_block_data(dev->on_file, NIC_READ_STATUS_CMD, buf); if (rc < 0) { rc = errno; LOG_ERR(rc, "Failed to get status on %d-%x", dev->on_bus, dev->on_addr); return -rc; } if (rc != NIC_READ_STATUS_RES_LEN) { LOG_ERR(EFAULT, "Unexpected response len (%d) for get status on %d-%x", rc, dev->on_bus, dev->on_addr); return -EFAULT; } if (buf[0] != NIC_READ_STATUS_RES_OPT) { LOG_ERR(EFAULT, "Unexpected response opt code (0x%x) get status on %d-%x", buf[0], dev->on_bus, dev->on_addr); return -EFAULT; } memset(status, 0, sizeof(*status)); status->ons_byte1 = buf[1]; status->ons_byte2 = buf[2]; LOG_VER("Get status on %d-%x: byte1:0x%x byte2:0x%x", dev->on_bus, dev->on_addr, status->ons_byte1, status->ons_byte2); return 0; }
int read_batt_info(uint8_t channel) { if(channel==0) { //switch i2c to slot A GPIO_SetBits(BATS_I2C_SEL_PORT, BATS_I2C_SEL_PIN); } else { //switch i2c to slot B GPIO_ResetBits(BATS_I2C_SEL_PORT, BATS_I2C_SEL_PIN); } i2c_smbus_read_block_data(0x0B,0x1c,2,(uint8_t *)&pm.ps[channel].ID); i2c_smbus_read_block_data(0x0B,0x09,2,(uint8_t *)&pm.ps[channel].voltage); i2c_smbus_read_block_data(0x0B,0x0a,2,(uint8_t *)&(pm.ps[channel].current)); pm.ps[channel].power=pm.ps[channel].current*pm.ps[channel].voltage; i2c_smbus_read_block_data(0x0B,0x10,2,(uint8_t *)&(pm.ps[channel].energyAll)); i2c_smbus_read_block_data(0x0B,0x0f,2,(uint8_t *)&(pm.ps[channel].energyNow)); i2c_smbus_read_block_data(0x0B,0x17,2,(uint8_t *)&(pm.ps[channel].cycleNum)); i2c_smbus_read_block_data(0x0B,0x12,2,(uint8_t *)&(pm.ps[channel].thisWorkTime)); DEBUG("ID %x , volatge %d.%d, current %x, energyAll %d , energyNow %d , cycleNum %d ,thisWorkTime %d\r\n",\ pm.ps[channel].ID,pm.ps[channel].voltage/1000,pm.ps[channel].voltage%1000,pm.ps[channel].current,pm.ps[channel].energyAll,pm.ps[channel].energyNow\ ,pm.ps[channel].cycleNum,pm.ps[channel].thisWorkTime); return 0; }
static int elan_smbus_calibrate_result(struct i2c_client *client, u8 *val) { int error; error = i2c_smbus_read_block_data(client, ETP_SMBUS_CALIBRATE_QUERY, val); if (error < 0) return error; return 0; }
static int elan_smbus_write_fw_block(struct i2c_client *client, const u8 *page, u16 checksum, int idx) { struct device *dev = &client->dev; int error; u16 result; u8 val[3]; /* * Due to the limitation of smbus protocol limiting * transfer to 32 bytes at a time, we must split block * in 2 transfers. */ error = i2c_smbus_write_block_data(client, ETP_SMBUS_WRITE_FW_BLOCK, ETP_FW_PAGE_SIZE / 2, page); if (error) { dev_err(dev, "Failed to write page %d (part %d): %d\n", idx, 1, error); return error; } error = i2c_smbus_write_block_data(client, ETP_SMBUS_WRITE_FW_BLOCK, ETP_FW_PAGE_SIZE / 2, page + ETP_FW_PAGE_SIZE / 2); if (error) { dev_err(dev, "Failed to write page %d (part %d): %d\n", idx, 2, error); return error; } /* Wait for F/W to update one page ROM data. */ usleep_range(8000, 10000); error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val); if (error < 0) { dev_err(dev, "Failed to read IAP write result: %d\n", error); return error; } result = be16_to_cpup((__be16 *)val); if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) { dev_err(dev, "IAP reports failed write: %04hx\n", result); return -EIO; } return 0; }
/* SMB block read - wrapper over ic2_smb_read_block */ static int smb_block_read(struct rmi_transport_dev *xport, u8 commandcode, void *buf, size_t len) { struct rmi_smb_xport *rmi_smb = container_of(xport, struct rmi_smb_xport, xport); struct i2c_client *client = rmi_smb->client; int retval; retval = i2c_smbus_read_block_data(client, commandcode, buf); if (retval < 0) return retval; return retval; }
static int elan_smbus_get_product_id(struct i2c_client *client, u8 *id) { int error; u8 val[3]; error = i2c_smbus_read_block_data(client, ETP_SMBUS_UNIQUEID_CMD, val); if (error < 0) { dev_err(&client->dev, "failed to get product ID: %d\n", error); return error; } *id = val[1]; return 0; }
static int elan_smbus_calibrate_result(struct i2c_client *client, u8 *val) { int error; u8 buf[I2C_SMBUS_BLOCK_MAX] = {0}; BUILD_BUG_ON(ETP_CALIBRATE_MAX_LEN > sizeof(buf)); error = i2c_smbus_read_block_data(client, ETP_SMBUS_CALIBRATE_QUERY, buf); if (error < 0) return error; memcpy(val, buf, ETP_CALIBRATE_MAX_LEN); return 0; }
static int elan_smbus_get_product_id(struct i2c_client *client, u16 *id) { int error; u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, ETP_SMBUS_UNIQUEID_CMD, val); if (error < 0) { dev_err(&client->dev, "failed to get product ID: %d\n", error); return error; } *id = be16_to_cpup((__be16 *)val); return 0; }
static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version) { int error; u8 val[3]; error = i2c_smbus_read_block_data(client, ETP_SMBUS_SM_VERSION_CMD, val); if (error < 0) { dev_err(&client->dev, "failed to get SM version: %d\n", error); return error; } *version = val[0]; /* XXX Why 0 and not 2 as in IAP/FW versions? */ return 0; }
int rj_readblock(int subreg, void *inbuf) { int rval, retry = 3; do { rval = i2c_smbus_read_block_data(rj_file, subreg, inbuf); if (rval < 0) { retry--; usleep(RETRY_TIMEOUT); } } while ((rval < 0) && (retry > 0)); if (rval < 0) fprintf(stderr, "i2c_smbus_read_block_data failed.\n"); return rval; }
static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *ic_type, u8 *version) { int error; u8 val[3]; error = i2c_smbus_read_block_data(client, ETP_SMBUS_SM_VERSION_CMD, val); if (error < 0) { dev_err(&client->dev, "failed to get SM version: %d\n", error); return error; } *version = val[0]; *ic_type = val[1]; return 0; }
static int elan_smbus_get_max(struct i2c_client *client, unsigned int *max_x, unsigned int *max_y) { int error; u8 val[3]; error = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val); if (error) { dev_err(&client->dev, "failed to get dimensions: %d\n", error); return error; } *max_x = (0x0f & val[0]) << 8 | val[1]; *max_y = (0xf0 & val[0]) << 4 | val[2]; return 0; }
static int elan_smbus_get_resolution(struct i2c_client *client, u8 *hw_res_x, u8 *hw_res_y) { int error; u8 val[3]; error = i2c_smbus_read_block_data(client, ETP_SMBUS_RESOLUTION_CMD, val); if (error) { dev_err(&client->dev, "failed to get resolution: %d\n", error); return error; } *hw_res_x = val[1] & 0x0F; *hw_res_y = (val[1] & 0xF0) >> 4; return 0; }
static int elan_smbus_get_baseline_data(struct i2c_client *client, bool max_baseline, u8 *value) { int error; u8 val[3]; error = i2c_smbus_read_block_data(client, max_baseline ? ETP_SMBUS_MAX_BASELINE_CMD : ETP_SMBUS_MIN_BASELINE_CMD, val); if (error < 0) return error; *value = be16_to_cpup((__be16 *)val); return 0; }
static int pem_read_block(struct i2c_client *client, u8 command, u8 *data, int data_len) { u8 block_buffer[I2C_SMBUS_BLOCK_MAX]; int result; result = i2c_smbus_read_block_data(client, command, block_buffer); if (unlikely(result < 0)) goto abort; if (unlikely(result == 0xff || result != data_len)) { result = -EIO; goto abort; } memcpy(data, block_buffer, data_len); result = 0; abort: return result; }
static int elan_smbus_get_max(struct i2c_client *client, unsigned int *max_x, unsigned int *max_y) { int ret; int error; u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val); if (ret != 3) { error = ret < 0 ? ret : -EIO; dev_err(&client->dev, "failed to get dimensions: %d\n", error); return error; } *max_x = (0x0f & val[0]) << 8 | val[1]; *max_y = (0xf0 & val[0]) << 4 | val[2]; return 0; }
static int elan_smbus_get_sm_version(struct i2c_client *client, u16 *ic_type, u8 *version, u8 *clickpad) { int error; u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, ETP_SMBUS_SM_VERSION_CMD, val); if (error < 0) { dev_err(&client->dev, "failed to get SM version: %d\n", error); return error; } *version = val[0]; *ic_type = val[1]; *clickpad = val[0] & 0x10; return 0; }
static int elan_smbus_get_num_traces(struct i2c_client *client, unsigned int *x_traces, unsigned int *y_traces) { int error; u8 val[3]; error = i2c_smbus_read_block_data(client, ETP_SMBUS_XY_TRACENUM_CMD, val); if (error) { dev_err(&client->dev, "failed to get trace info: %d\n", error); return error; } *x_traces = val[1]; *y_traces = val[2]; return 0; }
static int elan_smbus_get_checksum(struct i2c_client *client, bool iap, u16 *csum) { int error; u8 val[3]; error = i2c_smbus_read_block_data(client, iap ? ETP_SMBUS_FW_CHECKSUM_CMD : ETP_SMBUS_IAP_CHECKSUM_CMD, val); if (error < 0) { dev_err(&client->dev, "failed to get %s checksum: %d\n", iap ? "IAP" : "FW", error); return error; } *csum = be16_to_cpup((__be16 *)val); return 0; }
static int elan_smbus_get_resolution(struct i2c_client *client, u8 *hw_res_x, u8 *hw_res_y) { int ret; int error; u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RESOLUTION_CMD, val); if (ret != 3) { error = ret < 0 ? ret : -EIO; dev_err(&client->dev, "failed to get resolution: %d\n", error); return error; } *hw_res_x = val[1] & 0x0F; *hw_res_y = (val[1] & 0xF0) >> 4; return 0; }
static int elan_smbus_get_version(struct i2c_client *client, bool iap, u8 *version) { int error; u8 val[3]; error = i2c_smbus_read_block_data(client, iap ? ETP_SMBUS_IAP_VERSION_CMD : ETP_SMBUS_FW_VERSION_CMD, val); if (error < 0) { dev_err(&client->dev, "failed to get %s version: %d\n", iap ? "IAP" : "FW", error); return error; } *version = val[2]; return 0; }
static int elan_smbus_get_num_traces(struct i2c_client *client, unsigned int *x_traces, unsigned int *y_traces) { int ret; int error; u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; ret = i2c_smbus_read_block_data(client, ETP_SMBUS_XY_TRACENUM_CMD, val); if (ret != 3) { error = ret < 0 ? ret : -EIO; dev_err(&client->dev, "failed to get trace info: %d\n", error); return error; } *x_traces = val[1]; *y_traces = val[2]; return 0; }
static int elan_smbus_get_report(struct i2c_client *client, u8 *report) { int len; len = i2c_smbus_read_block_data(client, ETP_SMBUS_PACKET_QUERY, &report[ETP_SMBUS_REPORT_OFFSET]); if (len < 0) { dev_err(&client->dev, "failed to read report data: %d\n", len); return len; } if (len != ETP_SMBUS_REPORT_LEN) { dev_err(&client->dev, "wrong report length (%d vs %d expected)\n", len, ETP_SMBUS_REPORT_LEN); return -EIO; } return 0; }
static int elan_smbus_iap_get_mode(struct i2c_client *client, enum tp_mode *mode) { int error; u16 constant; u8 val[3]; error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val); if (error < 0) { dev_err(&client->dev, "failed to read iap ctrol register: %d\n", error); return error; } constant = be16_to_cpup((__be16 *)val); dev_dbg(&client->dev, "iap control reg: 0x%04x.\n", constant); *mode = (constant & ETP_SMBUS_IAP_MODE_ON) ? IAP_MODE : MAIN_MODE; return 0; }
/*SMB version 2 block read - wrapper over ic2_smb_read_block */ static int smb_v2_block_read(struct rmi_phys_device *phys, u8 commandcode, u8 *buf, int len) { struct i2c_client *client = to_i2c_client(phys->dev); struct rmi_smb_data *data = phys->data; int retval; /* mutex_lock(&data->page_mutex); */ retval = i2c_smbus_read_block_data(client, commandcode, buf); phys->info.rx_count++; phys->info.rx_bytes += len; if (retval < 0) { phys->info.rx_errs++; return retval; } else if (COMMS_DEBUG(data) && !copy_to_debug_buf(&client->dev, data, buf, len)) dev_dbg(&client->dev, "read %d bytes for command %#04x:%s\n", len, commandcode, data->debug_buf); /* mutex_unlock(&data->page_mutex); */ return retval; }
static int read_block_data(int buf_fd, int mode, int *block) { uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2CDUMP_NUM_REGS]; int res, blen = 0, tmp, i; if (mode == I2C_SMBUS_BLOCK_DATA) { blen = i2c_smbus_read_block_data(buf_fd, 0, cblock); if (blen <= 0) goto fail; } else { for (res = 0; res < I2CDUMP_NUM_REGS; res += tmp) { tmp = i2c_smbus_read_i2c_block_data( buf_fd, res, I2C_SMBUS_BLOCK_MAX, cblock + res); if (tmp <= 0) { blen = tmp; goto fail; } } if (res >= I2CDUMP_NUM_REGS) res = I2CDUMP_NUM_REGS; for (i = 0; i < res; i++) block[i] = cblock[i]; if (mode != I2C_SMBUS_BLOCK_DATA) for (i = res; i < I2CDUMP_NUM_REGS; i++) block[i] = -1; } return blen; fail: bb_error_msg_and_die("block read failed: %d", blen); }