Beispiel #1
0
static int i2c_fsl_start(struct i2c_adapter *adapter)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	void __iomem *base = i2c_fsl->base;
	unsigned int temp = 0;
	int result;

	writeb(i2c_fsl->ifdr, base + FSL_I2C_IFDR);
	if (i2c_fsl->dfsrr != -1)
		writeb(i2c_fsl->dfsrr, base + FSL_I2C_DFSRR);

	/* Enable I2C controller */
	writeb(0, base + FSL_I2C_I2SR);
	writeb(I2CR_IEN, base + FSL_I2C_I2CR);

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

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

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

	i2c_fsl->stopped = 0;

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

	return result;
}
Beispiel #2
0
static int i2c_fsl_xfer(struct i2c_adapter *adapter,
                        struct i2c_msg *msgs, int num)
{
    struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
    void __iomem *base = i2c_fsl->base;
    unsigned int i, temp;
    int result;

    /* Start I2C transfer */
    for (i = 0; i < 3; i++) {
        result = i2c_fsl_start(adapter);
        if (!result)
            break;
        if (result == -EAGAIN)
            continue;
        return result;
    }

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

            result = i2c_fsl_bus_busy(adapter, 1);
            if (result)
                goto fail0;
        }
        i2c_fsl_dump_reg(adapter);

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

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

    return (result < 0) ? result : num;
}
Beispiel #3
0
static int i2c_fsl_acked(struct i2c_adapter *adapter)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	uint64_t start;

	start = get_time_ns();
	while (1) {
		unsigned int reg = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
		if (!(reg & I2SR_RXAK))
			break;

		if (is_timeout(start, MSECOND)) {
			dev_dbg(&adapter->dev, "<%s> No ACK\n", __func__);
			return -EIO;
		}
	}

	return 0;
}
Beispiel #4
0
static int i2c_fsl_start(struct i2c_adapter *adapter)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	unsigned int temp = 0;
	int result;

	fsl_i2c_write_reg(i2c_fsl->ifdr, i2c_fsl, FSL_I2C_IFDR);
#ifdef CONFIG_PPC
	if (i2c_fsl->dfsrr != -1)
		fsl_i2c_write_reg(i2c_fsl->dfsrr, i2c_fsl, FSL_I2C_DFSRR);
#endif

	/* Enable I2C controller */
	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode,
			  i2c_fsl, FSL_I2C_I2SR);
	fsl_i2c_write_reg(i2c_fsl->hwdata->i2cr_ien_opcode,
			  i2c_fsl, FSL_I2C_I2CR);

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

	/* Start I2C transaction */
	temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
	temp |= I2CR_MSTA;
	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);

	result = i2c_fsl_bus_busy(adapter, 1);
	if (result) {
		result = i2c_recover_bus(&i2c_fsl->adapter);
		if (result)
			return result;
		return -EAGAIN;
	}

	i2c_fsl->stopped = 0;

	temp |= I2CR_MTX | I2CR_TXAK;
	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);

	return result;
}
Beispiel #5
0
static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	void __iomem *base = i2c_fsl->base;
	uint64_t start;

	start = get_time_ns();
	while (1) {
		unsigned int reg = readb(base + FSL_I2C_I2SR);
		if (reg & I2SR_IIF)
			break;

		if (is_timeout(start, 100 * MSECOND)) {
			dev_err(&adapter->dev, "<%s> TXR timeout\n", __func__);
			return -EIO;
		}
	}
	writeb(0, base + FSL_I2C_I2SR);

	return 0;
}
Beispiel #6
0
static void i2c_fsl_dump_reg(struct i2c_adapter *adapter)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	u32 reg_cr, reg_sr;

	reg_cr = readb(i2c_fsl->base + FSL_I2C_I2CR);
	reg_sr = readb(i2c_fsl->base + FSL_I2C_I2SR);

	dev_dbg(adapter->dev, "CONTROL:\t"
		"IEN =%d, IIEN=%d, MSTA=%d, MTX =%d, TXAK=%d, RSTA=%d\n",
		(reg_cr & I2CR_IEN  ? 1 : 0), (reg_cr & I2CR_IIEN ? 1 : 0),
		(reg_cr & I2CR_MSTA ? 1 : 0), (reg_cr & I2CR_MTX  ? 1 : 0),
		(reg_cr & I2CR_TXAK ? 1 : 0), (reg_cr & I2CR_RSTA ? 1 : 0));

	dev_dbg(adapter->dev, "STATUS:\t"
		"ICF =%d, IAAS=%d, IB  =%d, IAL =%d, SRW =%d, IIF =%d, RXAK=%d\n",
		(reg_sr & I2SR_ICF  ? 1 : 0), (reg_sr & I2SR_IAAS ? 1 : 0),
		(reg_sr & I2SR_IBB  ? 1 : 0), (reg_sr & I2SR_IAL  ? 1 : 0),
		(reg_sr & I2SR_SRW  ? 1 : 0), (reg_sr & I2SR_IIF  ? 1 : 0),
		(reg_sr & I2SR_RXAK ? 1 : 0));
}
Beispiel #7
0
static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	uint64_t start;

	start = get_time_ns();
	while (1) {
		unsigned int reg = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
		if (reg & I2SR_IIF)
			break;

		if (is_timeout(start, 100 * MSECOND)) {
			dev_err(&adapter->dev, "<%s> TXR timeout\n", __func__);
			return -EIO;
		}
	}

	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode,
			  i2c_fsl, FSL_I2C_I2SR);

	return 0;
}
Beispiel #8
0
static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	void __iomem *base = i2c_fsl->base;
	int i, result;

	if ( !(msgs->flags & I2C_M_DATA_ONLY) ) {
		dev_dbg(&adapter->dev,
			"<%s> write slave address: addr=0x%02x\n",
			__func__, msgs->addr << 1);

		/* write slave address */
		writeb(msgs->addr << 1, base + FSL_I2C_I2DR);

		result = i2c_fsl_trx_complete(adapter);
		if (result)
			return result;
		result = i2c_fsl_acked(adapter);
		if (result)
			return result;
	}

	/* write data */
	for (i = 0; i < msgs->len; i++) {
		dev_dbg(&adapter->dev,
			"<%s> write byte: B%d=0x%02X\n",
			__func__, i, msgs->buf[i]);
		writeb(msgs->buf[i], base + FSL_I2C_I2DR);

		result = i2c_fsl_trx_complete(adapter);
		if (result)
			return result;
		result = i2c_fsl_acked(adapter);
		if (result)
			return result;
	}
	return 0;
}
Beispiel #9
0
static int i2c_fsl_bus_busy(struct i2c_adapter *adapter, int for_busy)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	uint64_t start;
	unsigned int temp;

	start = get_time_ns();
	while (1) {
		temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
		if (for_busy && (temp & I2SR_IBB))
			break;
		if (!for_busy && !(temp & I2SR_IBB))
			break;
		if (is_timeout(start, 500 * MSECOND)) {
			dev_err(&adapter->dev,
				 "<%s> timeout waiting for I2C bus %s\n",
				 __func__,for_busy ? "busy" : "not busy");
			return -EIO;
		}
	}

	return 0;
}
Beispiel #10
0
static void i2c_fsl_stop(struct i2c_adapter *adapter)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	void __iomem *base = i2c_fsl->base;
	unsigned int temp = 0;

	if (!i2c_fsl->stopped) {
		/* Stop I2C transaction */
		temp = readb(base + FSL_I2C_I2CR);
		temp &= ~(I2CR_MSTA | I2CR_MTX);
		writeb(temp, base + FSL_I2C_I2CR);
		/* wait for the stop condition to be send, otherwise the i2c
		 * controller is disabled before the STOP is sent completely */
		i2c_fsl->stopped = i2c_fsl_bus_busy(adapter, 0) ? 0 : 1;
	}

	if (!i2c_fsl->stopped) {
		i2c_fsl_bus_busy(adapter, 0);
		i2c_fsl->stopped = 1;
	}

	/* Disable I2C controller, and force our state to stopped */
	writeb(0, base + FSL_I2C_I2CR);
}
Beispiel #11
0
static void i2c_fsl_stop(struct i2c_adapter *adapter)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	unsigned int temp = 0;

	if (!i2c_fsl->stopped) {
		/* Stop I2C transaction */
		temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
		temp &= ~(I2CR_MSTA | I2CR_MTX);
		fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
		/* wait for the stop condition to be send, otherwise the i2c
		 * controller is disabled before the STOP is sent completely */
		i2c_fsl->stopped = i2c_fsl_bus_busy(adapter, 0) ? 0 : 1;
	}

	if (!i2c_fsl->stopped) {
		i2c_fsl_bus_busy(adapter, 0);
		i2c_fsl->stopped = 1;
	}

	/* Disable I2C controller, and force our state to stopped */
	temp = i2c_fsl->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
}
Beispiel #12
0
static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
{
	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
	void __iomem *base = i2c_fsl->base;
	int i, result;
	unsigned int temp;

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

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

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

		result = i2c_fsl_trx_complete(adapter);
		if (result)
			return result;
		result = i2c_fsl_acked(adapter);
		if (result)
			return result;
	}

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

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

	/* read data */
	for (i = 0; i < msgs->len; i++) {
		result = i2c_fsl_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 + FSL_I2C_I2CR);
			temp &= ~(I2CR_MSTA | I2CR_MTX);
			writeb(temp, base + FSL_I2C_I2CR);

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

			i2c_fsl_bus_busy(adapter, 0);
			i2c_fsl->stopped = 1;
		} else if (i == (msgs->len - 2)) {
			temp = readb(base + FSL_I2C_I2CR);
			temp |= I2CR_TXAK;
			writeb(temp, base + FSL_I2C_I2CR);
		}
		msgs->buf[i] = readb(base + FSL_I2C_I2DR);

		dev_dbg(&adapter->dev, "<%s> read byte: B%d=0x%02X\n",
			__func__, i, msgs->buf[i]);
	}
	return 0;
}