Пример #1
0
//---------------------------------------------------------------------------------
void sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, void *in) {
//---------------------------------------------------------------------------------
	u16 *in16 = (u16*)in;

	if(numsectors==1) {
		return sdmmc_sdcard_writesector(sector_no, in);
	}

	if(!sdmmc_sdhc)
		sector_no *= 512;

	sdmmc_mask16(0x100, 2, 0);
	sdmmc_write16(0xd8, 0);

	sdmmc_write16(REG_SDSTOP, 0x100);
	sdmmc_write16(REG_SDBLKCOUNT, numsectors);
	sdmmc_mask16(REG_SDCLKCTL, 0, 0x100);
	sdmmc_write16(REG_SDBLKLEN, 0x200);	
	
	set_irqhandler(2, in16, numsectors);

	// CMD25 - write multiple blocks
	sdmmc_send_command(25, sector_no & 0xffff, (sector_no >> 16));
	if(sdmmc_timeout) {
		sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
		fifoSendValue32(FIFO_SDMMC, 1);
	}
}
Пример #2
0
//---------------------------------------------------------------------------------
void sdmmc_controller_init() {
//---------------------------------------------------------------------------------
	int oldIME = enterCriticalSection();
	// Reset
	sdmmc_write16(0x100, 0x0402);
	sdmmc_write16(0x100, 0x0000);
	sdmmc_write16(0x104, 0x0000);
	sdmmc_write16(0x108, 0x0001);

	// InitIP
	sdmmc_mask16(REG_SDRESET, 0x0001, 0x0000);
	sdmmc_mask16(REG_SDRESET, 0x0000, 0x0001);
	sdmmc_mask16(REG_SDSTOP, 0x0001, 0x0000);

	// Reset
	sdmmc_mask16(REG_SDOPT, 0x0005, 0x0000);

	// EnableInfo
	sdmmc_mask16(REG_SDSTATUS0, 0x0018, 0x0000);
	sdmmc_mask16(0x20, 0x0018, 0x0000); // ??
	sdmmc_mask16(0x20, 0x0000, 0x0018);

	sdmmc_init_irq();
	leaveCriticalSection(oldIME);
}
Пример #3
0
//---------------------------------------------------------------------------------
void sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out) {
//---------------------------------------------------------------------------------
	u16 *out16 = (u16*)out;
//	int ret;

	if(numsectors==1) {
		return sdmmc_sdcard_readsector(sector_no, out);
	}

	if(!sdmmc_sdhc)
		sector_no *= 512;

	sdmmc_mask16(0x100, 2, 0);
	sdmmc_write16(0xd8, 0);

	sdmmc_write16(REG_SDSTOP, 0x100);
	sdmmc_write16(REG_SDBLKCOUNT, numsectors);
	sdmmc_mask16(REG_SDCLKCTL, 0, 0x100);
	sdmmc_write16(REG_SDBLKLEN, 0x200);	
	
	set_irqhandler(1, out16, numsectors);

	// CMD18 - read multiple blocks
	sdmmc_send_command(18, sector_no & 0xffff, (sector_no >> 16));
	if(sdmmc_timeout) {
		sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
		fifoSendValue32(FIFO_SDMMC, 1);
	}
}
Пример #4
0
//---------------------------------------------------------------------------------
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;
}
Пример #5
0
int NO_INLINE sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in)
{
	if(handelSD.isSDHC == 0) sector_no <<= 9;
	inittarget(&handelSD);
	sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
	sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
#endif
	sdmmc_write16(REG_SDBLKCOUNT,numsectors);
	handelSD.data = in;
	handelSD.size = numsectors << 9;
	sdmmc_send_command(&handelSD,0x52C19,sector_no);
	return geterror(&handelSD);
}
Пример #6
0
int NO_INLINE sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out)
{
	if(handelNAND.isSDHC == 0) sector_no <<= 9;
	inittarget(&handelNAND);
	sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
	sdmmc_write32(REG_SDBLKCOUNT32,numsectors);
#else
	sdmmc_write16(REG_SDBLKCOUNT,numsectors);
#endif
	handelNAND.data = out;
	handelNAND.size = numsectors << 9;
	sdmmc_send_command(&handelNAND,0x33C12,sector_no);
	inittarget(&handelSD);
	return geterror(&handelNAND);
}
Пример #7
0
//---------------------------------------------------------------------------------
void sdmmc_sdcard_readsector(u32 sector_no, void *out) {
//---------------------------------------------------------------------------------
	u16 *out16 = (u16*)out;
//	int ret;

	if(!sdmmc_sdhc)
		sector_no *= 512;

	sdmmc_mask16(0x100, 2, 0);
	sdmmc_write16(0xd8, 0);

	sdmmc_mask16(REG_SDCLKCTL, 0, 0x100);
	sdmmc_write16(REG_SDBLKLEN, 0x200);
	
	set_irqhandler(1, out16, 1);

	// CMD17 - read single block
	sdmmc_send_command(17, sector_no & 0xffff, (sector_no >> 16));
	if(sdmmc_timeout) {
		sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
		fifoSendValue32(FIFO_SDMMC, 1);
	}
}
Пример #8
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;
        }
    }
Пример #9
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);
}
Пример #10
0
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);
	}
}
Пример #11
0
//---------------------------------------------------------------------------------
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;
}
Пример #12
0
//---------------------------------------------------------------------------------
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--;
}