Beispiel #1
0
/*
 * I2C read called by cmd_i2c when doing 'i2c read' and by cmd_eeprom.c
 * Begin write, send address byte(s), begin read, receive data bytes, end.
 */
int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
{
    u32 status;
    u32 i = 0;
    u8 *cur_data = data;

    /* Check the hardware can handle the requested bytes */
    if ((length < 0) || (length > ZYNQ_I2C_TRANSFERT_SIZE_MAX))
        return -EINVAL;

    /* Write the register address */
    setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
                 ZYNQ_I2C_CONTROL_HOLD);
    /*
     * Temporarily disable restart (by clearing hold)
     * It doesn't seem to work.
     */
    clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW |
                 ZYNQ_I2C_CONTROL_HOLD);
    writel(0xFF, &zynq_i2c->interrupt_status);
    while (alen--)
        writel(addr >> (8*alen), &zynq_i2c->data);
    writel(dev, &zynq_i2c->address);

    /* Wait for the address to be sent */
    if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) {
        /* Release the bus */
        clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
        return -ETIMEDOUT;
    }
    debug("Device acked address\n");

    setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
                 ZYNQ_I2C_CONTROL_RW);
    /* Start reading data */
    writel(dev, &zynq_i2c->address);
    writel(length, &zynq_i2c->transfer_size);

    /* Wait for data */
    do {
        status = zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP |
                               ZYNQ_I2C_INTERRUPT_DATA);
        if (!status) {
            /* Release the bus */
            clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
            return -ETIMEDOUT;
        }
        debug("Read %d bytes\n",
              length - readl(&zynq_i2c->transfer_size));
        for (; i < length - readl(&zynq_i2c->transfer_size); i++)
            *(cur_data++) = readl(&zynq_i2c->data);
    } while (readl(&zynq_i2c->transfer_size) != 0);
    /* All done... release the bus */
    clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);

#ifdef DEBUG
    zynq_i2c_debug_status();
#endif
    return 0;
}
Beispiel #2
0
/* Wait for an interrupt */
static u32 zynq_i2c_wait(struct zynq_i2c_registers *zynq_i2c, u32 mask)
{
	int timeout, int_status;

	for (timeout = 0; timeout < 100; timeout++) {
		udelay(100);
		int_status = readl(&zynq_i2c->interrupt_status);
		if (int_status & mask)
			break;
	}
#ifdef DEBUG
	zynq_i2c_debug_status(zynq_i2c);
#endif
	/* Clear interrupt status flags */
	writel(int_status & mask, &zynq_i2c->interrupt_status);

	return int_status & mask;
}