Beispiel #1
0
void i2c_write_build(int bus, uint8_t address, uint8_t reg, uint8_t val)
{
    uint32_t mcr_val;

    writeb(reg, I2C_REG_ADDR(bus,I2C_TFR));

    writeb(val, I2C_REG_ADDR(bus,I2C_TFR));

    /* MCR register for read of two byte */
    /* Set Adress type = 7bit | Stop condition | Slave address | Length */
    mcr_val = 0x1000 | 0x4000 | ((uint32_t)(address) << 1) | 0x10000;

    i2c_mcr_built = mcr_val;
}
Beispiel #2
0
int i2c_write_test(int bus)
{
    /* Wait for TX FIFO not full*/
    if (until_bit_clear(I2C_REG_ADDR(bus,I2C_RISR), RISR_TXFF, I2C_TIMEOUT)) {
        i2c_abort(bus);
        return -1;
    }

    /* ACK MTD */
    set_bit(I2C_REG_ADDR(bus, I2C_ICR),ICR_MTDIC);
    set_bit(I2C_REG_ADDR(bus, I2C_ICR),ICR_MTDWSIC);

    return 0;
}
Beispiel #3
0
Datei: i2c.c Projekt: cpizano/lk
status_t i2c_transmit(int bus, uint8_t address, const void *buf, size_t count)
{
	status_t err;

	LTRACEF("bus %d, address 0x%hhx, buf %p, count %zd\n", bus, address, buf, count);

	i2c_wait_for_bb(bus);

	I2C_REG(bus, I2C_SA) = address;
	I2C_REG(bus, I2C_CNT) = count;
	I2C_REG(bus, I2C_CON) = (1<<15)|(1<<10)|(1<<9)|(1<<1)|(1<<0); // enable, master, transmit, STP, STT

	lk_time_t t = current_time();

	const uint8_t *ptr = (const uint8_t *)buf;
	for (;;) {
		uint16_t stat = I2C_REG(bus, I2C_STAT);
		if (stat & (1<<1)) {
			// NACK
//			printf("NACK\n");
			err = ERR_GENERIC;
			goto out;
		}
		if (stat & (1<<0)) {
			// AL (arbitration lost)
//			printf("arbitration lost!\n");
			err = ERR_GENERIC;
			goto out;
		}
		if (stat & (1<<2)) {
			// ARDY
//			printf("ARDY, completed\n");
			break;
		}
		if (stat & (1<<4)) {
			// RRDY
//			printf("XRDY\n");

			// transmit a byte
			*REG8(I2C_REG_ADDR(bus, I2C_DATA)) = *ptr;
			ptr++;
		}
		I2C_REG(bus, I2C_STAT) = stat;

		if (current_time() - t > I2C_TIMEOUT) {
//			printf("i2c timeout\n");
			err = ERR_TIMED_OUT;
			goto out;
		}
	}

	err = NO_ERROR;

out:
	I2C_REG(bus, I2C_STAT) = 0xffff;
	I2C_REG(bus, I2C_CNT) = 0;

	return err;
}
Beispiel #4
0
int i2c_receive(int bus, uint8_t address, void *buf, size_t count)
{
	int err;

	LTRACEF("bus %d, address 0x%hhx, buf %p, count %zd\n", bus, address, buf, count);
		
	i2c_wait_for_bb(bus);

	I2C_REG(bus, I2C_SA) = address;
	I2C_REG(bus, I2C_CNT) = count;
	I2C_REG(bus, I2C_CON) = (1<<15)|(1<<10)|(1<<1)|(1<<0); // enable, master, STP, STT

	lk_time_t t = current_time();

	uint8_t *ptr = (uint8_t *)buf;
	for(;;) {
		uint16_t stat = I2C_REG(bus, I2C_STAT);
		if (stat & (1<<1)) {
			// NACK
//			printf("NACK\n");
			err = -1;
			goto out;
		}
		if (stat & (1<<0)) {
			// AL (arbitration lost)
//			printf("arbitration lost!\n");
			err = -1;
			goto out;
		}
		if (stat & (1<<2)) {
			// ARDY
//			printf("ARDY, completed\n");
			break;
		}
		if (stat & (1<<3)) {
			// RRDY
//			printf("RRDY\n");

			// read a byte, since our fifo threshold is set to 1 byte
			*ptr = *REG8(I2C_REG_ADDR(bus, I2C_DATA));
			ptr++;
		}
		I2C_REG(bus, I2C_STAT) = stat;

		if (current_time() - t > I2C_TIMEOUT) {
//			printf("i2c timeout\n");
			err = ERR_TIMED_OUT;
			goto out;
		}
	}

	err = 0;

out:
	I2C_REG(bus, I2C_STAT) = 0xffff;
	I2C_REG(bus, I2C_CNT) = 0;

	return err;
}
Beispiel #5
0
int i2c_probe(int bus, uint8_t address)
{
    uint32_t mcr_val;

    /* MCR register for read one byte */
    /* Set Adress type = 7bit | Set Stop Cond | Slave addr | Length | Read OP */
    mcr_val = 0x1000 | 0x4000 | ((uint32_t)(address) << 1)| 0x8000 | 0x01;

    /* program I2C_MCR */
    writel(mcr_val, I2C_REG_ADDR(bus,I2C_MCR));

    /* Wait for something in RX FIFO */
    if (until_bit_clear(I2C_REG_ADDR(bus,I2C_RISR), RISR_RXFE, I2C_TIMEOUT)) {
        i2c_abort(bus);
        return -1;
    }

    /* Flush FIFO, ACK MTD and reinit device */
    i2c_abort(bus);

    return 0;
}
Beispiel #6
0
static void i2c_abort(int bus)
{
    int nbr_of_data = FLUSH_TIMEOUT;
    /* flush TX & RX FIFO */
    set_bit(I2C_REG_ADDR(bus, I2C_CR),CR_FTX);
    until_bit_clear(I2C_REG_ADDR(bus,I2C_CR), CR_FTX, I2C_TIMEOUT);

    set_bit(I2C_REG_ADDR(bus, I2C_CR),CR_FRX);
    until_bit_clear(I2C_REG_ADDR(bus,I2C_CR), CR_FRX, I2C_TIMEOUT);

    /* Empty data */
    while (nbr_of_data--) {
        if ((!(readl(I2C_REG_ADDR(bus,I2C_CR)))) & (CR_FTX | CR_FRX)) {
            break;
        }
    }

    /* ACK MTD */
    set_bit(I2C_REG_ADDR(bus, I2C_ICR),ICR_MTDIC);
    set_bit(I2C_REG_ADDR(bus, I2C_ICR),ICR_MTDWSIC);

    /* reinit device */
    i2c_init(bus);
}
Beispiel #7
0
int i2c_read(int bus, uint8_t address, bool StopCondition, uint8_t *buffer, int len)
{
    uint32_t mcr_val;

    /* MCR register for read of len bytes */
    /* Set Adress type = 7bit | Stop condition | Slave address | Length | Read OP */
    mcr_val = (1 << MCR_SHIFT_AM) | ((uint32_t)(address) << MCR_SHIFT_A7);
    mcr_val |= ((uint32_t)(len) << MCR_SHIFT_LENGTH) | (1 << MCR_SHIFT_OP);
    if (StopCondition) {
        mcr_val |= (1 << MCR_SHIFT_P);
    }

    /* program I2C_MCR */
    writel(mcr_val, I2C_REG_ADDR(bus,I2C_MCR));

    for (int index = 0; index < len; index++)
    {
        /* Wait for something in RX FIFO */
        if (until_bit_clear(I2C_REG_ADDR(bus,I2C_RISR), RISR_RXFE, I2C_TIMEOUT)) {
            i2c_abort(bus);
            return -1;
        }

        /* Read data */
        buffer[index] = readb(I2C_REG_ADDR(bus,I2C_RFR));
    }

    /* Wait for MTD */
    if (until_bit_set(I2C_REG_ADDR(bus,I2C_RISR), RISR_MTD, I2C_TIMEOUT)) {
        i2c_abort(bus);
        return -1;
    }

    /* ACK MTD */
    set_bit(I2C_REG_ADDR(bus, I2C_ICR),ICR_MTDIC);
    set_bit(I2C_REG_ADDR(bus, I2C_ICR),ICR_MTDWSIC);

    return 0;
}
Beispiel #8
0
int i2c_write(int bus, uint8_t address, bool StopCondition, uint8_t *buffer, int len)
{
    uint32_t mcr_val;

    /* MCR register for write of len bytes */
    /* Set Adress type = 7bit | Stop condition | Slave address | Length */
    mcr_val = (1 << MCR_SHIFT_AM) | ((uint32_t)(address) << MCR_SHIFT_A7);
    mcr_val |= ((uint32_t)(len) << MCR_SHIFT_LENGTH);
    if (StopCondition) {
        mcr_val |= (1 << MCR_SHIFT_P);
    }

    /* program I2C_MCR */
    writel(mcr_val, I2C_REG_ADDR(bus,I2C_MCR));

    for (int index = 0; index < len; index++)
    {
        /* Wait for TX FIFO not full*/
        if (until_bit_clear(I2C_REG_ADDR(bus,I2C_RISR), RISR_TXFF, I2C_TIMEOUT)) {
            i2c_abort(bus);
            return -1;
        }

        /* write data */
        writeb(buffer[index],I2C_REG_ADDR(bus,I2C_TFR));
    }

    /* Wait for MTD */
    if (until_bit_set(I2C_REG_ADDR(bus,I2C_RISR), RISR_MTDWS, I2C_TIMEOUT)) {
        i2c_abort(bus);
        return -1;
    }

    /* ACK MTD */
    set_bit(I2C_REG_ADDR(bus, I2C_ICR),ICR_MTDIC);
    set_bit(I2C_REG_ADDR(bus, I2C_ICR),ICR_MTDWSIC);

    return 0;
}
Beispiel #9
0
int i2c_set_bus_speed(int bus, int speed)
{
    int return_speed;
    uint32_t brcnt2_val;

#ifdef CONFIG_I2C_FAST_SPEED
    uint32_t sm_value;
    uint32_t slave_setup_time;
#endif

#ifndef CONFIG_I2C_FAST_SPEED
    /* Set bus speed */
    /* Set standard mode 100K/s */
    clear_bit(I2C_REG_ADDR(bus, I2C_CR),CR_SM_0);
    clear_bit(I2C_REG_ADDR(bus, I2C_CR),CR_SM_1);

    /* Set BRCNT2, set BRCNT1 = 0*/
    /* Baud rate (standard) = fi2cclk / ( (BRCNT2 x 2) + Foncycle) */
    /* Foncycle = 0 */
    brcnt2_val = (uint32_t) (I2C_IN_FREQ / (speed * 2) );
    writel(brcnt2_val, I2C_REG_ADDR(bus, I2C_BRCR));

    return_speed = (int) (I2C_IN_FREQ / (brcnt2_val * 2));
#else
    if( speed > I2C_MAX_FAST_PLUS_SCL)
    {
        printf("Max i2c bus_speed supported is %d \n",
                I2C_MAX_FAST_PLUS_SCL);
        speed = I2C_MAX_FAST_PLUS_SCL;
    }

    if( speed > I2C_MAX_FAST_SCL)
    {
        /* FAST PLUS */
        sm_value = 0x11;
        brcnt2_val = (uint32_t) (I2C_IN_FREQ / (speed * 3));
        return_speed = (int)(I2C_IN_FREQ / (brcnt2_val * 3));
        slave_setup_time = SLAVE_FAST_SETUP_TIME;
    }
    else if( speed > I2C_MAX_STANDARD_SCL)
    {
        /*FAST */
        sm_value = 0x01;
        brcnt2_val = (uint32_t) (I2C_IN_FREQ / (speed * 3));
        return_speed = (int)(I2C_IN_FREQ / (brcnt2_val * 3));
        slave_setup_time = SLAVE_FAST_SETUP_TIME;
    }
    else
    {
        /* STANDARD */
        sm_value = 0x00;
        brcnt2_val = (uint32_t) (I2C_IN_FREQ / (speed * 2));
        return_speed = (int)(I2C_IN_FREQ / (brcnt2_val * 2));
        slave_setup_time = SLAVE_SETUP_TIME;
    }

    /* Set baud rate */
    writel(brcnt2_val, I2C_REG_ADDR(bus, I2C_BRCR));

    /* Set speed mode */
    writel((readl(I2C_REG_ADDR(bus, I2C_CR)) & ~0x30) | (sm_value<<4), I2C_REG_ADDR(bus, I2C_CR));

    /* Set data hold time */
    writel(DATA_HOLD_TIME, I2C_REG_ADDR(bus, I2C_THDDAT));

    /* Set slave setup time */
    writel((readl(I2C_REG_ADDR(bus, I2C_SCR)) & ~0xFFFF0000) | (slave_setup_time<<16),
            I2C_REG_ADDR(bus, I2C_SCR));
#endif

    /* Save current speed */
    bus_speeds[bus] = return_speed;

    return return_speed;
}
Beispiel #10
0
void i2c_write_go(int bus)
{
    /* program I2C_MCR */
    writel(i2c_mcr_built, I2C_REG_ADDR(bus,I2C_MCR));
}
Beispiel #11
0
void i2c_init(int bus)
{
    uint32_t brcnt2_val;

    if (I2C_LAST_BUS < bus) {
        printf("I2C bus %d not available\n", bus);
        return;
    }

    /* Disable I2C */
    clear_bit(I2C_REG_ADDR(bus, I2C_CR),CR_PE);

    /* Clear registers */
    writel(0, I2C_REG_ADDR(bus,I2C_CR));
    writel(0, I2C_REG_ADDR(bus,I2C_SCR));
    writel(0, I2C_REG_ADDR(bus,I2C_HSMCR));
    writel(0, I2C_REG_ADDR(bus,I2C_TFTR));
    writel(0, I2C_REG_ADDR(bus,I2C_RFTR));
    writel(0, I2C_REG_ADDR(bus,I2C_DMAR));

    /* Set bus speed */
    /* Set standard mode 100K/s */
    clear_bit(I2C_REG_ADDR(bus, I2C_CR),CR_SM_0);
    clear_bit(I2C_REG_ADDR(bus, I2C_CR),CR_SM_1);

    /* Set BRCNT2, set BRCNT1 = 0*/
    /* Baud rate (standard) = fi2cclk / ( (BRCNT2 x 2) + Foncycle) */
    /* Foncycle = 0 */
    brcnt2_val = (uint32_t) (I2C_IN_FREQ / (I2C_SPEED * 2) );
    writel(brcnt2_val, I2C_REG_ADDR(bus, I2C_BRCR));

    /* Set Slave data setup time */
    writel((readl(I2C_REG_ADDR(bus, I2C_SCR)) & 0x0000FFFF) | (SLAVE_SETUP_TIME<<16),
             I2C_REG_ADDR(bus, I2C_SCR));

    /* Disable DMA */
    clear_bit(I2C_REG_ADDR(bus, I2C_CR),0x800); //BIT11

    /* Disable interrupts */
    writel(0,I2C_REG_ADDR(bus,I2C_IMSCR));

    /* Set Operating mode (MASTER ONLY)*/
    clear_bit(I2C_REG_ADDR(bus, I2C_CR),CR_OM_1);
    set_bit(I2C_REG_ADDR(bus, I2C_CR),CR_OM_0);

    /* Set FIFO threashold */
    writel(4,I2C_REG_ADDR(bus,I2C_TFTR));
    writel(4,I2C_REG_ADDR(bus,I2C_RFTR));

    /* Enable I2C */
    set_bit(I2C_REG_ADDR(bus, I2C_CR),CR_PE);
}