Esempio n. 1
0
static void i2c_imx_stop(struct i2c_adapter *adapter)
{
	struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter);
	void __iomem *base = i2c_imx->base;
	unsigned int temp = 0;

	if (!i2c_imx->stopped) {
		/* Stop I2C transaction */
		temp = readb(base + IMX_I2C_I2CR);
		temp &= ~(I2CR_MSTA | I2CR_MTX);
		writeb(temp, base + IMX_I2C_I2CR);
		/* wait for the stop condition to be send, otherwise the i2c
		 * controller is disabled before the STOP is sent completely */
		i2c_imx->stopped = i2c_imx_bus_busy(adapter, 0) ? 0 : 1;
	}
	if (cpu_is_mx1()) {
		/*
		 * This delay caused by an i.MXL hardware bug.
		 * If no (or too short) delay, no "STOP" bit will be generated.
		 */
		udelay(i2c_imx->disable_delay);
	}

	if (!i2c_imx->stopped) {
		i2c_imx_bus_busy(adapter, 0);
		i2c_imx->stopped = 1;
	}

	/* Disable I2C controller, and force our state to stopped */
	writeb(0, base + IMX_I2C_I2CR);
}
Esempio n. 2
0
static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
{
	unsigned int temp = 0;

	if (!i2c_imx->stopped) {
		/* Stop I2C transaction */
		dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
		temp = readb(i2c_imx->base + IMX_I2C_I2CR);
		temp &= ~(I2CR_MSTA | I2CR_MTX);
		writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
	}
	if (cpu_is_mx1()) {
		/*
		 * This delay caused by an i.MXL hardware bug.
		 * If no (or too short) delay, no "STOP" bit will be generated.
		 */
		udelay(i2c_imx->disable_delay);
	}

	if (!i2c_imx->stopped) {
		i2c_imx_bus_busy(i2c_imx, 0);
		i2c_imx->stopped = 1;
	}

	/* Disable I2C controller */
	writeb(0, i2c_imx->base + IMX_I2C_I2CR);
	clk_disable(i2c_imx->clk);
}
Esempio n. 3
0
static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
{
	unsigned int temp = 0;
	int result;

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

	clk_enable(i2c_imx->clk);
	writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR);
	/* Enable I2C controller */
	writeb(0, i2c_imx->base + IMX_I2C_I2SR);
	writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);

	/* Wait controller to be stable */
	udelay(50);

	/* Start I2C transaction */
	temp = readb(i2c_imx->base + IMX_I2C_I2CR);
	temp |= I2CR_MSTA;
	writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
	result = i2c_imx_bus_busy(i2c_imx, 1);
	if (result)
		return result;
	i2c_imx->stopped = 0;

	temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
	writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
	return result;
}
Esempio n. 4
0
static void i2c_imx_stop(struct i2c_adapter *adapter)
{
	struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter);
	unsigned long base = adapter->dev->map_base;
	unsigned int temp = 0;

	if (!i2c_imx->stopped) {
		/* Stop I2C transaction */
		temp = readb(base + IMX_I2C_I2CR);
		temp &= ~(I2CR_MSTA | I2CR_MTX);
		writeb(temp, base + IMX_I2C_I2CR);
		i2c_imx->stopped = 1;
	}
	if (cpu_is_mx1()) {
		/*
		 * This delay caused by an i.MXL hardware bug.
		 * If no (or too short) delay, no "STOP" bit will be generated.
		 */
		udelay(i2c_imx->disable_delay);
	}

	if (!i2c_imx->stopped)
		i2c_imx_bus_busy(adapter, 0);

	/* Disable I2C controller */
	writeb(0, base + IMX_I2C_I2CR);
}
Esempio n. 5
0
static int i2c_imx_start(struct i2c_adapter *adapter)
{
	struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter);
	unsigned long base = adapter->dev->map_base;
	unsigned int temp = 0;
	int result;

	writeb(i2c_imx->ifdr, base + IMX_I2C_IFDR);
	/* Enable I2C controller */
	writeb(0, base + IMX_I2C_I2SR);
	writeb(I2CR_IEN, base + IMX_I2C_I2CR);

	/* Wait controller to be stable */
	udelay(100);

	/* Start I2C transaction */
	temp = readb(base + IMX_I2C_I2CR);
	temp |= I2CR_MSTA;
	writeb(temp, base + IMX_I2C_I2CR);

	result = i2c_imx_bus_busy(adapter, 1);
	if (result)
		return result;

	i2c_imx->stopped = 0;

	temp |= I2CR_MTX | I2CR_TXAK;
	writeb(temp, base + IMX_I2C_I2CR);

	return result;
}
Esempio n. 6
0
/*
 * Start the controller
 */
int i2c_imx_start(void)
{
	struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)I2C_BASE;
	unsigned int temp = 0;
	int result;

	writeb(clk_idx, &i2c_regs->ifdr);

	/* Enable I2C controller */
	writeb(0, &i2c_regs->i2sr);
	writeb(I2CR_IEN, &i2c_regs->i2cr);

	/* Wait controller to be stable */
	udelay(50);

	/* Start I2C transaction */
	temp = readb(&i2c_regs->i2cr);
	temp |= I2CR_MSTA;
	writeb(temp, &i2c_regs->i2cr);

	result = i2c_imx_bus_busy(1);
	if (result)
		return result;

	temp |= I2CR_MTX | I2CR_TX_NO_AK;
	writeb(temp, &i2c_regs->i2cr);

	return 0;
}
Esempio n. 7
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. 8
0
static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
{
	int i, result;
	unsigned int temp;

	dev_dbg(&i2c_imx->adapter.dev,
		"<%s> write slave address: addr=0x%x\n",
		__func__, (msgs->addr << 1) | 0x01);

	/* write slave address */
	writeb((msgs->addr << 1) | 0x01, i2c_imx->base + IMX_I2C_I2DR);
	result = i2c_imx_trx_complete(i2c_imx);
	if (result)
		return result;
	result = i2c_imx_acked(i2c_imx);
	if (result)
		return result;

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

	/* setup bus to read data */
	temp = readb(i2c_imx->base + IMX_I2C_I2CR);
	temp &= ~I2CR_MTX;
	if (msgs->len - 1)
		temp &= ~I2CR_TXAK;
	writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
	readb(i2c_imx->base + IMX_I2C_I2DR); /* dummy read */

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

	/* read data */
	for (i = 0; i < msgs->len; i++) {
		result = i2c_imx_trx_complete(i2c_imx);
		if (result)
			return result;
		if (i == (msgs->len - 1)) {
			/* It must generate STOP before read I2DR to prevent
			   controller from generating another clock cycle */
			dev_dbg(&i2c_imx->adapter.dev,
				"<%s> clear MSTA\n", __func__);
			temp = readb(i2c_imx->base + IMX_I2C_I2CR);
			temp &= ~(I2CR_MSTA | I2CR_MTX);
			writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
			i2c_imx_bus_busy(i2c_imx, 0);
			i2c_imx->stopped = 1;
		} else if (i == (msgs->len - 2)) {
			dev_dbg(&i2c_imx->adapter.dev,
				"<%s> set TXAK\n", __func__);
			temp = readb(i2c_imx->base + IMX_I2C_I2CR);
			temp |= I2CR_TXAK;
			writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
		}
		msgs->buf[i] = readb(i2c_imx->base + IMX_I2C_I2DR);
		dev_dbg(&i2c_imx->adapter.dev,
			"<%s> read byte: B%d=0x%X\n",
			__func__, i, msgs->buf[i]);
	}
	return 0;
}
Esempio n. 9
0
/*
 * Stop the controller
 */
void i2c_imx_stop(void)
{
	struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)I2C_BASE;
	unsigned int temp = 0;

	/* Stop I2C transaction */
	temp = readb(&i2c_regs->i2cr);
	temp |= ~(I2CR_MSTA | I2CR_MTX);
	writeb(temp, &i2c_regs->i2cr);

	i2c_imx_bus_busy(0);

	/* Disable I2C controller */
	writeb(0, &i2c_regs->i2cr);
}
Esempio n. 10
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. 11
0
static int i2c_imx_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
{
	struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter);
	unsigned long base = adapter->dev->map_base;
	int i, result;
	unsigned int temp;

	dev_dbg(adapter->dev,
		"<%s> write slave address: addr=0x%02x\n",
		__func__, (msgs->addr << 1) | 0x01);

	/* clear IIF */
	writeb(0x0, base + IMX_I2C_I2SR);

	/* write slave address */
	writeb((msgs->addr << 1) | 0x01, base + IMX_I2C_I2DR);

	result = i2c_imx_trx_complete(adapter);
	if (result)
		return result;
	result = i2c_imx_acked(adapter);
	if (result)
		return result;

	result = i2c_imx_wait_iif(adapter);
	if (result)
		return result;

	/* setup bus to read data */
	temp = readb(base + IMX_I2C_I2CR);
	temp &= ~I2CR_MTX;
	if (msgs->len - 1)
		temp &= ~I2CR_TXAK;
	writeb(temp, base + IMX_I2C_I2CR);

	readb(base + IMX_I2C_I2DR);	/* dummy read */

	/* read data */
	for (i = 0; i < msgs->len; i++) {
		result = i2c_imx_trx_complete(adapter);
		if (result)
			return result;

		if (i == (msgs->len - 1)) {
			/*
			 * It must generate STOP before read I2DR to prevent
			 * controller from generating another clock cycle
			 */
			temp = readb(base + IMX_I2C_I2CR);
			temp &= ~(I2CR_MSTA | I2CR_MTX);
			writeb(temp, base + IMX_I2C_I2CR);

			/*
			 * adding this delay helps on low bitrates
			 */
			udelay(i2c_imx->disable_delay);

			i2c_imx_bus_busy(adapter, 0);
			i2c_imx->stopped = 1;
		} else if (i == (msgs->len - 2)) {
			temp = readb(base + IMX_I2C_I2CR);
			temp |= I2CR_TXAK;
			writeb(temp, base + IMX_I2C_I2CR);
		}
		msgs->buf[i] = readb(base + IMX_I2C_I2DR);

		dev_dbg(adapter->dev, "<%s> read byte: B%d=0x%02X\n",
			__func__, i, msgs->buf[i]);
	}
	return 0;
}
Esempio n. 12
0
/*
 * Read data from I2C device
 */
int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
{
	struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)I2C_BASE;
	int ret;
	unsigned int temp;
	int i;

	ret = i2c_imx_start();
	if (ret)
		return ret;

	/* write slave address */
	ret = i2c_imx_set_chip_addr(chip, 0);
	if (ret)
		return ret;

	ret = i2c_imx_set_reg_addr(addr, alen);
	if (ret)
		return ret;

	temp = readb(&i2c_regs->i2cr);
	temp |= I2CR_RSTA;
	writeb(temp, &i2c_regs->i2cr);

	ret = i2c_imx_set_chip_addr(chip, 1);
	if (ret)
		return ret;

	/* setup bus to read data */
	temp = readb(&i2c_regs->i2cr);
	temp &= ~(I2CR_MTX | I2CR_TX_NO_AK);
	if (len == 1)
		temp |= I2CR_TX_NO_AK;
	writeb(temp, &i2c_regs->i2cr);
	readb(&i2c_regs->i2dr);

	/* read data */
	for (i = 0; i < len; i++) {
		ret = i2c_imx_trx_complete();
		if (ret)
			return ret;

		/*
		 * It must generate STOP before read I2DR to prevent
		 * controller from generating another clock cycle
		 */
		if (i == (len - 1)) {
			temp = readb(&i2c_regs->i2cr);
			temp &= ~(I2CR_MSTA | I2CR_MTX);
			writeb(temp, &i2c_regs->i2cr);
			i2c_imx_bus_busy(0);
		} else if (i == (len - 2)) {
			temp = readb(&i2c_regs->i2cr);
			temp |= I2CR_TX_NO_AK;
			writeb(temp, &i2c_regs->i2cr);
		}

		buf[i] = readb(&i2c_regs->i2dr);
	}

	i2c_imx_stop();

	return ret;
}