~foura/uxn900

8a428254ea413ef5c534c025acffc399eacb7aa8 — james palmer 8 months ago c468e12
*: refactoring: enum style
M inc/fs.h => inc/fs.h +7 -7
@@ 34,15 34,15 @@ struct fs_fat_entry {
	u8int	name[11];

	enum {
		FATAttrReadOnly = 1<<0,
		FATAttrHidden   = 1<<1,
		FATAttrSystem   = 1<<2,
		FATAttrVolumeID = 1<<3,
		FATAttrDir      = 1<<4,
		FATAttrArchive  = 1<<5,
		FAT_ATTR_READ_ONLY	= 1<<0,
		FAT_ATTR_HIDDEN		= 1<<1,
		FAT_ATTR_SYSTEM		= 1<<2,
		FAT_ATTR_VOLUME_ID	= 1<<3,
		FAT_ATTR_DIR		= 1<<4,
		FAT_ATTR_ARCHIVE	= 1<<5,

		/* long file names */
		FATAttrLFN = 0x0f,	
		FAT_ATTR_LFN = 0x0f,
	} attr;

	u16int cluster;

M inc/hw/bus/mmc.h => inc/hw/bus/mmc.h +4 -4
@@ 6,11 6,11 @@ struct bus_mmc {
	u16int address;

	enum {
		MMCTypeNone,
		MMC_TYPE_NONE,

		MMCTypeMMC,
		MMCTypeSD1,
		MMCTypeSD2,
		MMC_TYPE_MMC,
		MMC_TYPE_SD1,
		MMC_TYPE_SD2,
	} type;

	u32int cid[4];

M src/dev/console.c => src/dev/console.c +9 -9
@@ 6,10 6,10 @@
#include "dev/console.h"

enum {
	Rdata	= 0x00,
	Rstatus = 0x14,
		Rstatusrxfull 	= 1<<1,
		Rstatustxempty	= 1<<5,
	REG_DATA	= 0x00,
	REG_STATUS = 0x14,
		STATUS_RX_FULL 	= 1<<1,
		STATUS_TX_EMPTY	= 1<<5,
};

static char hex[] = {


@@ 24,12 24,12 @@ console_putc(char c)
{
	u32int status;

	mmio_write(PHYSUART, Rdata, c);
	mmio_write(PHYSUART, REG_DATA, c);
	for(;;) {
		status = mmio_read(PHYSUART, Rstatus);
		if(status & Rstatusrxfull)
			mmio_read(PHYSUART, Rdata);
		if(status & Rstatustxempty)
		status = mmio_read(PHYSUART, REG_STATUS);
		if(status & STATUS_RX_FULL)
			mmio_read(PHYSUART, REG_DATA);
		if(status & STATUS_TX_EMPTY)
			break;
	}
}

M src/dev/controller.c => src/dev/controller.c +32 -32
@@ 8,21 8,21 @@
#include "dev/controller.h"

enum {
	Ckp = 0x4a,

	Mshift = (1 << 2),
	Mfn    = (1 << 1),
	Mctrl  = (1 << 0),

	Rctrl = 0xd2,
		Rctrlon       = (1 << 6),
		Rctrlsoftmode = (1 << 1),
		Rctrlsoftnrst = (1 << 0),
	Rcode = 0xdb,
	Risr  = 0xe3,
	Rimr  = 0xe4,
	Redr  = 0xe8,
	Rsih  = 0xe9,
	CHIP_KEYPAD = 0x4a,

	MOD_SHIFT = (1 << 2),
	MOD_FN    = (1 << 1),
	MOD_CTRL  = (1 << 0),

	REG_CTRL = 0xd2,
		CTRL_ON       = (1 << 6),
		CTRL_SOFT_MODE = (1 << 1),
		CTRL_SOFT_NRST = (1 << 0),
	REG_CODE = 0xdb,
	REG_ISR  = 0xe3,
	REG_IMR  = 0xe4,
	REG_EDR  = 0xe8,
	REG_SIH  = 0xe9,
};

static char keymap[256] = {


@@ 54,31 54,31 @@ controller_init(dev_controller_t *ctrl)
	Uint8 buf[2];

	/* read in ctrl register */
	buf[0] = Rctrl;
	buf[0] = REG_CTRL;
	buf[1] = 0;
	i2c_read(PHYSI2C1, Ckp, buf, 1, 1);
	i2c_read(PHYSI2C1, CHIP_KEYPAD, buf, 1, 1);

	/* turn on the keyboard */
	buf[0] = Rctrl;
	buf[1] |= Rctrlon;
	buf[1] |= Rctrlsoftmode;
	buf[1] |= Rctrlsoftnrst;
	i2c_write(PHYSI2C1, Ckp, buf, 1, 1);
	buf[0] = REG_CTRL;
	buf[1] |= CTRL_ON;
	buf[1] |= CTRL_SOFT_MODE;
	buf[1] |= CTRL_SOFT_NRST;
	i2c_write(PHYSI2C1, CHIP_KEYPAD, buf, 1, 1);

	/* enable key event status */
	buf[0] = Rimr;
	buf[0] = REG_IMR;
	buf[1] = 0xfe;
	i2c_write(PHYSI2C1, Ckp, buf, 1, 1);
	i2c_write(PHYSI2C1, CHIP_KEYPAD, buf, 1, 1);

	/* enable rising and falling interrupts (qemu workaround) */
	buf[0] = Redr;
	buf[0] = REG_EDR;
	buf[1] = 0x57;
	i2c_write(PHYSI2C1, Ckp, buf, 1, 1);
	i2c_write(PHYSI2C1, CHIP_KEYPAD, buf, 1, 1);

	/* enable isr clear on read */
	buf[0] = Rsih;
	buf[0] = REG_SIH;
	buf[1] = 0x05;
	i2c_write(PHYSI2C1, Ckp, buf, 1, 1);
	i2c_write(PHYSI2C1, CHIP_KEYPAD, buf, 1, 1);

	/* clear state */
	ctrl->raw.mods = 0;


@@ 206,15 206,15 @@ controller_poll(dev_controller_t *ctrl, Uxn *u)
	/* twl4030 remembers the last 2 events */
	for(i = 0; i < 2; i++) {
		/* check status register */
		buf[0] = Risr + 2*i;
		i2c_read(PHYSI2C1, Ckp, buf, 1, 1);
		buf[0] = REG_ISR + 2*i;
		i2c_read(PHYSI2C1, CHIP_KEYPAD, buf, 1, 1);
		if(!(buf[1] & 1))
			continue;

		/* read the key state */
		buf[0] = Rcode;
		buf[0] = REG_CODE;
		for(j = 0; j < 8; j++) {
			i2c_read(PHYSI2C1, Ckp, buf, 1, 1);
			i2c_read(PHYSI2C1, CHIP_KEYPAD, buf, 1, 1);

			/* extract modifiers */
			if(j == 4) {

M src/dev/datetime.c => src/dev/datetime.c +21 -21
@@ 9,18 9,18 @@
#define bcd2bin(x) (((x) & 0x0f) + ((x) >> 4) * 10)

enum {
	Rseconds = 0x1c,
	Rminutes = 0x1d,
	Rhours   = 0x1e,
	Rdays    = 0x1f,
	REG_SECONDS = 0x1c,
	REG_MINUTES = 0x1d,
	REG_HOURS   = 0x1e,
	REG_DAYS    = 0x1f,
	Rmonths  = 0x20,
	Ryears   = 0x21,	
	Rweeks   = 0x22,
	REG_YEARS   = 0x21,
	REG_WEEKS   = 0x22,

	Rctrl   = 0x29,
		Rctrlget = 0x40,
	Rstatus = 0x2a,
	Rie     = 0x2b,
	REG_CTRL   = 0x29,
		CTRL_GET = 0x40,
	REG_STATUS = 0x2a,
	REG_IE     = 0x2b,
};

static void


@@ 28,11 28,11 @@ datetime_latch(void)
{
	Uint8 buf[2];

	buf[0] = Rctrl;
	buf[0] = REG_CTRL;
	buf[1] = 0;
	
	i2c_read(PHYSI2C1, 0x4b, buf, 1, 1);
	buf[1] |= Rctrlget;
	buf[1] |= CTRL_GET;
	i2c_write(PHYSI2C1, 0x4b, buf, 1, 1);
}



@@ 51,9 51,9 @@ datetime_snarf(Uint8 reg)
Uint8
datetime_dotw(void)
{
	Uint8 day = datetime_snarf(Rdays) - 1;
	Uint8 day = datetime_snarf(REG_DAYS) - 1;
	Uint8 month = datetime_snarf(Rmonths) - 1;
	Uint8 year = datetime_snarf(Ryears);
	Uint8 year = datetime_snarf(REG_YEARS);

	return (day + month + year + year / 4 + 21) % 7;
} 


@@ 63,9 63,9 @@ datetime_doty(void)
{
	Uint16 ret;

	Uint8 day = datetime_snarf(Rdays) - 1;
	Uint8 day = datetime_snarf(REG_DAYS) - 1;
	Uint8 month = datetime_snarf(Rmonths);
	Uint8 year = datetime_snarf(Ryears);
	Uint8 year = datetime_snarf(REG_YEARS);

	ret = 0;
	for(Uint8 i = 1; i < month; i++) {


@@ 104,7 104,7 @@ datetime_dei(Uint8 port)
	switch(port) {
	case 0x0:
	case 0x1:
		tmp = datetime_snarf(Ryears);		
		tmp = datetime_snarf(REG_YEARS);
		tmp += 2000; 

		if(port == 0x0)


@@ 117,10 117,10 @@ datetime_dei(Uint8 port)
		tmp += 1;
		break;

	case 0x3: tmp = datetime_snarf(Rdays); break;
	case 0x4: tmp = datetime_snarf(Rhours); break;
	case 0x5: tmp = datetime_snarf(Rminutes); break;
	case 0x6: tmp = datetime_snarf(Rseconds); break;
	case 0x3: tmp = datetime_snarf(REG_DAYS); break;
	case 0x4: tmp = datetime_snarf(REG_HOURS); break;
	case 0x5: tmp = datetime_snarf(REG_MINUTES); break;
	case 0x6: tmp = datetime_snarf(REG_SECONDS); break;
	case 0x7: tmp = datetime_dotw(); break;

	case 0x8:

M src/hw/bus/i2c.c => src/hw/bus/i2c.c +91 -91
@@ 9,55 9,55 @@


enum {
	Rrev     = 0x00,
	Rie      = 0x04,
		Riexrdy = 1 << 4, /* tx ready */
		Rierrdy = 1 << 3, /* rx ready */
		Rieardy = 1 << 2, /* register access ready */
		Rienack = 1 << 1, /* no acknowledgment */
		Rieal   = 1 << 0, /* arbitration lost */
	Rstat    = 0x08,
		Rstatsbd  = 1 << 15, /* single byte data */
		Rstatbb   = 1 << 12, /* bus busy */
		Rstatrovr = 1 << 11, /* receive overrun */
		Rstatxudf = 1 << 10, /* transmit underflow */
		Rstataas  = 1 << 9,  /* address as slave */
		Rstatxrdy = 1 << 4, /* tx ready */
		Rstatrrdy = 1 << 3, /* rx ready */
		Rstatardy = 1 << 2, /* register access ready */
		Rstatnack = 1 << 1, /* no acknowledgment */
		Rstatal   = 1 << 0, /* arbitration lost */
	Rwe      = 0x0c,
	Rsyss    = 0x10,
		Rsyssrdone = 1 << 0, /* reset monitoring */
	Rbuf     = 0x14,
		Rbufrdma = 1 << 15,  /* recieve dma */
		Rbufxdma = 1 << 7,   /* transmit dma */
	Rcnt     = 0x18,
	Rdata    = 0x1c,
	Rsysc    = 0x20,
	Rcon     = 0x24,
		Rconen  = 1 << 15, /* module enable */
		Rconbe  = 1 << 14, /* big endian mode */
		Rconstb = 1 << 11, /* start byte mode */
		Rconmst = 1 << 10, /* master/slave mode */
		Rcontrx = 1 << 9,  /* transmitter/receiver mode */
		Rconxa  = 1 << 8,  /* expand address */
		Rconstp = 1 << 1,  /* stop condition */
		Rconstt = 1 << 0,  /* start condition */
	Roa      = 0x28,
	Rsa      = 0x2c,
	Rpsc     = 0x30,
	Rscll    = 0x34,
	Rsclh    = 0x38,
	Rsystest = 0x3c,
	Rbufstat = 0x40,
	REG_REV     = 0x00,
	REG_IE      = 0x04,
		IE_XRDY = 1 << 4, /* tx ready */
		IE_RRDY = 1 << 3, /* rx ready */
		IE_ARDY = 1 << 2, /* register access ready */
		IE_NACK = 1 << 1, /* no acknowledgment */
		IE_AL   = 1 << 0, /* arbitration lost */
	REG_STAT    = 0x08,
		STAT_SBD  = 1 << 15, /* single byte data */
		STAT_BB   = 1 << 12, /* bus busy */
		STAT_ROVR = 1 << 11, /* receive overrun */
		STAT_XUDF = 1 << 10, /* transmit underflow */
		STAT_AAS  = 1 << 9,  /* address as slave */
		STAT_XRDY = 1 << 4, /* tx ready */
		STAT_RRDY = 1 << 3, /* rx ready */
		STAT_ARDY = 1 << 2, /* register access ready */
		STAT_NACK = 1 << 1, /* no acknowledgment */
		STAT_AL   = 1 << 0, /* arbitration lost */
	REG_WE      = 0x0c,
	REG_SYSS    = 0x10,
		REG_SYSSrdone = 1 << 0, /* reset monitoring */
	REG_BUF     = 0x14,
		REG_BUFrdma = 1 << 15,  /* recieve dma */
		REG_BUFxdma = 1 << 7,   /* transmit dma */
	REG_CNT     = 0x18,
	REG_DATA    = 0x1c,
	REG_SYSC    = 0x20,
	REG_CON     = 0x24,
		CON_EN  = 1 << 15, /* module enable */
		CON_BE  = 1 << 14, /* big endian mode */
		CON_STB = 1 << 11, /* start byte mode */
		CON_MST = 1 << 10, /* master/slave mode */
		CON_TRX = 1 << 9,  /* transmitter/receiver mode */
		CON_XA  = 1 << 8,  /* expand address */
		CON_STP = 1 << 1,  /* stop condition */
		CON_STT = 1 << 0,  /* start condition */
	REG_OA      = 0x28,
	REG_SA      = 0x2c,
	REG_PSC     = 0x30,
	REG_SCLL    = 0x34,
	REG_SCLH    = 0x38,
	REG_SYSTEST = 0x3c,
	REG_BUF_STAT = 0x40,
};

static void
i2c_wait_for_bus(u32int base)
{
	while(mmio_read(base, Rstat) & Rstatbb)
	while(mmio_read(base, REG_STAT) & STAT_BB)
		;
}



@@ 67,10 67,10 @@ i2c_flush_fifo(u32int base)
	u16int stat;

	for(;;) {
		stat = mmio_read(base, Rstat);
		if(stat == Rstatrrdy) {
			mmio_read(base, Rdata);
			mmio_write(base, Rstat, Rstatrrdy);
		stat = mmio_read(base, REG_STAT);
		if(stat == STAT_RRDY) {
			mmio_read(base, REG_DATA);
			mmio_write(base, REG_STAT, STAT_RRDY);
			timer_delay(PHYSTIMER2, 1000);
		} else {
			break;


@@ 86,13 86,13 @@ i2c_wait_for_event(u32int base)

	timeout = 1000;
	do {
		status = mmio_read(base, Rstat);
		status = mmio_read(base, REG_STAT);
		timer_delay(PHYSTIMER2, 10);
	} while(status == 0 && timeout--);

	if(timeout <= 0) {
		console_puts("i2c: timeout waiting for event\n");
		mmio_write(base, Rstat, 0xFFFF);
		mmio_write(base, REG_STAT, 0xFFFF);
	}

	return status;


@@ 101,29 101,29 @@ i2c_wait_for_event(u32int base)
void
i2c_init(u32int base)
{
	if(mmio_read(base, Rcon) & Rconen) {
		mmio_write(base, Rcon, 0);
	if(mmio_read(base, REG_CON) & CON_EN) {
		mmio_write(base, REG_CON, 0);
		timer_delay(PHYSTIMER2, 50000);
	}

	mmio_write(base, Rsysc, 0x2);
	mmio_write(base, REG_SYSC, 0x2);
	timer_delay(PHYSTIMER2, 1000);

	mmio_write(base, Rcon, Rconen);
	while(!(mmio_read(base, Rsyss) & 1))
	mmio_write(base, REG_CON, CON_EN);
	while(!(mmio_read(base, REG_SYSS) & 1))
		timer_delay(PHYSTIMER2, 1000);

	mmio_write(base, Roa, 0x11);
	mmio_write(base, Rie, Riexrdy
		| Rierrdy	
		| Rieardy
		| Rienack
		| Rieal);
	mmio_write(base, REG_OA, 0x11);
	mmio_write(base, REG_IE, IE_XRDY
		| IE_RRDY
		| IE_ARDY
		| IE_NACK
		| IE_AL);

	timer_delay(PHYSTIMER2, 1000);
	i2c_flush_fifo(base);
	mmio_write(base, Rstat, 0xFFFF);
	mmio_write(base, Rbuf, 0);
	mmio_write(base, REG_STAT, 0xFFFF);
	mmio_write(base, REG_BUF, 0);
}

void


@@ 135,9 135,9 @@ i2c_write(u32int base, u8int sa, u8int *data, u8int acnt, u8int dcnt)
	cnt = acnt + dcnt;

	i2c_wait_for_bus(base);
	mmio_write(base, Rcnt, acnt + dcnt);
	mmio_write(base, Rsa, sa);
	mmio_write(base, Rcon, Rconen | Rconmst | Rcontrx | Rconstt | Rconstp);
	mmio_write(base, REG_CNT, acnt + dcnt);
	mmio_write(base, REG_SA, sa);
	mmio_write(base, REG_CON, CON_EN | CON_MST | CON_TRX | CON_STT | CON_STP);

	while(cnt) {
		status = i2c_wait_for_event(base);


@@ 146,14 146,14 @@ i2c_write(u32int base, u8int sa, u8int *data, u8int acnt, u8int dcnt)
			goto error;
		}

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

		if(status & Rstatxrdy) {
			mmio_write(base, Rdata, *data++);
			mmio_write(base, Rstat, Rstatxrdy);
		if(status & STAT_XRDY) {
			mmio_write(base, REG_DATA, *data++);
			mmio_write(base, REG_STAT, STAT_XRDY);
			cnt--;
		} else {
			console_puts("i2c: was not ready to transmit\n");


@@ 163,11 163,11 @@ i2c_write(u32int base, u8int sa, u8int *data, u8int acnt, u8int dcnt)

	do {
		status = i2c_wait_for_event(base);
	} while(!(status & Rstatardy));
	} while(!(status & STAT_ARDY));

error:
	i2c_flush_fifo(base);
	mmio_write(base, Rstat, 0xffff);
	mmio_write(base, REG_STAT, 0xffff);
}

void


@@ 176,12 176,12 @@ i2c_read(u32int base, u8int sa, u8int *data, u8int acnt, u8int dcnt)
	u32int status;

	i2c_wait_for_bus(base);
	mmio_write(base, Rcnt, acnt);
	mmio_write(base, Rsa, sa);
	mmio_write(base, REG_CNT, acnt);
	mmio_write(base, REG_SA, sa);

	/* transmit mode if we need to send a register address */
	if(acnt)
		mmio_write(base, Rcon, Rconen | Rconmst | Rcontrx | Rconstt | Rconstp);
		mmio_write(base, REG_CON, CON_EN | CON_MST | CON_TRX | CON_STT | CON_STP);

	while(acnt) {
		status = i2c_wait_for_event(base);


@@ 190,23 190,23 @@ i2c_read(u32int base, u8int sa, u8int *data, u8int acnt, u8int dcnt)
			goto error;
		}

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

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

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



@@ 214,9 214,9 @@ i2c_read(u32int base, u8int sa, u8int *data, u8int acnt, u8int dcnt)
		}
	}

	mmio_write(base, Rcnt, dcnt);
	mmio_write(base, Rsa, sa);
	mmio_write(base, Rcon, Rconen | Rconmst | Rconstt | Rconstp);
	mmio_write(base, REG_CNT, dcnt);
	mmio_write(base, REG_SA, sa);
	mmio_write(base, REG_CON, CON_EN | CON_MST | CON_STT | CON_STP);

	while(dcnt) {
		status = i2c_wait_for_event(base);


@@ 225,27 225,27 @@ i2c_read(u32int base, u8int sa, u8int *data, u8int acnt, u8int dcnt)
			goto error;
		}

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

		if(status & Rstatrrdy) {
		if(status & STAT_RRDY) {
			dcnt--;
			*data++ = mmio_read(base, Rdata);
			mmio_write(base, Rstat, Rstatxrdy);
			*data++ = mmio_read(base, REG_DATA);
			mmio_write(base, REG_STAT, STAT_XRDY);
		} else {
			console_puts("i2c: was not ready to transmit\n");
			goto error;
		}

		if(status & Rstatardy) {
			mmio_write(base, Rstat, Rstatardy);
		if(status & STAT_ARDY) {
			mmio_write(base, REG_STAT, STAT_ARDY);
			break;
		}
	}

error:
	i2c_flush_fifo(base);
	mmio_write(base, Rstat, 0xffff);
	mmio_write(base, REG_STAT, 0xffff);
}

M src/hw/bus/mmc.c => src/hw/bus/mmc.c +144 -144
@@ 9,63 9,63 @@
#include "dev/console.h"

enum {
	RSysConfig	= 0x10,
		RSysConfigReset 	= 1<<1,

	RSysStatus	= 0x14,
		RSysStatusResetDone	= 1<<0,

	RCon		= 0x2c,
	RBlk		= 0x104,
	RArg		= 0x108,
	RCmd		= 0x10c,
	RResp0		= 0x110,
	RResp1		= 0x114,
	RResp2		= 0x118,
	RResp3		= 0x11c,
	RData		= 0x120,
	RHostCtl	= 0x128,
	RSysCtl		= 0x12c,
	RStat		= 0x130,
		RStatCommandComplete	= 1<<0,
		RStatTransferComplete	= 1<<1,
		RStatBufferWriteReady	= 1<<4,
		RStatBufferReadReady	= 1<<5,

		RStatOkMask		= 0x0000ffff,
		RStatErrMask	= 0xffff0000,

	RIntr		= 0x134,
	RIntrSignal	= 0x138,
	REG_SYS_CONFIG	= 0x10,
		SYS_CONFIG_RESET 	= 1<<1,

	REG_SYS_STATUS	= 0x14,
		SYS_STATUS_RESET_DONE	= 1<<0,

	REG_CON			= 0x2c,
	REG_BLK			= 0x104,
	REG_ARG			= 0x108,
	REG_CMD			= 0x10c,
	REG_RESP_0		= 0x110,
	REG_RESP_1		= 0x114,
	REG_RESP_2		= 0x118,
	REG_RESP_3		= 0x11c,
	REG_DATA		= 0x120,
	REG_HOST_CTL	= 0x128,
	REG_SYS_CTL		= 0x12c,
	REG_STAT		= 0x130,
		STAT_COMMAND_COMPLETE	= 1<<0,
		STAT_TRANSFER_COMPLETE	= 1<<1,
		STAT_BUFFER_WRITE_READY	= 1<<4,
		STAT_BUFFER_READ_READY	= 1<<5,

		STAT_OK_MASK		= 0x0000ffff,
		STAT_ERROR_MASK		= 0xffff0000,

	REG_INTR		= 0x134,
	REG_INTR_SIGNAL	= 0x138,
};

enum {
	CmdIdxIdle				= 0,
	CmdIdxSendOpCond		= 1,
	CmdIdxSendCid			= 2,
	CmdIdxSendRelativeAddr	= 3,
	CmdIdxSelect			= 7,
	CmdIdxSendIfCond		= 8,
	CmdIdxSendCsd			= 9,
	CmdIdxSetBlockLen		= 16,
	CmdIdxReadSingle		= 17,
	CmdIdxReadMultiple		= 18,
	CmdIdxWriteSingle		= 24,
	CmdIdxWriteMultiple		= 25,
	CmdIdxAppCommand		= 55,

	CmdAppSendOpCond	= 41,

	CmdRespNone		= 0,
	CmdResp136		= 1,
	CmdResp48		= 2,
	CmdResp48Busy	= 3,

	CmdFlagData					= 1<<21,
	CmdFlagCommandIndexCheck	= 1<<20,
	CmdFlagCommandCRCCheck		= 1<<19,
	CmdFlagDataMulti			= 1<<5,
	CmdFlagDataRead				= 1<<4,
	CMD_IDX_IDLE				= 0,
	CMD_IDX_SEND_OP_COND		= 1,
	CMD_IDX_SEND_CID			= 2,
	CMD_IDX_SEND_RELATIVE_ADDR	= 3,
	CMD_IDX_SELECT				= 7,
	CMD_IDX_SEND_IF_COND		= 8,
	CMD_IDX_SEND_CSD			= 9,
	CMD_IDX_SET_BLOCK_LEN		= 16,
	CMD_IDX_READ_SINGLE			= 17,
	CMD_IDX_READ_MULTIPLE		= 18,
	CMD_IDX_WRITE_SINGLE		= 24,
	CMD_IDX_WRITE_MULTIPLE		= 25,
	CMD_IDX_APP_COMMAND			= 55,

	CMD_APP_SEND_OP_COND	= 41,

	CMD_RESP_NONE		= 0,
	CMD_RESP_136		= 1,
	CMD_RESP_48			= 2,
	CMD_RESP_48_Busy	= 3,

	CMD_FLAG_DATA					= 1<<21,
	CMD_FLAG_COMMAND_INDEX_CHECK	= 1<<20,
	CMD_FLAG_COMMAND_CRC_CHECK		= 1<<19,
	CMD_FLAG_DATA_MULTI				= 1<<5,
	CMD_FLAG_DATA_READ				= 1<<4,
};

typedef struct bus_mmc_cmd bus_mmc_cmd_t;


@@ 93,23 93,23 @@ mmc_data_read(bus_mmc_t *mmc, bus_mmc_data_t *data)
		count = size / 4;

	while(size) {
		stat = mmio_read(mmc->base, RStat);
		if(stat & RStatErrMask)
		stat = mmio_read(mmc->base, REG_STAT);
		if(stat & STAT_ERROR_MASK)
			return 0;

		if(stat & RStatBufferReadReady) {
			mmio_mask(mmc->base, RStat, RStatBufferReadReady, RStatBufferReadReady);
		if(stat & STAT_BUFFER_READ_READY) {
			mmio_mask(mmc->base, REG_STAT, STAT_BUFFER_READ_READY, STAT_BUFFER_READ_READY);
			for(int i = 0; i < count; i++)
				*ptr++ = mmio_read(mmc->base, RData);
				*ptr++ = mmio_read(mmc->base, REG_DATA);

			size -= count * 4;
		}

		if(stat & RStatBufferWriteReady)
			mmio_mask(mmc->base, RStat, RStatBufferWriteReady, RStatBufferWriteReady);
		if(stat & STAT_BUFFER_WRITE_READY)
			mmio_mask(mmc->base, REG_STAT, STAT_BUFFER_WRITE_READY, STAT_BUFFER_WRITE_READY);

		if(stat & RStatTransferComplete) {
			mmio_mask(mmc->base, RStat, RStatTransferComplete, RStatTransferComplete);
		if(stat & STAT_TRANSFER_COMPLETE) {
			mmio_mask(mmc->base, REG_STAT, STAT_TRANSFER_COMPLETE, STAT_TRANSFER_COMPLETE);
			break;
		}
	}


@@ 134,28 134,28 @@ mmc_data_write(bus_mmc_t *mmc, bus_mmc_data_t *data)
		count = size / 4;

	while(size) {
		stat = mmio_read(mmc->base, RStat);
		if(stat & RStatErrMask)
		stat = mmio_read(mmc->base, REG_STAT);
		if(stat & STAT_ERROR_MASK)
			return stat;

		if(stat & RStatBufferWriteReady) {
			mmio_mask(mmc->base, RStat, RStatBufferWriteReady, RStatBufferWriteReady);
		if(stat & STAT_BUFFER_WRITE_READY) {
			mmio_mask(mmc->base, REG_STAT, STAT_BUFFER_WRITE_READY, STAT_BUFFER_WRITE_READY);
			for(int i = 0; i < count; i++)
				mmio_write(mmc->base, RData, *ptr++);
				mmio_write(mmc->base, REG_DATA, *ptr++);

			size -= count * 4;
		}

		if(stat & RStatBufferReadReady)
			mmio_mask(mmc->base, RStat, RStatBufferReadReady, RStatBufferReadReady);
		if(stat & STAT_BUFFER_READ_READY)
			mmio_mask(mmc->base, REG_STAT, STAT_BUFFER_READ_READY, STAT_BUFFER_READ_READY);

		if(stat & RStatTransferComplete) {
			mmio_mask(mmc->base, RStat, RStatTransferComplete, RStatTransferComplete);
		if(stat & STAT_TRANSFER_COMPLETE) {
			mmio_mask(mmc->base, REG_STAT, STAT_TRANSFER_COMPLETE, STAT_TRANSFER_COMPLETE);
			break;
		}
	}

	return mmio_read(mmc->base, RStat);
	return mmio_read(mmc->base, REG_STAT);
}

static int


@@ 170,24 170,24 @@ mmc_cmd(bus_mmc_t *mmc, bus_mmc_cmd_t *cmd, bus_mmc_data_t *data)

	/* set command specific flags */
	switch(cmd->idx) {
	case CmdIdxReadMultiple:
		c |= CmdFlagData;
		c |= CmdFlagDataMulti;
		c |= CmdFlagDataRead;
	case CMD_IDX_READ_MULTIPLE:
		c |= CMD_FLAG_DATA;
		c |= CMD_FLAG_DATA_MULTI;
		c |= CMD_FLAG_DATA_READ;
		break;

	case CmdIdxReadSingle:
		c |= CmdFlagData;
		c |= CmdFlagDataRead;
	case CMD_IDX_READ_SINGLE:
		c |= CMD_FLAG_DATA;
		c |= CMD_FLAG_DATA_READ;
		break;

	case CmdIdxWriteMultiple:
		c |= CmdFlagData;
		c |= CmdFlagDataMulti;
	case CMD_IDX_WRITE_MULTIPLE:
		c |= CMD_FLAG_DATA;
		c |= CMD_FLAG_DATA_MULTI;
		break;

	case CmdIdxWriteSingle:
		c |= CmdFlagData;
	case CMD_IDX_WRITE_SINGLE:
		c |= CMD_FLAG_DATA;
		break;
	}



@@ 197,39 197,39 @@ mmc_cmd(bus_mmc_t *mmc, bus_mmc_cmd_t *cmd, bus_mmc_data_t *data)
		d = (data->blocksize & 0x3ff) << 0;
		d |= (data->blocks & 0xffff) << 16;

		mmio_write(mmc->base, RBlk, d);
		mmio_write(mmc->base, REG_BLK, d);
	}

	/* off it goes */
	mmio_write(mmc->base, RStat, ~0);
	mmio_write(mmc->base, RArg, cmd->arg);
	mmio_write(mmc->base, RCmd, c);
	mmio_write(mmc->base, REG_STAT, ~0);
	mmio_write(mmc->base, REG_ARG, cmd->arg);
	mmio_write(mmc->base, REG_CMD, c);

	/* unpack the response */
	switch(cmd->type) {
	case CmdRespNone:
	case CMD_RESP_NONE:
		break;

	case CmdResp136:
		cmd->resp[3] = mmio_read(mmc->base, RResp0);
		cmd->resp[2] = mmio_read(mmc->base, RResp1);
		cmd->resp[1] = mmio_read(mmc->base, RResp2);
		cmd->resp[0] = mmio_read(mmc->base, RResp3);
	case CMD_RESP_136:
		cmd->resp[3] = mmio_read(mmc->base, REG_RESP_0);
		cmd->resp[2] = mmio_read(mmc->base, REG_RESP_1);
		cmd->resp[1] = mmio_read(mmc->base, REG_RESP_2);
		cmd->resp[0] = mmio_read(mmc->base, REG_RESP_3);
		break;

	default:
		cmd->resp[0] = mmio_read(mmc->base, RResp0);
		cmd->resp[0] = mmio_read(mmc->base, REG_RESP_0);
		break;
	}

	if(data != nil) {
		if(c & CmdFlagDataRead)
		if(c & CMD_FLAG_DATA_READ)
			mmc_data_read(mmc, data);
		else
			mmc_data_write(mmc, data);
	}

	return mmio_read(mmc->base, RStat);
	return mmio_read(mmc->base, REG_STAT);
}

static int


@@ 238,12 238,12 @@ mmc_app_cmd(bus_mmc_t *mmc, bus_mmc_cmd_t *cmd, bus_mmc_data_t *data)
	bus_mmc_cmd_t	app;
	int 			err;

	app.idx = CmdIdxAppCommand;
	app.idx = CMD_IDX_APP_COMMAND;
	app.arg = 0;
	app.type = CmdRespNone;
	app.type = CMD_RESP_NONE;

	err = mmc_cmd(mmc, &app, nil);
	if(err & RStatErrMask)
	if(err & STAT_ERROR_MASK)
		return err;

	return mmc_cmd(mmc, cmd, data);


@@ 255,54 255,54 @@ mmc_probe(bus_mmc_t *mmc)
	bus_mmc_cmd_t cmd;

	/* go to idle state */
	cmd.idx = CmdIdxIdle;
	cmd.idx = CMD_IDX_IDLE;
	cmd.arg = 0;
	cmd.type = CmdRespNone;
	cmd.type = CMD_RESP_NONE;

	mmc_cmd(mmc, &cmd, nil);

	/* ask for interface condition */
	cmd.idx = CmdIdxSendIfCond;
	cmd.idx = CMD_IDX_SEND_IF_COND;
	cmd.arg = 0x1aa;
	cmd.type = CmdResp48;
	if(mmc_cmd(mmc, &cmd, nil) & RStatErrMask)
	cmd.type = CMD_RESP_48;
	if(mmc_cmd(mmc, &cmd, nil) & STAT_ERROR_MASK)
		return;

	if((cmd.resp[0] & 0xff) == 0xaa) {
		mmc->type = MMCTypeSD2;
		mmc->type = MMC_TYPE_SD2;

		/* ask for sd operating condition */
		cmd.idx = CmdAppSendOpCond;
		cmd.idx = CMD_APP_SEND_OP_COND;
		cmd.arg = 0x40300000;
		cmd.type = CmdResp48;
		cmd.type = CMD_RESP_48;
		mmc_app_cmd(mmc, &cmd, nil);

		return;
	}

	/* ask for sd operating condition */
	cmd.idx = CmdAppSendOpCond;
	cmd.idx = CMD_APP_SEND_OP_COND;
	cmd.arg = 0x40300000;
	cmd.type = CmdResp48;
	if(mmc_app_cmd(mmc, &cmd, nil) & RStatErrMask) {
	cmd.type = CMD_RESP_48;
	if(mmc_app_cmd(mmc, &cmd, nil) & STAT_ERROR_MASK) {
		/* go to idle */
		cmd.idx = CmdIdxIdle;
		cmd.idx = CMD_IDX_IDLE;
		cmd.arg = 0;
		cmd.type = CmdRespNone;
		cmd.type = CMD_RESP_NONE;
		mmc_cmd(mmc, &cmd, nil);

		/* ask for mmc operating condition */
		cmd.idx = CmdIdxSendOpCond;
		cmd.idx = CMD_IDX_SEND_OP_COND;
		cmd.arg = 0;
		cmd.type = CmdResp48;
		if(mmc_cmd(mmc, &cmd, nil) & RStatErrMask)
		cmd.type = CMD_RESP_48;
		if(mmc_cmd(mmc, &cmd, nil) & STAT_ERROR_MASK)
			return;

		mmc->type = MMCTypeMMC;
		mmc->type = MMC_TYPE_MMC;
		return;
	}

	mmc->type = MMCTypeSD1;
	mmc->type = MMC_TYPE_SD1;
}

static int


@@ 311,41 311,41 @@ mmc_identify(bus_mmc_t *mmc)
	bus_mmc_cmd_t cmd;

	/* go to identify state and get cid */
	cmd.idx = CmdIdxSendCid;
	cmd.idx = CMD_IDX_SEND_CID;
	cmd.arg = 0;
	cmd.type = CmdResp136;
	if(mmc_cmd(mmc, &cmd, nil) & RStatErrMask)
	cmd.type = CMD_RESP_136;
	if(mmc_cmd(mmc, &cmd, nil) & STAT_ERROR_MASK)
		return 0;

	for(int i = 0; i < 4; i++)
		mmc->cid[i] = cmd.resp[i];

	/* go to standby state */
	cmd.idx = CmdIdxSendRelativeAddr;
	cmd.idx = CMD_IDX_SEND_RELATIVE_ADDR;
	cmd.arg = 0;
	cmd.type = CmdResp48;
	if(mmc_cmd(mmc, &cmd, nil) & RStatErrMask)
	cmd.type = CMD_RESP_48;
	if(mmc_cmd(mmc, &cmd, nil) & STAT_ERROR_MASK)
		return 0;

	/* if it's an sd card we are getting the relative address */
	if(mmc->type == MMCTypeSD1 || mmc->type == MMCTypeSD2)
	if(mmc->type == MMC_TYPE_SD1 || mmc->type == MMC_TYPE_SD2)
		mmc->address = cmd.resp[0] >> 16;

	/* get card csd */
	cmd.idx = CmdIdxSendCsd;
	cmd.idx = CMD_IDX_SEND_CSD;
	cmd.arg = mmc->address << 16;
	cmd.type = CmdResp136;
	if(mmc_cmd(mmc, &cmd, nil) & RStatErrMask)
	cmd.type = CMD_RESP_136;
	if(mmc_cmd(mmc, &cmd, nil) & STAT_ERROR_MASK)
		return 0;

	for(int i = 0; i < 4; i++)
		mmc->csd[i] = cmd.resp[i];

	/* go to transfer state */
	cmd.idx = CmdIdxSelect;
	cmd.idx = CMD_IDX_SELECT;
	cmd.arg = mmc->address << 16;
	cmd.type = CmdResp48;
	if(mmc_cmd(mmc, &cmd, nil) & RStatErrMask)
	cmd.type = CMD_RESP_48;
	if(mmc_cmd(mmc, &cmd, nil) & STAT_ERROR_MASK)
		return 0;

	return 1;


@@ 356,14 356,14 @@ mmc_block_read(bus_mmc_t *mmc, bus_mmc_data_t *data, u32int lba)
{
	bus_mmc_cmd_t cmd;

	cmd.idx = CmdIdxReadSingle;
	cmd.idx = CMD_IDX_READ_SINGLE;
	cmd.arg = lba;
	cmd.type = CmdResp48;
	cmd.type = CMD_RESP_48;

	if(data->blocks > 1)
		cmd.idx = CmdIdxReadMultiple;
		cmd.idx = CMD_IDX_READ_MULTIPLE;

	if(mmc_cmd(mmc, &cmd, data) & RStatErrMask)
	if(mmc_cmd(mmc, &cmd, data) & STAT_ERROR_MASK)
		return 0;

	return 1;


@@ 374,14 374,14 @@ mmc_block_write(bus_mmc_t *mmc, bus_mmc_data_t *data, u32int lba)
{
	bus_mmc_cmd_t cmd;

	cmd.idx = CmdIdxWriteSingle;
	cmd.idx = CMD_IDX_WRITE_SINGLE;
	cmd.arg = lba;
	cmd.type = CmdResp48;
	cmd.type = CMD_RESP_48;

	if(data->blocks > 1)
		cmd.idx = CmdIdxWriteMultiple;
		cmd.idx = CMD_IDX_WRITE_MULTIPLE;

	if(mmc_cmd(mmc, &cmd, data) & RStatErrMask)
	if(mmc_cmd(mmc, &cmd, data) & STAT_ERROR_MASK)
		return 0;

	return 1;


@@ 393,15 393,15 @@ mmc_init(bus_mmc_t *mmc)
	u32int status;

	/* software reset */
	mmio_mask(mmc->base, RSysConfig, ~0, RSysConfigReset);
	mmio_mask(mmc->base, REG_SYS_CONFIG, ~0, SYS_CONFIG_RESET);
	for(;;) {
		status = mmio_read(mmc->base, RSysStatus);
		if(status & RSysStatusResetDone)
		status = mmio_read(mmc->base, REG_SYS_STATUS);
		if(status & SYS_STATUS_RESET_DONE)
			break;
	}

	mmc_probe(mmc);
	if(mmc->type == MMCTypeNone)
	if(mmc->type == MMC_TYPE_NONE)
		return 0;

	return mmc_identify(mmc);

M src/hw/bus/spi.c => src/hw/bus/spi.c +36 -36
@@ 7,29 7,29 @@
#include "dev/console.h"

enum {
	Rrev       = 0x00,
	Rsysconfig = 0x10,
		Rsysconfigautoidle = 1<<0,
		Rsysconfigreset    = 1<<1,
		Rsysconfigwakeup   = 1<<2,
		Rsysconfigidlemode = 3<<3, /* sidlemode mask */
		Rsysconfigclockact = 3<<8, /* clockactivity mask */
	Rsysstatus = 0x14,
		Rsysstatusresetdone = 1<<0,
	Rirqstatus = 0x18,
	Rirqenable = 0x1c,
	Rmodulctrl = 0x28,

	Cconf = 0x00,
		Cconfws = 4<<7,
	Cstat = 0x04,
		Cstatrx  = 1<<0,
		Cstattx  = 1<<1,
		Cstateot = 1<<2,
	Cctrl = 0x08,
		Cctrlen = 1<<0,
	Ctx   = 0x0c,
	Crx   = 0x10,
	REG_REV			= 0x00,
	REG_SYSCONFIG	= 0x10,
		SYSCONFIG_AUTO_IDLE			= 1<<0,
		SYSCONFIG_RESET				= 1<<1,
		SYSCONFIG_WAKEUP			= 1<<2,
		SYSCONFIG_IDLE_MODE			= 3<<3, /* sidlemode mask */
		SYSCONFIG_CLOCK_ACTIVITY	= 3<<8, /* clockactivity mask */
	REG_SYSSTATUS	= 0x14,
		SYSSTATUS_RESET_DONE = 1<<0,
	REG_IRQ_STATUS	= 0x18,
	REG_IRQ_ENABLE	= 0x1c,
	REG_MODULE_CTRL	= 0x28,

	CHAN_CONF = 0x00,
		CHAN_CONF_WS = 4<<7,
	CHAN_STAT = 0x04,
		CHAN_STAT_RX  = 1<<0,
		CHAN_STAT_TX  = 1<<1,
		CHAN_STAT_EOT = 1<<2,
	CHAN_CTRL = 0x08,
		CHAN_CTRLen = 1<<0,
	CHAN_TX   = 0x0c,
	CHAN_RX   = 0x10,
};

static u32int


@@ 71,35 71,35 @@ spi_ch_mask(u32int base, u8int ch, u8int reg, u32int mask, u32int set)
void
spi_init(u32int base)
{
	mmio_mask(base, Rsysconfig, ~0, Rsysconfigreset);
	while(!(mmio_read(base, Rsysstatus) & Rsysstatusresetdone))
	mmio_mask(base, REG_SYSCONFIG, ~0, SYSCONFIG_RESET);
	while(!(mmio_read(base, REG_SYSSTATUS) & SYSSTATUS_RESET_DONE))
		;

	mmio_write(base, Rmodulctrl, 0);
	mmio_mask(base, Rsysconfig, Rsysconfigclockact, 3<<8);
	mmio_mask(base, Rsysconfig, Rsysconfigidlemode, 2<<3);
	mmio_write(base, REG_MODULE_CTRL, 0);
	mmio_mask(base, REG_SYSCONFIG, SYSCONFIG_CLOCK_ACTIVITY, 3<<8);
	mmio_mask(base, REG_SYSCONFIG, SYSCONFIG_IDLE_MODE, 2<<3);
}

void
spi_config(u32int base, u8int ch, u32int config)
{
	spi_ch_write(base, ch, Cconf, config);
	spi_ch_write(base, ch, CHAN_CONF, config);
}

void
spi_transfer(u32int base, u8int ch, u8int count, u32int *data)
{
	spi_ch_mask(base, ch, Cconf, ~Cconfws, 7<<7);
	spi_ch_mask(base, ch, Cctrl, ~Cctrlen, Cctrlen);
	spi_ch_mask(base, ch, CHAN_CONF, ~CHAN_CONF_WS, 7<<7);
	spi_ch_mask(base, ch, CHAN_CTRL, ~CHAN_CTRLen, CHAN_CTRLen);
	while(count--) {
		spi_ch_write(base, ch, Ctx, *data);
		while(!(spi_ch_read(base, ch, Cstat) & Cstatrx))
		spi_ch_write(base, ch, CHAN_TX, *data);
		while(!(spi_ch_read(base, ch, CHAN_STAT) & CHAN_STAT_RX))
			;

		*data++ = spi_ch_read(base, ch, Crx);
		while(!(spi_ch_read(base, ch, Cstat) & Cstateot))
		*data++ = spi_ch_read(base, ch, CHAN_RX);
		while(!(spi_ch_read(base, ch, CHAN_STAT) & CHAN_STAT_EOT))
			;
	}

	spi_ch_mask(base, ch, Cctrl, ~Cctrlen, 0);
	spi_ch_mask(base, ch, CHAN_CTRL, ~CHAN_CTRLen, 0);
}