/* * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() * as they will try to lock the adapter a second time. */ static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) { struct i2c_adapter *adap = client->adapter; int ret; if (adap->algo->master_xfer) { struct i2c_msg msg; char buf[2]; msg.addr = client->addr; msg.flags = 0; msg.len = 2; buf[0] = command; buf[1] = val; msg.buf = buf; ret = __i2c_transfer(adap, &msg, 1); } else { union i2c_smbus_data data; data.byte = val; ret = adap->algo->smbus_xfer(adap, client->addr, client->flags, I2C_SMBUS_WRITE, command, I2C_SMBUS_BYTE_DATA, &data); } return ret; }
/** * i2c_transfer - execute a single or combined I2C message * @adap: Handle to I2C bus * @msgs: One or more messages to execute before STOP is issued to * terminate the operation; each message begins with a START. * @num: Number of messages to be executed. * * Returns negative errno, else the number of messages executed. * * Note that there is no requirement that each message be sent to * the same slave address, although that is the most common model. */ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { int ret; /* REVISIT the fault reporting model here is weak: * * - When we get an error after receiving N bytes from a slave, * there is no way to report "N". * * - When we get a NAK after transmitting N bytes to a slave, * there is no way to report "N" ... or to let the master * continue executing the rest of this combined message, if * that's the appropriate response. * * - When for example "num" is two and we successfully complete * the first message but get an error part way through the * second, it's unclear whether that should be reported as * one (discarding status on the second message) or errno * (discarding status on the first one). */ if (adap->algo->master_xfer) { ret = __i2c_transfer(adap, msgs, num); //IOLog("NouveauI2C: i2c_transfer=%d\n", ret); return ret; } else { IOLog("GeforceSensors: I2C level transfers not supported\n"); return -EOPNOTSUPP; } }
/* Write to mux register. Don't use i2c_transfer() and i2c_smbus_xfer() * for this as they will try to lock adapter a second time. */ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap, struct i2c_client *client, u8 val) { struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev); int ret = -ENODEV; if (adap->algo->master_xfer) { struct i2c_msg msg; u8 msgbuf[] = {pdata->sel_reg_addr, val}; msg.addr = client->addr; msg.flags = 0; msg.len = 2; msg.buf = msgbuf; ret = __i2c_transfer(adap, &msg, 1); if (ret >= 0 && ret != 1) ret = -EREMOTEIO; } else if (adap->algo->smbus_xfer) { union i2c_smbus_data data; data.byte = val; ret = adap->algo->smbus_xfer(adap, client->addr, client->flags, I2C_SMBUS_WRITE, pdata->sel_reg_addr, I2C_SMBUS_BYTE_DATA, &data); } return ret; }
/* * iic_tpm_read() - read from TPM register * @addr: register address to read from * @buffer: provided by caller * @len: number of bytes to read * * Read len bytes from TPM register and put them into * buffer (little-endian format, i.e. first byte is put into buffer[0]). * * NOTE: TPM is big-endian for multi-byte values. Multi-byte * values have to be swapped. * * NOTE: We can't unfortunately use the combined read/write functions * provided by the i2c core as the TPM currently does not support the * repeated start condition and due to it's special requirements. * The i2c_smbus* functions do not work for this chip. * * Return -EIO on error, 0 on success. */ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) { struct i2c_msg msg1 = { tpm_dev.client->addr, 0, 1, &addr }; struct i2c_msg msg2 = { tpm_dev.client->addr, I2C_M_RD, len, buffer }; int rc; int count; /* Lock the adapter for the duration of the whole sequence. */ if (!tpm_dev.client->adapter->algo->master_xfer) return -EOPNOTSUPP; i2c_lock_adapter(tpm_dev.client->adapter); for (count = 0; count < MAX_COUNT; count++) { rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); if (rc > 0) break; /* break here to skip sleep */ usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); } if (rc <= 0) goto out; /* After the TPM has successfully received the register address it needs * some time, thus we're sleeping here again, before retrieving the data */ for (count = 0; count < MAX_COUNT; count++) { usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1); if (rc > 0) break; } out: i2c_unlock_adapter(tpm_dev.client->adapter); if (rc <= 0) return -EIO; return 0; }
static int __i2c_mux_master_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct i2c_mux_priv *priv = adap->algo_data; struct i2c_mux_core *muxc = priv->muxc; struct i2c_adapter *parent = muxc->parent; int ret; /* Switch to the right mux port and perform the transfer. */ ret = muxc->select(muxc, priv->chan_id); if (ret >= 0) ret = __i2c_transfer(parent, msgs, num); if (muxc->deselect) muxc->deselect(muxc, priv->chan_id); return ret; }
static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, unsigned int sleep_low, unsigned int sleep_hi, u8 max_count) { int rc = -EIO; int count; struct i2c_msg msg1 = { tpm_dev.client->addr, 0, len + 1, tpm_dev.buf }; if (len > TPM_BUFSIZE) return -EINVAL; if (!tpm_dev.client->adapter->algo->master_xfer) return -EOPNOTSUPP; i2c_lock_adapter(tpm_dev.client->adapter); /* prepend the 'register address' to the buffer */ tpm_dev.buf[0] = addr; memcpy(&(tpm_dev.buf[1]), buffer, len); /* * NOTE: We have to use these special mechanisms here and unfortunately * cannot rely on the standard behavior of i2c_transfer. */ for (count = 0; count < max_count; count++) { rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); if (rc > 0) break; usleep_range(sleep_low, sleep_hi); } i2c_unlock_adapter(tpm_dev.client->adapter); if (rc <= 0) return -EIO; return 0; }
if (adap->algo->master_xfer) { struct i2c_msg msg[2] = { { .addr = client->addr, .flags = 0, .len = 1, .buf = &command }, { .addr = client->addr, .flags = I2C_M_RD, .len = 1, .buf = &val } }; ret = __i2c_transfer(adap, msg, 2); if (ret == 2) ret = val; else if (ret >= 0) ret = -EIO; } else { union i2c_smbus_data data; ret = adap->algo->smbus_xfer(adap, client->addr, client->flags, I2C_SMBUS_READ, command, I2C_SMBUS_BYTE_DATA, &data); if (!ret) ret = data.byte; }
/* set i2c to pio mode */ i2c_set_pio_mode(client->adapter, 1); reg = PMIC_GENERAL_USE_REGISTER; data = PMIC_GENERAL_USE_BOOT_BY_NONE | PMIC_GENERAL_USE_SHUTDOWN_BY_POWEROFF; buf[0] = reg; /* send register */ msgs[0].addr = client->addr; msgs[0].flags = 0; msgs[0].len = 2; msgs[0].buf[0] = reg; msgs[0].buf[1] = data; ret = __i2c_transfer(client->adapter, msgs, 1); if (ret < 0) { pr_err("%s send reg fails...\n", __func__); BUG(); } /* send register */ reg = PM800_WAKEUP1; buf[0] = reg; ret = __i2c_transfer(client->adapter, msgs, 2); if (ret < 0) { pr_err("%s send reg fails...\n", __func__); BUG(); } /* send data */