Example #1
0
File: i2c.c Project: cpizano/lk
static void i2c_wait_for_bb(int bus)
{
	I2C_REG(bus, I2C_STAT) = 0xffff; // clear whatever is pending
	while (I2C_REG(bus, I2C_STAT) & (1<<12)) {
		I2C_REG(bus, I2C_STAT) = 0xffff; // clear whatever is pending
	}
	I2C_REG(bus, I2C_STAT) = 0xffff; // clear whatever is pending
}
Example #2
0
File: i2c.c Project: 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;
}
Example #3
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;
}
Example #4
0
void i2c_init(int speed, int slaveadd)
{
	/* scl_out = clk_func_ref / 3,
	   clk_func_ref = master_clock_freq / (divisor_2 + 1)
	   master_clock_freq = ext_clock_freq / divisor_1 */
	/* clk_func_ref = scl_out * 3,
	   divisor_2 = (master_clock_freq / clk_func_ref) - 1
	   divisor_1 = ext_clock_freq / master_clock_freq */
	/* for a target freq of 200kHz:
		ext_clock_freq = 13MHz
		clk_func_ref = 3 * 300kHZ = 600kHz
		divisor_1 = 1 => master_clock_freq = ext_clock_freq = 13MHz
		divisor_2 = 21 => clk_func_ref = 13MHz / (21+2) = 590.91 kHz
		scl_out = clk_func_ref / 3 = 509.91 kHz / 3 = 196.97kHz */
	writeb(I2C_CMD_SOFT_RESET, I2C_REG(CMD_REG));

	writeb(0x00, I2C_REG(CONF_CLK_REG));
	writeb(21, I2C_REG(CONF_CLK_FUNC_REF));

	writeb(I2C_CMD_EN_CLK, I2C_REG(CMD_REG));
}
Example #5
0
int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 mask)
{
	u8 busy;
	int i;
	int ret;

	for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) {
		ret = m5mols_read_u8(sd, I2C_REG(category, cmd, 1), &busy);
		if (ret < 0)
			return ret;
		if ((busy & mask) == mask)
			return 0;
	}
	return -EBUSY;
}
Example #6
0
int i2c_write(uint8_t chip, uint32_t addr, int alen, const uint8_t *buffer, int len)
{
	uint8_t cmd;

	/* Calypso I2C controller doesn't support fancy addressing */
	if (alen > 1)
		return -1;

	/* FIXME: implement writes longer than fifo size */
	if (len > 16)
		return -1;

	printd("i2c_write(chip=0x%02u, addr=0x%02u): ", chip, addr)

	writeb(chip & 0x3f, I2C_REG(DEVICE_REG));
	writeb(addr & 0xff, I2C_REG(ADDRESS_REG));
	
	/* we have to tell the controller how many bits we'll put into the fifo ?!? */
	writeb(len-1, I2C_REG(CONF_FIFO_REG));

	/* fill the FIFO */
	while (len--) {
		uint8_t byte = *buffer++;
		writeb(byte, I2C_REG(DATA_WR_REG));
		printd("%02X ", byte);
	}
	dputchar('\n');

	/* start the transfer */
	cmd = readb(I2C_REG(CMD_REG));
	cmd |= I2C_CMD_START;
	writeb(cmd, I2C_REG(CMD_REG));

	/* wait until transfer completes */
	while (1) {
		uint8_t reg = readb(I2C_REG(STATUS_ACTIVITY_REG));
		printd("I2C Status: 0x%02x\n", rerg & 0xf);
		if (!(reg & I2C_STATUS_IDLE)) // 0: idle 1: not idle
			break;
	}
	dputs("I2C transfer completed\n");

	return 0;
}
Example #7
0
File: i2c.c Project: cpizano/lk
static void i2c_reset_bus(int bus)
{
	I2C_REG(bus, I2C_CON) &= ~(1<<15); // make sure the bus is disabled

	/* reset the bus */
	I2C_REG(bus, I2C_SYSC) = (1<<1);
	I2C_REG(bus, I2C_CON) = (1<<15); // enable the bus
	while ((I2C_REG(bus, I2C_SYSS) & 1) == 0)
		;

	/* disable the bus again and set up some internals */
	I2C_REG(bus, I2C_CON) &= ~(1<<15); // make sure the bus is disabled

	/* set up the clock */
	I2C_REG(bus, I2C_PSC) = 23; // 96Mhz / 23 == 4Mhz
	I2C_REG(bus, I2C_SCLL) = 13;
	I2C_REG(bus, I2C_SCLH) = 15; // 4Mhz / combined divider of 40 (13+7 + 15+5) == 100khz

	/* slave address */
	I2C_REG(bus, I2C_OA0) = 1; // XXX made this up

	/* fifo is set to 1 byte trigger */
	I2C_REG(bus, I2C_BUF) = 0;

	/* disable all interrupts */
	I2C_REG(bus, I2C_IE) = 0;

	/* enable the bus */
	I2C_REG(bus, I2C_CON) = (1<<15)|(1<<10)|(1<<9); // enable, master, transmitter mode
}