Esempio n. 1
0
static int i2c_imx_xfer(struct i2c_adapter *adapter,
                        struct i2c_msg *msgs, int num)
{
    unsigned int i, temp;
    int result;
    struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);

    dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);

    /* Start I2C transfer */
    result = i2c_imx_start(i2c_imx);
    if (result)
        goto fail0;

    /* read/write data */
    for (i = 0; i < num; i++) {
        if (i) {
            dev_dbg(&i2c_imx->adapter.dev,
                    "<%s> repeated start\n", __func__);
            temp = readb(i2c_imx->base + IMX_I2C_I2CR);
            temp |= I2CR_RSTA;
            writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
            result =  i2c_imx_bus_busy(i2c_imx, 1);
            if (result)
                goto fail0;
        }
        dev_dbg(&i2c_imx->adapter.dev,
                "<%s> transfer message: %d\n", __func__, i);
        /* write/read data */
#ifdef CONFIG_I2C_DEBUG_BUS
        temp = readb(i2c_imx->base + IMX_I2C_I2CR);
        dev_dbg(&i2c_imx->adapter.dev, "<%s> CONTROL: IEN=%d, IIEN=%d, "
                "MSTA=%d, MTX=%d, TXAK=%d, RSTA=%d\n", __func__,
                (temp & I2CR_IEN ? 1 : 0), (temp & I2CR_IIEN ? 1 : 0),
                (temp & I2CR_MSTA ? 1 : 0), (temp & I2CR_MTX ? 1 : 0),
                (temp & I2CR_TXAK ? 1 : 0), (temp & I2CR_RSTA ? 1 : 0));
        temp = readb(i2c_imx->base + IMX_I2C_I2SR);
        dev_dbg(&i2c_imx->adapter.dev,
                "<%s> STATUS: ICF=%d, IAAS=%d, IBB=%d, "
                "IAL=%d, SRW=%d, IIF=%d, RXAK=%d\n", __func__,
                (temp & I2SR_ICF ? 1 : 0), (temp & I2SR_IAAS ? 1 : 0),
                (temp & I2SR_IBB ? 1 : 0), (temp & I2SR_IAL ? 1 : 0),
                (temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0),
                (temp & I2SR_RXAK ? 1 : 0));
#endif
        if (msgs[i].flags & I2C_M_RD)
            result = i2c_imx_read(i2c_imx, &msgs[i]);
        else
            result = i2c_imx_write(i2c_imx, &msgs[i]);
    }

fail0:
    /* Stop I2C transfer */
    i2c_imx_stop(i2c_imx);

    dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
            (result < 0) ? "error" : "success msg",
            (result < 0) ? result : num);
    return (result < 0) ? result : num;
}
Esempio n. 2
0
static int i2c_imx_xfer(struct i2c_adapter *adapter,
			struct i2c_msg *msgs, int num)
{
	struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter);
	void __iomem *base = i2c_imx->base;
	unsigned int i, temp;
	int result;

	/* Start I2C transfer */
	result = i2c_imx_start(adapter);
	if (result)
		goto fail0;

	/* read/write data */
	for (i = 0; i < num; i++) {
		if (i && !(msgs[i].flags & I2C_M_DATA_ONLY)) {
			temp = readb(base + IMX_I2C_I2CR);
			temp |= I2CR_RSTA;
			writeb(temp, base + IMX_I2C_I2CR);

			result = i2c_imx_bus_busy(adapter, 1);
			if (result)
				goto fail0;
		}
		i2c_imx_dump_reg(adapter);

		/* write/read data */
		if (msgs[i].flags & I2C_M_RD)
			result = i2c_imx_read(adapter, &msgs[i]);
		else
			result = i2c_imx_write(adapter, &msgs[i]);
		if (result)
			goto fail0;
	}

fail0:
	/* Stop I2C transfer */
	i2c_imx_stop(adapter);

	return (result < 0) ? result : num;
}
Esempio n. 3
0
static int i2c_imx_transfer(struct device *dev, struct i2c_msg *msgs,
		u8_t num_msgs, u16_t addr)
{
	I2C_Type *base = DEV_BASE(dev);
	struct i2c_imx_data *data = DEV_DATA(dev);
	struct i2c_master_transfer *transfer = &data->transfer;
	u8_t *buf, *buf_end;
	u16_t timeout = UINT16_MAX;
	int result = -EIO;

	if (!num_msgs) {
		return 0;
	}

	/* Wait until bus not busy */
	while ((I2C_I2SR_REG(base) & i2cStatusBusBusy) && (--timeout)) {
	}

	if (timeout == 0) {
		return result;
	}

	/* Make sure we're in a good state so slave recognises the Start */
	I2C_SetWorkMode(base, i2cModeSlave);
	transfer->currentMode = i2cModeSlave;
	/* Switch back to Rx direction. */
	I2C_SetDirMode(base, i2cDirectionReceive);
	transfer->currentDir = i2cDirectionReceive;
	/* Start condition */
	I2C_SetDirMode(base, i2cDirectionTransmit);
	transfer->currentDir = i2cDirectionTransmit;
	I2C_SetWorkMode(base, i2cModeMaster);
	transfer->currentMode = i2cModeMaster;

	/* Send address after any Start condition */
	if (!i2c_imx_send_addr(dev, addr, msgs->flags)) {
		goto finish; /* No ACK received */
	}

	do {
		if (msgs->flags & I2C_MSG_RESTART) {
			I2C_SendRepeatStart(base);
			if (!i2c_imx_send_addr(dev, addr, msgs->flags)) {
				goto finish; /* No ACK received */
			}
		}

		/* Transfer data */
		buf = msgs->buf;
		buf_end = buf + msgs->len;
		if ((msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) {
			i2c_imx_read(dev, msgs->buf, msgs->len);
		} else {
			if (!i2c_imx_write(dev, msgs->buf, msgs->len)) {
				goto finish; /* No ACK received */
			}
		}

		if (msgs->flags & I2C_MSG_STOP) {
			I2C_SetWorkMode(base, i2cModeSlave);
			transfer->currentMode = i2cModeSlave;
			I2C_SetDirMode(base, i2cDirectionReceive);
			transfer->currentDir = i2cDirectionReceive;
		}

		/* Next message */
		msgs++;
		num_msgs--;
	} while (num_msgs);

	/* Complete without error */
	result = 0;
	return result;

finish:
	I2C_SetWorkMode(base, i2cModeSlave);
	transfer->currentMode = i2cModeSlave;
	I2C_SetDirMode(base, i2cDirectionReceive);
	transfer->currentDir = i2cDirectionReceive;

	return result;
}