Exemple #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;
}
Exemple #2
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);
}
Exemple #3
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);
}
Exemple #4
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;
}
Exemple #5
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;
}
Exemple #6
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;
}