示例#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;
}
示例#2
0
/*
 * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c
 * Begin write, send address byte(s), send data bytes, end.
 */
static int zynq_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
			  int alen, u8 *data, int length)
{
	u8 *cur_data = data;
	struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);

	/* Write the register address */
	setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
		ZYNQ_I2C_CONTROL_HOLD);
	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW);
	writel(0xFF, &zynq_i2c->interrupt_status);
	writel(dev, &zynq_i2c->address);
	if (alen) {
		while (alen--)
			writel(addr >> (8 * alen), &zynq_i2c->data);
		/* Start the tranfer */
		if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
			/* Release the bus */
			clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
			return -ETIMEDOUT;
		}
		debug("Device acked address\n");
	}

	while (length--) {
		writel(*(cur_data++), &zynq_i2c->data);
		if (readl(&zynq_i2c->transfer_size) == ZYNQ_I2C_FIFO_DEPTH) {
			if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
				/* Release the bus */
				clrbits_le32(&zynq_i2c->control,
					     ZYNQ_I2C_CONTROL_HOLD);
				return -ETIMEDOUT;
			}
		}
	}

	/* All done... release the bus */
	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
	/* Wait for the address and data to be sent */
	if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP))
		return -ETIMEDOUT;
	return 0;
}
示例#3
0
/*
 * I2C probe called by cmd_i2c when doing 'i2c probe'.
 * Begin read, nak data byte, end.
 */
int i2c_probe(u8 dev)
{
    /* Attempt to read a byte */
    setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
                 ZYNQ_I2C_CONTROL_RW);
    clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
    writel(0xFF, &zynq_i2c->interrupt_status);
    writel(dev, &zynq_i2c->address);
    writel(1, &zynq_i2c->transfer_size);

    return (zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP |
                          ZYNQ_I2C_INTERRUPT_NACK) &
            ZYNQ_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT;
}
示例#4
0
/*
 * I2C probe called by cmd_i2c when doing 'i2c probe'.
 * Begin read, nak data byte, end.
 */
static int zynq_i2c_probe(struct i2c_adapter *adap, u8 dev)
{
	struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);

	/* Attempt to read a byte */
	setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
		ZYNQ_I2C_CONTROL_RW);
	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
	writel(0xFF, &zynq_i2c->interrupt_status);
	writel(dev, &zynq_i2c->address);
	writel(1, &zynq_i2c->transfer_size);

	return (zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP |
		ZYNQ_I2C_INTERRUPT_NACK) &
		ZYNQ_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT;
}