/** * cdns_i2c_master_xfer - The main i2c transfer function * @adap: pointer to the i2c adapter driver instance * @msgs: pointer to the i2c message structure * @num: the number of messages to transfer * * Initiates the send/recv activity based on the transfer message received. * * Return: number of msgs processed on success, negative error otherwise */ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { int ret, count; u32 reg; struct cdns_i2c *id = adap->algo_data; /* Check if the bus is free */ if (msgs->len) if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) return -EAGAIN; /* * Set the flag to one when multiple messages are to be * processed with a repeated start. */ if (num > 1) { /* * This controller does not give completion interrupt after a * master receive message if HOLD bit is set (repeated start), * resulting in SW timeout. Hence, if a receive message is * followed by any other message, an error is returned * indicating that this sequence is not supported. */ for (count = 0; count < num - 1; count++) { if (msgs[count].flags & I2C_M_RD) { dev_warn(adap->dev.parent, "Can't do repeated start after a receive message\n"); return -EOPNOTSUPP; } } id->bus_hold_flag = 1; reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); reg |= CDNS_I2C_CR_HOLD; cdns_i2c_writereg(reg, CDNS_I2C_CR_OFFSET); } else { id->bus_hold_flag = 0; } /* Process the msg one by one */ for (count = 0; count < num; count++, msgs++) { if (count == (num - 1)) id->bus_hold_flag = 0; ret = cdns_i2c_process_msg(id, msgs, adap); if (ret) return ret; /* Report the other error interrupts to application */ if (id->err_status) { cdns_i2c_master_reset(adap); if (id->err_status & CDNS_I2C_IXR_NACK) return -ENXIO; return -EIO; } } return num; }
/** * cdns_i2c_master_xfer - The main i2c transfer function * @adap: pointer to the i2c adapter driver instance * @msgs: pointer to the i2c message structure * @num: the number of messages to transfer * * Initiates the send/recv activity based on the transfer message received. * * Return: number of msgs processed on success, negative error otherwise */ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { int ret, count; u32 reg; struct cdns_i2c *id = adap->algo_data; /* Check if the bus is free */ if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) return -EAGAIN; /* * Set the flag to one when multiple messages are to be * processed with a repeated start. */ if (num > 1) { id->bus_hold_flag = 1; reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); reg |= CDNS_I2C_CR_HOLD; cdns_i2c_writereg(reg, CDNS_I2C_CR_OFFSET); } else { id->bus_hold_flag = 0; } /* Process the msg one by one */ for (count = 0; count < num; count++, msgs++) { if (count == (num - 1)) id->bus_hold_flag = 0; ret = cdns_i2c_process_msg(id, msgs, adap); if (ret) return ret; /* Report the other error interrupts to application */ if (id->err_status) { cdns_i2c_master_reset(adap); if (id->err_status & CDNS_I2C_IXR_NACK) return -ENXIO; return -EIO; } } return num; }