示例#1
0
文件: sdmmc.c 项目: bowies/Team3
//---------------------------------------------------------------------------------
void sdmmcValueHandler(u32 value, void* user_data) {
//---------------------------------------------------------------------------------
	int result;
	
	switch(value) {

	case SDMMC_HAVE_SD:
		result = sdmmc_read16(REG_SDSTATUS0);
		fifoSendValue32(FIFO_SDMMC, result);
		break;

	case SDMMC_SD_START:
		if (sdmmc_read16(REG_SDSTATUS0) == 0) {
			result = 1;
		} else {
			sdmmc_controller_init();
			result = sdmmc_sdcard_init();
		}
		fifoSendValue32(FIFO_SDMMC, result);
		break;

	case SDMMC_SD_IS_INSERTED:
		result = sdmmc_cardinserted();
		fifoSendValue32(FIFO_SDMMC, result);
		break;

	case SDMMC_SD_STOP:
		break;

	}
}
示例#2
0
文件: sdmmc.c 项目: bowies/Team3
//---------------------------------------------------------------------------------
void sdmmc_send_acmd41(u32 arg, u32 *resp) {
//---------------------------------------------------------------------------------
	sdmmc_send_command(55, 0x0000, 0x000);
	*resp = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1)<<16);

	sdmmc_send_command(41, (u16)arg, (arg>>16));
	
	*resp = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1)<<16);
}
示例#3
0
文件: sdmmc.c 项目: bowies/Team3
//---------------------------------------------------------------------------------
int sdmmc_send_command(u16 cmd, u16 arg0, u16 arg1) {
//---------------------------------------------------------------------------------
	u16 is_stat0, was_stat0;
	u16 is_stat1, was_stat1;

	sdmmc_write16(REG_SDCMDARG0, arg0);
	sdmmc_write16(REG_SDCMDARG1, arg1);

	was_stat1 = sdmmc_read16(REG_SDSTATUS1);

	while(sdmmc_read16(REG_SDSTATUS1) & 0x4000);

	is_stat1 = sdmmc_read16(REG_SDSTATUS1);

	sdmmc_mask16(REG_SDSTATUS1, 0x807F, 0);
	sdmmc_mask16(REG_SDSTATUS0, 0x0001, 0);
	sdmmc_mask16(REG_SDSTATUS0, 0x0004, 0);
	sdmmc_mask16(REG_SDSTATUS1, 0x100, 0);
	sdmmc_mask16(REG_SDSTATUS1, 0x200, 0);
	sdmmc_mask16(REG_SDSTOP, 1, 0);
	sdmmc_mask16(0x22, 0x807F, 0);
	sdmmc_mask16(0x20, 0x4, 0);
	sdmmc_timeout = 0;

	if(cmd==17 || cmd==18) {
		if((sdmmc_read16(0x100) & 2)==0)sdmmc_mask16(0x22, 0x100, 0);
	}
	if(cmd==24 || cmd==25) {
		if((sdmmc_read16(0x100) & 2)==0)sdmmc_mask16(0x22, 0x200, 0);
	}

	sdmmc_write16(REG_SDCMD, cmd);

	if (cmd != 0) {
		was_stat0 = sdmmc_read16(REG_SDSTATUS0);

		if (cmd != 0x5016) {
			while((sdmmc_read16(REG_SDSTATUS0) & 5) == 0) {
				if(sdmmc_read16(REG_SDSTATUS1) & 0x40) {
					sdmmc_mask16(REG_SDSTATUS1, 0x40, 0);
					sdmmc_timeout = 1;
					break;
				}
			}
		}

		is_stat0 = sdmmc_read16(REG_SDSTATUS0);
		sdmmc_mask16(REG_SDSTATUS0, 5, 0);
	}

	if(cmd!=17 && cmd!=18 && cmd!=24 && cmd!=25)sdmmc_mask16(0x22, 0, 0x807F);

	return 0;
}
示例#4
0
static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args)
{
    bool getSDRESP = (cmd << 15) >> 31;
    u16 flags = (cmd << 15) >> 31;
    const bool readdata = cmd & 0x20000;
    const bool writedata = cmd & 0x40000;

    if (readdata || writedata)
        flags |= TMIO_STAT0_DATAEND;

    ctx->error = 0;
    while (sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY); //mmc working?
    sdmmc_write16(REG_SDIRMASK0,0);
    sdmmc_write16(REG_SDIRMASK1,0);
    sdmmc_write16(REG_SDSTATUS0,0);
    sdmmc_write16(REG_SDSTATUS1,0);
    sdmmc_mask16(REG_SDDATACTL32,0x1800,0);

    sdmmc_write16(REG_SDCMDARG0,args &0xFFFF);
    sdmmc_write16(REG_SDCMDARG1,args >> 16);
    sdmmc_write16(REG_SDCMD,cmd &0xFFFF);

    u32 size = ctx->size;
    vu8 *dataPtr = ctx->data;

    bool useBuf = ( NULL != dataPtr );

    u16 status0 = 0;
    while(true) {
        u16 status1 = sdmmc_read16(REG_SDSTATUS1);
        if (status1 & TMIO_STAT1_RXRDY) {
            if (readdata && useBuf) {
                sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0);
                //sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_RXRDY);
                if (size > 0x1FF) {
                    for(int i = 0; i<0x200; i+=2) {
                        u16 data = sdmmc_read16(REG_SDFIFO);
                        *dataPtr++ = data & 0xFF;
                        *dataPtr++ = data >> 8;
                    }
                    size -= 0x200;
                }
            }
        }

        if (status1 & TMIO_STAT1_TXRQ) {
            if (writedata && useBuf) {
                sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0);
                //sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ);
                if (size > 0x1FF) {
                    for (int i = 0; i<0x200; i+=2) {
                        u16 data = *dataPtr++;
                        data |= *dataPtr++ << 8;
                        sdmmc_write16(REG_SDFIFO, data);
                    }
                    size -= 0x200;
                }
            }
        }
        if (status1 & TMIO_MASK_GW) {
            ctx->error |= 4;
            break;
        }

        if (!(status1 & TMIO_STAT1_CMD_BUSY)) {
            status0 = sdmmc_read16(REG_SDSTATUS0);
            if (sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND)
                ctx->error |= 0x1;
            if (status0 & TMIO_STAT0_DATAEND)
                ctx->error |= 0x2;

            if ((status0 & flags) == flags)
                break;
        }
    }
示例#5
0
static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set) {
    u16 val = sdmmc_read16(reg);
    val &= ~clear;
    val |= set;
    sdmmc_write16(reg, val);
}
示例#6
0
            ctx->error |= 4;
            break;
        }

        if (!(status1 & TMIO_STAT1_CMD_BUSY)) {
            status0 = sdmmc_read16(REG_SDSTATUS0);
            if (sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND)
                ctx->error |= 0x1;
            if (status0 & TMIO_STAT0_DATAEND)
                ctx->error |= 0x2;

            if ((status0 & flags) == flags)
                break;
        }
    }
    ctx->stat0 = sdmmc_read16(REG_SDSTATUS0);
    ctx->stat1 = sdmmc_read16(REG_SDSTATUS1);
    sdmmc_write16(REG_SDSTATUS0,0);
    sdmmc_write16(REG_SDSTATUS1,0);

    if (getSDRESP != 0) {
        ctx->ret[0] = (u32)sdmmc_read16(REG_SDRESP0) | (u32)(sdmmc_read16(REG_SDRESP1) << 16);
        ctx->ret[1] = (u32)sdmmc_read16(REG_SDRESP2) | (u32)(sdmmc_read16(REG_SDRESP3) << 16);
        ctx->ret[2] = (u32)sdmmc_read16(REG_SDRESP4) | (u32)(sdmmc_read16(REG_SDRESP5) << 16);
        ctx->ret[3] = (u32)sdmmc_read16(REG_SDRESP6) | (u32)(sdmmc_read16(REG_SDRESP7) << 16);
    }
}

u32 __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out)
{
    if (handleSD.isSDHC == 0)
示例#7
0
文件: sdmmc.c 项目: master861/uncart2
void NO_INLINE sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args)
{
	bool getSDRESP = (cmd << 15) >> 31;
	uint16_t flags = (cmd << 15) >> 31;
	const bool readdata = cmd & 0x20000;
	const bool writedata = cmd & 0x40000;
	
	if(readdata || writedata)
	{
		flags |= TMIO_STAT0_DATAEND;
	}
	
	ctx->error = 0;
	while(sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY); //mmc working?
	sdmmc_write16(REG_SDIRMASK0,0);
	sdmmc_write16(REG_SDIRMASK1,0);
	sdmmc_write16(REG_SDSTATUS0,0);
	sdmmc_write16(REG_SDSTATUS1,0);
#ifdef DATA32_SUPPORT
	if(readdata)sdmmc_mask16(REG_DATACTL32, 0x1000, 0x800);
	if(writedata)sdmmc_mask16(REG_DATACTL32, 0x800, 0x1000);
#else
	sdmmc_mask16(REG_DATACTL32,0x1800,0);
#endif
	sdmmc_write16(REG_SDCMDARG0,args &0xFFFF);
	sdmmc_write16(REG_SDCMDARG1,args >> 16);
	sdmmc_write16(REG_SDCMD,cmd &0xFFFF);
	
	uint32_t size = ctx->size;
	uint16_t *dataPtr = (uint16_t*)ctx->data;
#ifdef DATA32_SUPPORT
	uint32_t *dataPtr32 = (uint32_t*)ctx->data;
#endif
	
	bool useBuf = ( NULL != dataPtr );
#ifdef DATA32_SUPPORT
	bool useBuf32 = (useBuf && (0 == (3 & ((uint32_t)dataPtr))));
#endif
	
	uint16_t status0 = 0;
	while(1)
	{
		uint16_t status1 = sdmmc_read16(REG_SDSTATUS1);
		if(status1 & TMIO_STAT1_RXRDY)
		{
			if(readdata)
			{
				if(useBuf)
				{
					sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0);
					//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_RXRDY);
					if(size > 0x1FF)
					{
						#ifdef DATA32_SUPPORT
						if(useBuf32)
						{
							for(int i = 0; i<0x200; i+=4)
							{
								*dataPtr32++ = sdmmc_read32(REG_SDFIFO32);
							}
						}
						else 
						{
						#endif
							for(int i = 0; i<0x200; i+=2)
							{
								*dataPtr++ = sdmmc_read16(REG_SDFIFO);
							}
						#ifdef DATA32_SUPPORT
						}
						#endif
						size -= 0x200;
					}
				}
			}
		}
		if(status1 & TMIO_STAT1_TXRQ)
		{
			if(writedata)
			{
				if(useBuf)
				{
					sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0);
					//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ);
					if(size > 0x1FF)
					{
						#ifdef DATA32_SUPPORT
						for(int i = 0; i<0x200; i+=4)
						{
							sdmmc_write32(REG_SDFIFO32,*dataPtr32++);
						}
						#else
						for(int i = 0; i<0x200; i+=2)
						{
							sdmmc_write16(REG_SDFIFO,*dataPtr++);
						}
						#endif
						size -= 0x200;
					}
				}
			}
		}
		if(status1 & TMIO_MASK_GW)
		{
			ctx->error |= 4;
			break;
		}
		
		if(!(status1 & TMIO_STAT1_CMD_BUSY))
		{
			status0 = sdmmc_read16(REG_SDSTATUS0);
			if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND)
			{
				ctx->error |= 0x1;
			}
			if(status0 & TMIO_STAT0_DATAEND)
			{
				ctx->error |= 0x2;
			}
			
			if((status0 & flags) == flags)
				break;
		}
	}
	ctx->stat0 = sdmmc_read16(REG_SDSTATUS0);
	ctx->stat1 = sdmmc_read16(REG_SDSTATUS1);
	sdmmc_write16(REG_SDSTATUS0,0);
	sdmmc_write16(REG_SDSTATUS1,0);
	
	if(getSDRESP != 0)
	{
		ctx->ret[0] = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16);
		ctx->ret[1] = sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16);
		ctx->ret[2] = sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16);
		ctx->ret[3] = sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16);
	}
}
示例#8
0
文件: sdmmc.c 项目: bowies/Team3
//---------------------------------------------------------------------------------
int sdmmc_sdcard_init() {
//---------------------------------------------------------------------------------
	u16 sdaddr;
	u32 resp0;
	u32 resp1;
	u32 resp2;
	u32 resp3;
	u32 resp4;
	u32 resp5;
	u32 resp6;
	u32 resp7;

	u32 ocr, ccs, hcs, response;

	sdmmc_cardready = 0;

	int oldIME = enterCriticalSection();

	sdmmc_write16(REG_SDCLKCTL, 0x20);
	sdmmc_write16(REG_SDOPT, 0x40EA); // XXX: document me!
	sdmmc_write16(0x02, 0x400);

	sdmmc_mask16(REG_SDCLKCTL, 0, 0x100);
	sdmmc_write16(REG_SDCLKCTL, sdmmc_read16(REG_SDCLKCTL));
	sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
	sdmmc_mask16(REG_SDCLKCTL, 0, 0x200);
	sdmmc_mask16(REG_SDCLKCTL, 0, 0x100);

	// CMD0
	sdmmc_send_command(0x0000, 0x0000, 0x0000);
	sdmmc_send_command(0x0408, 0x01aa, 0x0000);
	sdmmc_gotcmd8reply = 1;

	if(sdmmc_timeout)
		sdmmc_gotcmd8reply = 0;

	if(sdmmc_gotcmd8reply)
		hcs = (1<<30);
	else
		hcs = 0;

	ocr = 0x00ff8000;

	while (1) {
		sdmmc_send_acmd41(ocr | hcs, &response);

		if (response & 0x80000000)
			break;
	}

	ccs = response & (1<<30);

	if(ccs && hcs) 
		sdmmc_sdhc = 1;
	else
		sdmmc_sdhc = 0;

	// CMD2 - get CID
	sdmmc_send_command(2, 0, 0);
	
	resp0 = sdmmc_read16(REG_SDRESP0);
	resp1 = sdmmc_read16(REG_SDRESP1);
	resp2 = sdmmc_read16(REG_SDRESP2);
	resp3 = sdmmc_read16(REG_SDRESP3);
	resp4 = sdmmc_read16(REG_SDRESP4);
	resp5 = sdmmc_read16(REG_SDRESP5);
	resp6 = sdmmc_read16(REG_SDRESP6);
	resp7 = sdmmc_read16(REG_SDRESP7);

	sdmmc_cid[0] = resp0 | (u32)(resp1<<16);
	sdmmc_cid[1] = resp2 | (u32)(resp3<<16);
	sdmmc_cid[2] = resp4 | (u32)(resp5<<16);
	sdmmc_cid[3] = resp6 | (u32)(resp7<<16);

	// CMD3
	sdmmc_send_command(3, 0, 0);
	
	resp0 = sdmmc_read16(REG_SDRESP0);
	resp1 = sdmmc_read16(REG_SDRESP1);
	
	sdaddr = resp1;
	
	// CMD9 - get CSD
	sdmmc_send_command(9, 0, sdaddr);
	
	resp0 = sdmmc_read16(REG_SDRESP0);
	resp1 = sdmmc_read16(REG_SDRESP1);
	resp2 = sdmmc_read16(REG_SDRESP2);
	resp3 = sdmmc_read16(REG_SDRESP3);
	resp4 = sdmmc_read16(REG_SDRESP4);
	resp5 = sdmmc_read16(REG_SDRESP5);
	resp6 = sdmmc_read16(REG_SDRESP6);
	resp7 = sdmmc_read16(REG_SDRESP7);
	
	sdmmc_write16(REG_SDCLKCTL, 0x100);	
	
	// CMD7
	sdmmc_send_command(7, 0, sdaddr);
	
	resp0 = sdmmc_read16(REG_SDRESP0);
	resp1 = sdmmc_read16(REG_SDRESP1);
	
	// CMD55
	sdmmc_send_command(55, 0, sdaddr);
	
	// ACMD6
	sdmmc_send_command(6, 2, 0);
	
	resp0 = sdmmc_read16(REG_SDRESP0);
	resp1 = sdmmc_read16(REG_SDRESP1);

	sdmmc_send_command(13, 0, sdaddr);
	
	resp0 = sdmmc_read16(REG_SDRESP0);
	resp1 = sdmmc_read16(REG_SDRESP1);

	sdmmc_send_command(16, 0x200, 0x0);
	
	resp0 = sdmmc_read16(REG_SDRESP0);
	resp1 = sdmmc_read16(REG_SDRESP1);	
	
	sdmmc_write16(REG_SDCLKCTL, sdmmc_read16(REG_SDCLKCTL));
	sdmmc_write16(REG_SDBLKLEN, 0x200);

	sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);

	sdmmc_cardready = 1;
	leaveCriticalSection(oldIME);

	return 0;
}
示例#9
0
文件: sdmmc.c 项目: bowies/Team3
//---------------------------------------------------------------------------------
static void sdmmc_irqhandler() {
//---------------------------------------------------------------------------------
	int i;
	//u32 irqs;
	u32 status;
	u32 errstat;
	if(sdmmcirq_transfer==0)return;

	//irqs = sdmmc_read16(0x100);
	status = sdmmc_read16(REG_SDSTATUS0);

	errstat = sdmmc_read16(REG_SDSTATUS1) & 0x807f;//STATUS errors mask
	if(errstat) {
		sdmmc_mask16(REG_SDSTATUS1, errstat, 0);
		//sdmmc_mask16(0x22, 0x0, errstat);

		sdmmcirq_transfer = 0;
		sdmmcirq_bufpos = 0;
		sdmmcirq_abort = 1;
		sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
		fifoSendValue32(FIFO_SDMMC, 1);
		return;
	}

	if(sdmmcirq_blocks==0) {
		if(status & 0x4) {
			sdmmcirq_transfer = 0;
			sdmmcirq_bufpos = 0;

			sdmmc_mask16(REG_SDSTATUS0, 0x4, 0);

			sdmmc_mask16(0x22, 0, 0x807F | 0x4000);
			sdmmc_mask16(0x20, 0, 0x4);
			if((sdmmc_read16(0x22) & 0x100)==0)sdmmc_mask16(0x22, 0, 0x100);
			if((sdmmc_read16(0x22) & 0x200)==0)sdmmc_mask16(0x22, 0, 0x200);
		}
		sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
		fifoSendValue32(FIFO_SDMMC, 0);
		return;
	}

	if(sdmmcirq_transfer==1) {
		sdmmc_mask16(REG_SDSTATUS1, 0x100, 0);
		//if((sdmmc_read16(0x22) & 0x100))sdmmc_mask16(0x22, 0x100, 0x0);
	}
	if(sdmmcirq_transfer==2) {
		sdmmc_mask16(REG_SDSTATUS1, 0x200, 0);
		//if((sdmmc_read16(0x22) & 0x200))sdmmc_mask16(0x22, 0x200, 0x0);
		if(sdmmcirq_blocks==1)
		{
			sdmmc_mask16(0x100, 0x1800, 0x0);
			sdmmc_mask16(0x22, 0x0, 0x100);
			sdmmc_mask16(0x22, 0x0, 0x200);
		}
	}

	for(i=0; i<0x100; i++) {
		if(sdmmcirq_transfer==1)sdmmcirq_buffer[sdmmcirq_bufpos] = sdmmc_read16(REG_SDFIFO);
		if(sdmmcirq_transfer==2)sdmmc_write16(REG_SDFIFO, sdmmcirq_buffer[sdmmcirq_bufpos]);
		sdmmcirq_bufpos++;
	}

	sdmmcirq_blocks--;
}