~foura/uxn900

b0cfe4adf7d74b0c75b7083b5f15376f4a05c6bd — james palmer 2 months ago a8ae1f9
i2c: slight refactoring, read works now! :)
3 files changed, 74 insertions(+), 46 deletions(-)

M src/i2c.c
M src/inc/fns.h
M src/main.c
M src/i2c.c => src/i2c.c +65 -43
@@ 72,21 72,6 @@ i2c_wait_for_bus(Uint32 base)
}

static void
i2c_initiate_transfer(Uint32 base)
{
	Uint32 tmp;

	tmp = i2c_reg_read(base, Rcon);

	tmp |= Rconmst;
	tmp |= Rconstt;
	tmp |= Rconstp;
	tmp |= Rcontrx;

	i2c_reg_write(base, Rcon, tmp);
}

static void
i2c_flush_fifo(Uint32 base)
{
	Uint16 stat;


@@ 126,8 111,6 @@ i2c_wait_for_event(Uint32 base)
void
i2c_init(Uint32 base)
{
	Uint32 tmp;

	if(i2c_reg_read(base, Rcon) & Rconen) {
		i2c_reg_write(base, Rcon, 0);
		timer_delay(PHYSTIMER2, 50000);


@@ 151,29 134,25 @@ i2c_init(Uint32 base)
	i2c_flush_fifo(base);
	i2c_reg_write(base, Rstat, 0xFFFF);
	i2c_reg_write(base, Rbuf, 0);

	tmp = i2c_reg_read(base, Rcon);
	tmp |= Rconen;
	tmp |= Rconmst;
	tmp |= Rcontrx;

	i2c_reg_write(base, Rcon, tmp);
}

void
i2c_write(Uint32 base, Uint8 chip, Uint8 *data, Uint8 count)
i2c_write(Uint32 base, Uint8 sa, Uint8 *data, Uint8 acnt, Uint8 dcnt)
{
	Uint32 status;
	Uint32 cnt;

	i2c_reg_write(base, Rsa, chip);
	i2c_reg_write(base, Rcnt, count);
	cnt = acnt + dcnt;

	i2c_wait_for_bus(base);
	i2c_initiate_transfer(base);
	while(count) {
	i2c_reg_write(base, Rcnt, acnt + dcnt);
	i2c_reg_write(base, Rsa, sa);
	i2c_reg_write(base, Rcon, Rconen | Rconmst | Rcontrx | Rconstt | Rconstp);

	while(cnt) {
		status = i2c_wait_for_event(base);
		if(status == 0) {
			console_puts("i2c: status register zero after event\n");
			console_puts("i2c: status register was zero after event\n");
			goto error;
		}



@@ 185,7 164,7 @@ i2c_write(Uint32 base, Uint8 chip, Uint8 *data, Uint8 count)
		if(status & Rstatxrdy) {
			i2c_reg_write(base, Rdata, *data++);
			i2c_reg_write(base, Rstat, Rstatxrdy);
			count--;
			cnt--;
		} else {
			console_puts("i2c: was not ready to transmit\n");
			goto error;


@@ 198,23 177,60 @@ i2c_write(Uint32 base, Uint8 chip, Uint8 *data, Uint8 count)

error:
	i2c_flush_fifo(base);
	i2c_reg_write(base, Rstat, 0xFFFF);
	i2c_reg_write(base, Rstat, 0xffff);
}

void
i2c_read(Uint32 base, Uint8 chip, Uint8 *data, Uint8 count)
void i2c_read(Uint32 base, Uint8 sa, Uint8 *data, Uint8 acnt, Uint8 dcnt)
{
	Uint32 status;

	i2c_reg_write(base, Rsa, chip);
	i2c_reg_write(base, Rcnt, count);

	i2c_wait_for_bus(base);
	i2c_initiate_transfer(base);
	while(count) {
	i2c_reg_write(base, Rcnt, acnt);
	i2c_reg_write(base, Rsa, sa);

	/* transmit mode if we need to send a register address */
	if(acnt)
		i2c_reg_write(base, Rcon, Rconen | Rconmst | Rcontrx | Rconstt | Rconstp);

	while(acnt) {
		status = i2c_wait_for_event(base);
		if(status == 0) {
			console_puts("i2c: status register zero after event\n");
			console_puts("i2c: status register was zero after event\n");
			goto error;
		}

		if(status & Rstatnack) {
			console_puts("i2c: got no acknowledgement\n");
			goto error;
		}

		if(status & Rstatxrdy) {
			acnt--;
			i2c_reg_write(base, Rdata, *data++);
			i2c_reg_write(base, Rstat, Rstatxrdy);
		} else {
			console_puts("i2c: was not ready to transmit\n");
			goto error;
		}

		if(status & Rstatardy) {
			/* address phase over, skip any remaining bytes */
			i2c_reg_write(base, Rstat, Rstatardy);
			if(acnt != 0)
				data += acnt;

			break;
		}
	}

	i2c_reg_write(base, Rcnt, dcnt);
	i2c_reg_write(base, Rsa, sa);
	i2c_reg_write(base, Rcon, Rconen | Rconmst | Rconstt | Rconstp);

	while(dcnt) {
		status = i2c_wait_for_event(base);
		if(status == 0) {
			console_puts("i2c: status register was zero after event\n");
			goto error;
		}



@@ 224,15 240,21 @@ i2c_read(Uint32 base, Uint8 chip, Uint8 *data, Uint8 count)
		}

		if(status & Rstatrrdy) {
			dcnt--;
			*data++ = i2c_reg_read(base, Rdata);
			i2c_reg_write(base, Rstat, Rstatrrdy);
			i2c_reg_write(base, Rstat, Rstatxrdy);
		} else {
			console_puts("i2c: was not ready to receive\n");
			console_puts("i2c: was not ready to transmit\n");
			goto error;
		}

		if(status & Rstatardy) {
			i2c_reg_write(base, Rstat, Rstatardy);
			break;
		}
	}

error:
	i2c_flush_fifo(base);
	i2c_reg_write(base, Rstat, 0xFFFF);
	i2c_reg_write(base, Rstat, 0xffff);
}

M src/inc/fns.h => src/inc/fns.h +2 -2
@@ 3,5 3,5 @@ Uint32 timer_get(Uint32 base);
void   timer_delay(Uint32 base, Uint32 usec);

void  i2c_init(Uint32 base);
void  i2c_write(Uint32 base, Uint8 addr, Uint8 *data, Uint8 count);
void  i2c_read(Uint32 base, Uint8 addr, Uint8 *data, Uint8 count);
void  i2c_write(Uint32 base, Uint8 sa, Uint8 *data, Uint8 acnt, Uint8 dcnt);
void  i2c_read(Uint32 base, Uint8 sa, Uint8 *data, Uint8 acnt, Uint8 dcnt);

M src/main.c => src/main.c +7 -1
@@ 44,7 44,13 @@ watchdog_init(void)
	data[0] = 0x5e;
	data[1] = 0x0;

	i2c_write(PHYSI2C1, 0x4b, data, 2);
	i2c_write(PHYSI2C1, 0x4b, data, 1, 1);

	data[1] = 0xff;

	i2c_read(PHYSI2C1, 0x4b, data, 1, 1);
	if(data[1] != 0x0)
		console_puts("watchdog: failed to disable\n");
}

void