static int solo_i2c_handle_read(struct solo_dev *solo_dev) { prepare_read: if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) { solo_i2c_flush(solo_dev, 0); return 0; } solo_dev->i2c_msg_ptr = 0; solo_dev->i2c_msg++; solo_dev->i2c_msg_num--; if (solo_dev->i2c_msg_num == 0) { solo_i2c_stop(solo_dev); return 0; } if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) { solo_i2c_start(solo_dev); } else { if (solo_dev->i2c_msg->flags & I2C_M_RD) goto prepare_read; else solo_i2c_stop(solo_dev); } return 0; }
static int solo_i2c_handle_write(struct solo_dev *solo_dev) { retry_write: if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) { solo_reg_write(solo_dev, SOLO_IIC_TXD, solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr]); solo_dev->i2c_msg_ptr++; solo_i2c_flush(solo_dev, 1); return 0; } solo_dev->i2c_msg_ptr = 0; solo_dev->i2c_msg++; solo_dev->i2c_msg_num--; if (solo_dev->i2c_msg_num == 0) { solo_i2c_stop(solo_dev); return 0; } if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) { solo_i2c_start(solo_dev); } else { if (solo_dev->i2c_msg->flags & I2C_M_RD) solo_i2c_stop(solo_dev); else goto retry_write; } return 0; }
int solo_i2c_isr(struct solo6010_dev *solo_dev) { u32 status = solo_reg_read(solo_dev, SOLO_IIC_CTRL); int ret = -EINVAL; solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_IIC); if (status & (SOLO_IIC_STATE_TRNS & SOLO_IIC_STATE_SIG_ERR) || solo_dev->i2c_id < 0) { solo_i2c_stop(solo_dev); return -ENXIO; } switch (solo_dev->i2c_state) { case IIC_STATE_START: if (solo_dev->i2c_msg->flags & I2C_M_RD) { solo_dev->i2c_state = IIC_STATE_READ; ret = solo_i2c_handle_read(solo_dev); break; } solo_dev->i2c_state = IIC_STATE_WRITE; case IIC_STATE_WRITE: ret = solo_i2c_handle_write(solo_dev); break; case IIC_STATE_READ: solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr] = solo_reg_read(solo_dev, SOLO_IIC_RXD); solo_dev->i2c_msg_ptr++; ret = solo_i2c_handle_read(solo_dev); break; default: solo_i2c_stop(solo_dev); } return ret; }