Exemple #1
0
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;
}
Exemple #2
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;
}
Exemple #3
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;
}