diff --git a/source/nand/delay.h b/source/nand/delay.h new file mode 100644 index 0000000..e14ac32 --- /dev/null +++ b/source/nand/delay.h @@ -0,0 +1,5 @@ +#pragma once + +#include "common.h" + +void waitcycles(u32 us); diff --git a/source/nand/delay.s b/source/nand/delay.s index 3a2cfdf..0bf19c2 100644 --- a/source/nand/delay.s +++ b/source/nand/delay.s @@ -1,15 +1,16 @@ +.text .arm -.global waitcycles -.type waitcycles STT_FUNC +.align 4 -@waitcycles ( u32 us ) +.global waitcycles +.type waitcycles, %function waitcycles: - PUSH {R0-R2,LR} - STR R0, [SP,#4] - waitcycles_loop: - LDR R3, [SP,#4] - SUBS R2, R3, #1 - STR R2, [SP,#4] - CMP R3, #0 - BNE waitcycles_loop - POP {R0-R2,PC} + push {r0-r2, lr} + str r0, [sp, #4] + waitcycles_loop: + ldr r3, [sp, #4] + subs r2, r3, #1 + str r2, [sp, #4] + cmp r3, #0 + bne waitcycles_loop + pop {r0-r2, pc} diff --git a/source/nand/sdmmc.c b/source/nand/sdmmc.c index 6dab53a..e4c58f4 100644 --- a/source/nand/sdmmc.c +++ b/source/nand/sdmmc.c @@ -1,6 +1,6 @@ /* * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright (c) 2014-2015, Normmatt @@ -22,543 +22,459 @@ * along with this program. If not, see http://www.gnu.org/licenses/. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "sdmmc.h" -//#include "DrawCharacter.h" +#include "delay.h" -#define DATA32_SUPPORT +static struct mmcdevice handleNAND; +static struct mmcdevice handleSD; -#define TRUE 1 -#define FALSE 0 +static inline u16 sdmmc_read16(u16 reg) +{ + return *(vu16 *)(SDMMC_BASE + reg); +} -#define NO_INLINE __attribute__ ((noinline)) +static inline void sdmmc_write16(u16 reg, u16 val) +{ + *(vu16 *)(SDMMC_BASE + reg) = val; +} -#ifdef __cplusplus -extern "C" { -#endif - void waitcycles(uint32_t val); -#ifdef __cplusplus -}; -#endif +static inline u32 sdmmc_read32(u16 reg) +{ + return *(vu32 *)(SDMMC_BASE + reg); +} -struct mmcdevice handelNAND; -struct mmcdevice handelSD; +static inline void sdmmc_write32(u16 reg, u32 val) +{ + *(vu32 *)(SDMMC_BASE + reg) = val; +} + +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); +} + +static inline void setckl(u32 data) +{ + sdmmc_mask16(REG_SDCLKCTL, 0x100, 0); + sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF); + sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100); +} mmcdevice *getMMCDevice(int drive) { - if(drive==0) return &handelNAND; - return &handelSD; + if(drive == 0) return &handleNAND; + return &handleSD; } static int geterror(struct mmcdevice *ctx) { - return (int)((ctx->error << 29) >> 31); + return (int)((ctx->error << 29) >> 31); } - static void inittarget(struct mmcdevice *ctx) { - sdmmc_mask16(REG_SDPORTSEL,0x3,(uint16_t)ctx->devicenumber); - setckl(ctx->clk); - if(ctx->SDOPT == 0) - { - sdmmc_mask16(REG_SDOPT,0,0x8000); - } - else - { - sdmmc_mask16(REG_SDOPT,0x8000,0); - } - + sdmmc_mask16(REG_SDPORTSEL, 0x3, (u16)ctx->devicenumber); + setckl(ctx->clk); + if(ctx->SDOPT == 0) sdmmc_mask16(REG_SDOPT, 0, 0x8000); + else sdmmc_mask16(REG_SDOPT, 0x8000, 0); } -static void NO_INLINE sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args) +static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args) { - uint32_t getSDRESP = (cmd << 15) >> 31; - uint16_t flags = (cmd << 15) >> 31; - const int readdata = cmd & 0x20000; - const int writedata = cmd & 0x40000; + u32 getSDRESP = (cmd << 15) >> 31; + u16 flags = (cmd << 15) >> 31; + const int readdata = cmd & 0x20000; + const int writedata = cmd & 0x40000; - if(readdata || writedata) - { - flags |= TMIO_STAT0_DATAEND; - } + 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_DATACTL32,0x1800,0); - sdmmc_write16(REG_SDCMDARG0,args &0xFFFF); - sdmmc_write16(REG_SDCMDARG1,args >> 16); - sdmmc_write16(REG_SDCMD,cmd &0xFFFF); + 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_DATACTL32, 0x1800, 0); + sdmmc_write16(REG_SDCMDARG0, args & 0xFFFF); + sdmmc_write16(REG_SDCMDARG1, args >> 16); + sdmmc_write16(REG_SDCMD, cmd & 0xFFFF); - uint32_t size = ctx->size; - uint8_t *rDataPtr = ctx->rData; - const uint8_t *tDataPtr = ctx->tData; + u32 size = ctx->size; + u8 *rDataPtr = ctx->rData; + const u8 *tDataPtr = ctx->tData; - int rUseBuf = ( NULL != rDataPtr ); - int tUseBuf = ( NULL != tDataPtr ); + bool rUseBuf = rDataPtr != NULL; + bool tUseBuf = tDataPtr != NULL; - uint16_t status0 = 0; - while(1) - { - volatile uint16_t status1 = sdmmc_read16(REG_SDSTATUS1); -#ifdef DATA32_SUPPORT - volatile uint16_t ctl32 = sdmmc_read16(REG_DATACTL32); - if((ctl32 & 0x100)) -#else - if((status1 & TMIO_STAT1_RXRDY)) -#endif - { - if(readdata) - { - if(rUseBuf) - { - sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0); - if(size > 0x1FF) - { - #ifdef DATA32_SUPPORT - //Gabriel Marcano: This implementation doesn't assume alignment. - //I've removed the alignment check doen with former rUseBuf32 as a result - for(int i = 0; i<0x200; i+=4) - { - uint32_t data = sdmmc_read32(REG_SDFIFO32); - *rDataPtr++ = data; - *rDataPtr++ = data >> 8; - *rDataPtr++ = data >> 16; - *rDataPtr++ = data >> 24; - } - #else - for(int i = 0; i<0x200; i+=2) - { - uint16_t data = sdmmc_read16(REG_SDFIFO); - *rDataPtr++ = data; - *rDataPtr++ = data >> 8; - } - #endif - size -= 0x200; - } - } + u16 status0 = 0; + while(true) + { + vu16 status1 = sdmmc_read16(REG_SDSTATUS1); + vu16 ctl32 = sdmmc_read16(REG_DATACTL32); + if((ctl32 & 0x100)) + { + if(readdata) + { + if(rUseBuf) + { + sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0); + if(size > 0x1FF) + { + //Gabriel Marcano: This implementation doesn't assume alignment. + //I've removed the alignment check doen with former rUseBuf32 as a result + for(int i = 0; i < 0x200; i += 4) + { + u32 data = sdmmc_read32(REG_SDFIFO32); + *rDataPtr++ = data; + *rDataPtr++ = data >> 8; + *rDataPtr++ = data >> 16; + *rDataPtr++ = data >> 24; + } + size -= 0x200; + } + } - sdmmc_mask16(REG_DATACTL32, 0x800, 0); - } - } -#ifdef DATA32_SUPPORT - if(!(ctl32 & 0x200)) -#else - if((status1 & TMIO_STAT1_TXRQ)) -#endif - { - if(writedata) - { - if(tUseBuf) - { - sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0); - if(size > 0x1FF) - { - #ifdef DATA32_SUPPORT - for(int i = 0; i<0x200; i+=4) - { - uint32_t data = *tDataPtr++; - data |= (uint32_t)*tDataPtr++ << 8; - data |= (uint32_t)*tDataPtr++ << 16; - data |= (uint32_t)*tDataPtr++ << 24; - sdmmc_write32(REG_SDFIFO32, data); - } - #else - for(int i = 0; i<0x200; i+=2) - { - uint16_t data = *tDataPtr++; - data |= (uint8_t)(*tDataPtr++ << 8); - sdmmc_write16(REG_SDFIFO, data); - } - #endif - size -= 0x200; - } - } + sdmmc_mask16(REG_DATACTL32, 0x800, 0); + } + } + if(!(ctl32 & 0x200)) + { + if(writedata) + { + if(tUseBuf) + { + sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0); + if(size > 0x1FF) + { + for(int i = 0; i < 0x200; i += 4) + { + u32 data = *tDataPtr++; + data |= (u32)*tDataPtr++ << 8; + data |= (u32)*tDataPtr++ << 16; + data |= (u32)*tDataPtr++ << 24; + sdmmc_write32(REG_SDFIFO32, data); + } + size -= 0x200; + } + } - sdmmc_mask16(REG_DATACTL32, 0x1000, 0); - } - } - if(status1 & TMIO_MASK_GW) - { - ctx->error |= 4; - break; - } + sdmmc_mask16(REG_DATACTL32, 0x1000, 0); + } + } + 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(!(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((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] = (uint32_t)(sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16)); - ctx->ret[1] = (uint32_t)(sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16)); - ctx->ret[2] = (uint32_t)(sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16)); - ctx->ret[3] = (uint32_t)(sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16)); - } + if(getSDRESP != 0) + { + ctx->ret[0] = (u32)(sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16)); + ctx->ret[1] = (u32)(sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16)); + ctx->ret[2] = (u32)(sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16)); + ctx->ret[3] = (u32)(sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16)); + } } -int NO_INLINE sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, const uint8_t *in) +int __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in) { - if(handelSD.isSDHC == 0) sector_no <<= 9; - inittarget(&handelSD); - sdmmc_write16(REG_SDSTOP,0x100); -#ifdef DATA32_SUPPORT - sdmmc_write16(REG_SDBLKCOUNT32,numsectors); - sdmmc_write16(REG_SDBLKLEN32,0x200); -#endif - sdmmc_write16(REG_SDBLKCOUNT,numsectors); - handelSD.tData = in; - handelSD.size = numsectors << 9; - sdmmc_send_command(&handelSD,0x52C19,sector_no); - return geterror(&handelSD); + if(handleSD.isSDHC == 0) sector_no <<= 9; + inittarget(&handleSD); + sdmmc_write16(REG_SDSTOP, 0x100); + sdmmc_write16(REG_SDBLKCOUNT32, numsectors); + sdmmc_write16(REG_SDBLKLEN32, 0x200); + sdmmc_write16(REG_SDBLKCOUNT, numsectors); + handleSD.tData = in; + handleSD.size = numsectors << 9; + sdmmc_send_command(&handleSD, 0x52C19, sector_no); + return geterror(&handleSD); } -int NO_INLINE sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out) +int __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out) { - if(handelSD.isSDHC == 0) sector_no <<= 9; - inittarget(&handelSD); - sdmmc_write16(REG_SDSTOP,0x100); -#ifdef DATA32_SUPPORT - sdmmc_write16(REG_SDBLKCOUNT32,numsectors); - sdmmc_write16(REG_SDBLKLEN32,0x200); -#endif - sdmmc_write16(REG_SDBLKCOUNT,numsectors); - handelSD.rData = out; - handelSD.size = numsectors << 9; - sdmmc_send_command(&handelSD,0x33C12,sector_no); - return geterror(&handelSD); + if(handleSD.isSDHC == 0) sector_no <<= 9; + inittarget(&handleSD); + sdmmc_write16(REG_SDSTOP, 0x100); + sdmmc_write16(REG_SDBLKCOUNT32, numsectors); + sdmmc_write16(REG_SDBLKLEN32, 0x200); + sdmmc_write16(REG_SDBLKCOUNT, numsectors); + handleSD.rData = out; + handleSD.size = numsectors << 9; + sdmmc_send_command(&handleSD, 0x33C12, sector_no); + return geterror(&handleSD); } - - -int NO_INLINE sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out) +int __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out) { - if(handelNAND.isSDHC == 0) sector_no <<= 9; - inittarget(&handelNAND); - sdmmc_write16(REG_SDSTOP,0x100); -#ifdef DATA32_SUPPORT - sdmmc_write16(REG_SDBLKCOUNT32,numsectors); - sdmmc_write16(REG_SDBLKLEN32,0x200); -#endif - sdmmc_write16(REG_SDBLKCOUNT,numsectors); - handelNAND.rData = out; - handelNAND.size = numsectors << 9; - sdmmc_send_command(&handelNAND,0x33C12,sector_no); - return geterror(&handelNAND); + if(handleNAND.isSDHC == 0) sector_no <<= 9; + inittarget(&handleNAND); + sdmmc_write16(REG_SDSTOP, 0x100); + sdmmc_write16(REG_SDBLKCOUNT32, numsectors); + sdmmc_write16(REG_SDBLKLEN32, 0x200); + sdmmc_write16(REG_SDBLKCOUNT, numsectors); + handleNAND.rData = out; + handleNAND.size = numsectors << 9; + sdmmc_send_command(&handleNAND, 0x33C12, sector_no); + inittarget(&handleSD); + return geterror(&handleNAND); } -int NO_INLINE sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, const uint8_t *in) //experimental +int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in) //experimental { - if(handelNAND.isSDHC == 0) sector_no <<= 9; - inittarget(&handelNAND); - sdmmc_write16(REG_SDSTOP,0x100); -#ifdef DATA32_SUPPORT - sdmmc_write16(REG_SDBLKCOUNT32,numsectors); - sdmmc_write16(REG_SDBLKLEN32,0x200); -#endif - sdmmc_write16(REG_SDBLKCOUNT,numsectors); - handelNAND.tData = in; - handelNAND.size = numsectors << 9; - sdmmc_send_command(&handelNAND,0x52C19,sector_no); - return geterror(&handelNAND); + if(handleNAND.isSDHC == 0) sector_no <<= 9; + inittarget(&handleNAND); + sdmmc_write16(REG_SDSTOP, 0x100); + sdmmc_write16(REG_SDBLKCOUNT32, numsectors); + sdmmc_write16(REG_SDBLKLEN32, 0x200); + sdmmc_write16(REG_SDBLKCOUNT, numsectors); + handleNAND.tData = in; + handleNAND.size = numsectors << 9; + sdmmc_send_command(&handleNAND, 0x52C19, sector_no); + inittarget(&handleSD); + return geterror(&handleNAND); } -static uint32_t calcSDSize(uint8_t* csd, int type) +static u32 calcSDSize(u8 *csd, int type) { - uint32_t result = 0; - if(type == -1) type = csd[14] >> 6; - switch(type) - { - case 0: - { - uint32_t block_len=csd[9]&0xf; - block_len=1u<>7)|((csd[5]&3)<<1)); - mult=1u<<(mult+2); - result=csd[8]&3; - result=(result<<8)|csd[7]; - result=(result<<2)|(csd[6]>>6); - result=(result+1)*mult*block_len/512; - } - break; - case 1: - result=csd[7]&0x3f; - result=(result<<8)|csd[6]; - result=(result<<8)|csd[5]; - result=(result+1)*1024; - break; - default: - break; //Do nothing otherwise FIXME perhaps return some error? - } - return result; + u32 result = 0; + if(type == -1) type = csd[14] >> 6; + switch(type) + { + case 0: + { + u32 block_len = csd[9] & 0xF; + block_len = 1u << block_len; + u32 mult = (u32)((csd[4] >> 7) | ((csd[5] & 3) << 1)); + mult = 1u << (mult + 2); + result = csd[8] & 3; + result = (result << 8) | csd[7]; + result = (result << 2) | (csd[6] >> 6); + result = (result + 1) * mult * block_len / 512; + break; + } + case 1: + result = csd[7] & 0x3F; + result = (result << 8) | csd[6]; + result = (result << 8) | csd[5]; + result = (result + 1) * 1024; + break; + default: + break; //Do nothing otherwise FIXME perhaps return some error? + } + return result; } -void InitSD() +static void InitSD() { - //sdmmc_mask16(0x100,0x800,0); - //sdmmc_mask16(0x100,0x1000,0); - //sdmmc_mask16(0x100,0x0,0x402); - //sdmmc_mask16(0xD8,0x22,0x2); - //sdmmc_mask16(0x100,0x2,0); - //sdmmc_mask16(0xD8,0x22,0); - //sdmmc_write16(0x104,0); - //sdmmc_write16(0x108,1); - //sdmmc_mask16(REG_SDRESET,1,0); //not in new Version -- nintendo's code does this - //sdmmc_mask16(REG_SDRESET,0,1); //not in new Version -- nintendo's code does this - //sdmmc_mask16(0x20,0,0x31D); - //sdmmc_mask16(0x22,0,0x837F); - //sdmmc_mask16(0xFC,0,0xDB); - //sdmmc_mask16(0xFE,0,0xDB); - ////sdmmc_write16(REG_SDCLKCTL,0x20); - ////sdmmc_write16(REG_SDOPT,0x40EE); - ////sdmmc_mask16(0x02,0x3,0); - //sdmmc_write16(REG_SDCLKCTL,0x40); - //sdmmc_write16(REG_SDOPT,0x40EB); - //sdmmc_mask16(0x02,0x3,0); - //sdmmc_write16(REG_SDBLKLEN,0x200); - //sdmmc_write16(REG_SDSTOP,0); - - *(volatile uint16_t*)0x10006100 &= 0xF7FFu; //SDDATACTL32 - *(volatile uint16_t*)0x10006100 &= 0xEFFFu; //SDDATACTL32 -#ifdef DATA32_SUPPORT - *(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32 -#else - *(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32 -#endif - *(volatile uint16_t*)0x100060D8 = (*(volatile uint16_t*)0x100060D8 & 0xFFDD) | 2; -#ifdef DATA32_SUPPORT - *(volatile uint16_t*)0x10006100 &= 0xFFFFu; //SDDATACTL32 - *(volatile uint16_t*)0x100060D8 &= 0xFFDFu; //SDDATACTL - *(volatile uint16_t*)0x10006104 = 512; //SDBLKLEN32 -#else - *(volatile uint16_t*)0x10006100 &= 0xFFFDu; //SDDATACTL32 - *(volatile uint16_t*)0x100060D8 &= 0xFFDDu; //SDDATACTL - *(volatile uint16_t*)0x10006104 = 0; //SDBLKLEN32 -#endif - *(volatile uint16_t*)0x10006108 = 1; //SDBLKCOUNT32 - *(volatile uint16_t*)0x100060E0 &= 0xFFFEu; //SDRESET - *(volatile uint16_t*)0x100060E0 |= 1u; //SDRESET - *(volatile uint16_t*)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0 - *(volatile uint16_t*)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1 - *(volatile uint16_t*)0x100060FC |= 0xDBu; //SDCTL_RESERVED7 - *(volatile uint16_t*)0x100060FE |= 0xDBu; //SDCTL_RESERVED8 - *(volatile uint16_t*)0x10006002 &= 0xFFFCu; //SDPORTSEL -#ifdef DATA32_SUPPORT - *(volatile uint16_t*)0x10006024 = 0x20; - *(volatile uint16_t*)0x10006028 = 0x40EE; -#else - *(volatile uint16_t*)0x10006024 = 0x40; //Nintendo sets this to 0x20 - *(volatile uint16_t*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE -#endif - *(volatile uint16_t*)0x10006002 &= 0xFFFCu; ////SDPORTSEL - *(volatile uint16_t*)0x10006026 = 512; //SDBLKLEN - *(volatile uint16_t*)0x10006008 = 0; //SDSTOP + *(vu16 *)0x10006100 &= 0xF7FFu; //SDDATACTL32 + *(vu16 *)0x10006100 &= 0xEFFFu; //SDDATACTL32 + *(vu16 *)0x10006100 |= 0x402u; //SDDATACTL32 + *(vu16 *)0x100060D8 = (*(vu16 *)0x100060D8 & 0xFFDD) | 2; + *(vu16 *)0x10006100 &= 0xFFFFu; //SDDATACTL32 + *(vu16 *)0x100060D8 &= 0xFFDFu; //SDDATACTL + *(vu16 *)0x10006104 = 512; //SDBLKLEN32 + *(vu16 *)0x10006108 = 1; //SDBLKCOUNT32 + *(vu16 *)0x100060E0 &= 0xFFFEu; //SDRESET + *(vu16 *)0x100060E0 |= 1u; //SDRESET + *(vu16 *)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0 + *(vu16 *)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1 + *(vu16 *)0x100060FC |= 0xDBu; //SDCTL_RESERVED7 + *(vu16 *)0x100060FE |= 0xDBu; //SDCTL_RESERVED8 + *(vu16 *)0x10006002 &= 0xFFFCu; //SDPORTSEL + *(vu16 *)0x10006024 = 0x20; + *(vu16 *)0x10006028 = 0x40EE; + *(vu16 *)0x10006002 &= 0xFFFCu; ////SDPORTSEL + *(vu16 *)0x10006026 = 512; //SDBLKLEN + *(vu16 *)0x10006008 = 0; //SDSTOP } -int Nand_Init() +static int Nand_Init() { - //NAND - handelNAND.isSDHC = 0; - handelNAND.SDOPT = 0; - handelNAND.res = 0; - handelNAND.initarg = 1; - handelNAND.clk = 0x80; - handelNAND.devicenumber = 1; + //NAND + handleNAND.isSDHC = 0; + handleNAND.SDOPT = 0; + handleNAND.res = 0; + handleNAND.initarg = 1; + handleNAND.clk = 0x80; + handleNAND.devicenumber = 1; - inittarget(&handelNAND); - waitcycles(0xF000); + inittarget(&handleNAND); + waitcycles(0xF000); - sdmmc_send_command(&handelNAND,0,0); + sdmmc_send_command(&handleNAND, 0, 0); - do - { - do - { - sdmmc_send_command(&handelNAND,0x10701,0x100000); - } while ( !(handelNAND.error & 1) ); - } - while((handelNAND.ret[0] & 0x80000000) == 0); + do + { + do + { + sdmmc_send_command(&handleNAND, 0x10701, 0x100000); + } + while(!(handleNAND.error & 1)); + } + while((handleNAND.ret[0] & 0x80000000) == 0); - sdmmc_send_command(&handelNAND,0x10602,0x0); - if((handelNAND.error & 0x4))return -1; + sdmmc_send_command(&handleNAND, 0x10602, 0x0); + if((handleNAND.error & 0x4)) return -1; - sdmmc_send_command(&handelNAND,0x10403,handelNAND.initarg << 0x10); - if((handelNAND.error & 0x4))return -1; + sdmmc_send_command(&handleNAND, 0x10403, handleNAND.initarg << 0x10); + if((handleNAND.error & 0x4)) return -1; - sdmmc_send_command(&handelNAND,0x10609,handelNAND.initarg << 0x10); - if((handelNAND.error & 0x4))return -1; + sdmmc_send_command(&handleNAND, 0x10609, handleNAND.initarg << 0x10); + if((handleNAND.error & 0x4)) return -1; - handelNAND.total_size = calcSDSize((uint8_t*)&handelNAND.ret[0],0); - handelNAND.clk = 1; - setckl(1); + handleNAND.total_size = calcSDSize((u8*)&handleNAND.ret[0], 0); + handleNAND.clk = 1; + setckl(1); - sdmmc_send_command(&handelNAND,0x10407,handelNAND.initarg << 0x10); - if((handelNAND.error & 0x4))return -1; + sdmmc_send_command(&handleNAND, 0x10407, handleNAND.initarg << 0x10); + if((handleNAND.error & 0x4)) return -1; - handelNAND.SDOPT = 1; + handleNAND.SDOPT = 1; - sdmmc_send_command(&handelNAND,0x10506,0x3B70100); - if((handelNAND.error & 0x4))return -1; + sdmmc_send_command(&handleNAND, 0x10506, 0x3B70100); + if((handleNAND.error & 0x4)) return -1; - sdmmc_send_command(&handelNAND,0x10506,0x3B90100); - if((handelNAND.error & 0x4))return -1; + sdmmc_send_command(&handleNAND, 0x10506, 0x3B90100); + if((handleNAND.error & 0x4)) return -1; - sdmmc_send_command(&handelNAND,0x1040D,handelNAND.initarg << 0x10); - if((handelNAND.error & 0x4))return -1; + sdmmc_send_command(&handleNAND, 0x1040D, handleNAND.initarg << 0x10); + if((handleNAND.error & 0x4)) return -1; - sdmmc_send_command(&handelNAND,0x10410,0x200); - if((handelNAND.error & 0x4))return -1; + sdmmc_send_command(&handleNAND, 0x10410, 0x200); + if((handleNAND.error & 0x4)) return -1; - handelNAND.clk |= 0x200; + handleNAND.clk |= 0x200; - inittarget(&handelSD); + inittarget(&handleSD); - return 0; + return 0; } -int SD_Init() +static int SD_Init() { - //SD - handelSD.isSDHC = 0; - handelSD.SDOPT = 0; - handelSD.res = 0; - handelSD.initarg = 0; - handelSD.clk = 0x80; - handelSD.devicenumber = 0; + //SD + handleSD.isSDHC = 0; + handleSD.SDOPT = 0; + handleSD.res = 0; + handleSD.initarg = 0; + handleSD.clk = 0x80; + handleSD.devicenumber = 0; - inittarget(&handelSD); + inittarget(&handleSD); - waitcycles(1u << 22); //Card needs a little bit of time to be detected, it seems FIXME test again to see what a good number is for the delay + waitcycles(1u << 22); //Card needs a little bit of time to be detected, it seems FIXME test again to see what a good number is for the delay - //If not inserted - if (!(*((volatile uint16_t*)(SDMMC_BASE + REG_SDSTATUS0)) & TMIO_STAT0_SIGSTATE)) return 5; + //If not inserted + if(!(*((vu16 *)(SDMMC_BASE + REG_SDSTATUS0)) & TMIO_STAT0_SIGSTATE)) return 5; - sdmmc_send_command(&handelSD,0,0); - sdmmc_send_command(&handelSD,0x10408,0x1AA); - uint32_t temp = (handelSD.error & 0x1) << 0x1E; + sdmmc_send_command(&handleSD, 0, 0); + sdmmc_send_command(&handleSD, 0x10408, 0x1AA); + u32 temp = (handleSD.error & 0x1) << 0x1E; - uint32_t temp2 = 0; - do - { - do - { - sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10); - sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp); - temp2 = 1; - } while ( !(handelSD.error & 1) ); - } - while((handelSD.ret[0] & 0x80000000) == 0); + u32 temp2 = 0; + do + { + do + { + sdmmc_send_command(&handleSD, 0x10437, handleSD.initarg << 0x10); + sdmmc_send_command(&handleSD, 0x10769, 0x00FF8000 | temp); + temp2 = 1; + } + while(!(handleSD.error & 1)); + } + while((handleSD.ret[0] & 0x80000000) == 0); - if(!((handelSD.ret[0] >> 30) & 1) || !temp) - temp2 = 0; + if(!((handleSD.ret[0] >> 30) & 1) || !temp) + temp2 = 0; - handelSD.isSDHC = temp2; + handleSD.isSDHC = temp2; - sdmmc_send_command(&handelSD,0x10602,0); - if((handelSD.error & 0x4)) return -1; + sdmmc_send_command(&handleSD, 0x10602, 0); + if((handleSD.error & 0x4)) return -1; - sdmmc_send_command(&handelSD,0x10403,0); - if((handelSD.error & 0x4)) return -2; - handelSD.initarg = handelSD.ret[0] >> 0x10; + sdmmc_send_command(&handleSD, 0x10403, 0); + if((handleSD.error & 0x4)) return -2; + handleSD.initarg = handleSD.ret[0] >> 0x10; - sdmmc_send_command(&handelSD,0x10609,handelSD.initarg << 0x10); - if((handelSD.error & 0x4)) return -3; + sdmmc_send_command(&handleSD, 0x10609, handleSD.initarg << 0x10); + if((handleSD.error & 0x4)) return -3; - handelSD.total_size = calcSDSize((uint8_t*)&handelSD.ret[0],-1); - handelSD.clk = 1; - setckl(1); + handleSD.total_size = calcSDSize((u8*)&handleSD.ret[0], -1); + handleSD.clk = 1; + setckl(1); - sdmmc_send_command(&handelSD,0x10507,handelSD.initarg << 0x10); - if((handelSD.error & 0x4)) return -4; + sdmmc_send_command(&handleSD, 0x10507, handleSD.initarg << 0x10); + if((handleSD.error & 0x4)) return -4; - sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10); - if((handelSD.error & 0x4)) return -5; + sdmmc_send_command(&handleSD, 0x10437, handleSD.initarg << 0x10); + if((handleSD.error & 0x4)) return -5; - handelSD.SDOPT = 1; - sdmmc_send_command(&handelSD,0x10446,0x2); - if((handelSD.error & 0x4)) return -6; + handleSD.SDOPT = 1; + sdmmc_send_command(&handleSD, 0x10446, 0x2); + if((handleSD.error & 0x4)) return -6; - sdmmc_send_command(&handelSD,0x1040D,handelSD.initarg << 0x10); - if((handelSD.error & 0x4)) return -7; + sdmmc_send_command(&handleSD, 0x1040D, handleSD.initarg << 0x10); + if((handleSD.error & 0x4)) return -7; - sdmmc_send_command(&handelSD,0x10410,0x200); - if((handelSD.error & 0x4)) return -8; - handelSD.clk |= 0x200; + sdmmc_send_command(&handleSD, 0x10410, 0x200); + if((handleSD.error & 0x4)) return -8; + handleSD.clk |= 0x200; - return 0; + return 0; } -int sdmmc_get_cid(bool isNand, uint32_t *info) +void sdmmc_get_cid(bool isNand, u32 *info) { - struct mmcdevice *device; - if(isNand) - device = &handelNAND; - else - device = &handelSD; + struct mmcdevice *device = isNand ? &handleNAND : &handleSD; - inittarget(device); - // use cmd7 to put sd card in standby mode - // CMD7 - { - sdmmc_send_command(device,0x10507,0); - //if((device->error & 0x4)) return -1; - } + inittarget(device); - // get sd card info - // use cmd10 to read CID - { - sdmmc_send_command(device,0x1060A,device->initarg << 0x10); - //if((device->error & 0x4)) return -2; + // use cmd7 to put sd card in standby mode + // CMD7 + sdmmc_send_command(device, 0x10507, 0); - for( int i = 0; i < 4; ++i ) { - info[i] = device->ret[i]; - } - } + // get sd card info + // use cmd10 to read CID + sdmmc_send_command(device, 0x1060A, device->initarg << 0x10); - // put sd card back to transfer mode - // CMD7 - { - sdmmc_send_command(device,0x10507,device->initarg << 0x10); - //if((device->error & 0x4)) return -3; - } + for(int i = 0; i < 4; ++i) + info[i] = device->ret[i]; - return 0; + // put sd card back to transfer mode + // CMD7 + sdmmc_send_command(device, 0x10507, device->initarg << 0x10); } -int sdmmc_sdcard_init() +u32 sdmmc_sdcard_init() { - InitSD(); - int nand_res = Nand_Init(); - int sd_res = SD_Init(); - return nand_res | sd_res; -} + u32 ret = 0; + InitSD(); + if(Nand_Init() != 0) ret &= 1; + if(SD_Init() != 0) ret &= 2; + return ret; +} \ No newline at end of file diff --git a/source/nand/sdmmc.h b/source/nand/sdmmc.h index 2e1a504..5195cc0 100644 --- a/source/nand/sdmmc.h +++ b/source/nand/sdmmc.h @@ -1,50 +1,48 @@ -#ifndef __SDMMC_H__ -#define __SDMMC_H__ +#pragma once -#include -#include +#include "common.h" -#define SDMMC_BASE 0x10006000 +#define SDMMC_BASE 0x10006000 -#define REG_SDCMD 0x00 -#define REG_SDPORTSEL 0x02 -#define REG_SDCMDARG 0x04 -#define REG_SDCMDARG0 0x04 -#define REG_SDCMDARG1 0x06 -#define REG_SDSTOP 0x08 -#define REG_SDBLKCOUNT 0x0a +#define REG_SDCMD 0x00 +#define REG_SDPORTSEL 0x02 +#define REG_SDCMDARG 0x04 +#define REG_SDCMDARG0 0x04 +#define REG_SDCMDARG1 0x06 +#define REG_SDSTOP 0x08 +#define REG_SDBLKCOUNT 0x0A -#define REG_SDRESP0 0x0c -#define REG_SDRESP1 0x0e -#define REG_SDRESP2 0x10 -#define REG_SDRESP3 0x12 -#define REG_SDRESP4 0x14 -#define REG_SDRESP5 0x16 -#define REG_SDRESP6 0x18 -#define REG_SDRESP7 0x1a +#define REG_SDRESP0 0x0C +#define REG_SDRESP1 0x0E +#define REG_SDRESP2 0x10 +#define REG_SDRESP3 0x12 +#define REG_SDRESP4 0x14 +#define REG_SDRESP5 0x16 +#define REG_SDRESP6 0x18 +#define REG_SDRESP7 0x1A -#define REG_SDSTATUS0 0x1c -#define REG_SDSTATUS1 0x1e +#define REG_SDSTATUS0 0x1C +#define REG_SDSTATUS1 0x1E -#define REG_SDIRMASK0 0x20 -#define REG_SDIRMASK1 0x22 -#define REG_SDCLKCTL 0x24 +#define REG_SDIRMASK0 0x20 +#define REG_SDIRMASK1 0x22 +#define REG_SDCLKCTL 0x24 -#define REG_SDBLKLEN 0x26 -#define REG_SDOPT 0x28 -#define REG_SDFIFO 0x30 +#define REG_SDBLKLEN 0x26 +#define REG_SDOPT 0x28 +#define REG_SDFIFO 0x30 -#define REG_DATACTL 0xd8 -#define REG_SDRESET 0xe0 -#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not? +#define REG_DATACTL 0xD8 +#define REG_SDRESET 0xE0 +#define REG_SDPROTECTED 0xF6 //bit 0 determines if sd is protected or not? -#define REG_DATACTL32 0x100 -#define REG_SDBLKLEN32 0x104 -#define REG_SDBLKCOUNT32 0x108 -#define REG_SDFIFO32 0x10C +#define REG_DATACTL32 0x100 +#define REG_SDBLKLEN32 0x104 +#define REG_SDBLKCOUNT32 0x108 +#define REG_SDFIFO32 0x10C #define REG_CLK_AND_WAIT_CTL 0x138 -#define REG_RESET_SDIO 0x1e0 +#define REG_RESET_SDIO 0x1E0 #define TMIO_STAT0_CMDRESPEND 0x0001 #define TMIO_STAT0_DATAEND 0x0004 @@ -68,94 +66,35 @@ #define TMIO_STAT1_CMD_BUSY 0x4000 #define TMIO_STAT1_ILL_ACCESS 0x8000 -#define TMIO_MASK_ALL 0x837f031d +#define TMIO_MASK_ALL 0x837F031D #define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \ - TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR) + TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR) #define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND) #define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND) -#ifdef __cplusplus -extern "C" { -#endif +typedef struct mmcdevice { + u8 *rData; + const u8 *tData; + u32 size; + u32 error; + u16 stat0; + u16 stat1; + u32 ret[4]; + u32 initarg; + u32 isSDHC; + u32 clk; + u32 SDOPT; + u32 devicenumber; + u32 total_size; //size in sectors of the device + u32 res; +} mmcdevice; - typedef struct mmcdevice { - uint8_t* rData; - const uint8_t* tData; - uint32_t size; - uint32_t error; - uint16_t stat0; - uint16_t stat1; - uint32_t ret[4]; - uint32_t initarg; - uint32_t isSDHC; - uint32_t clk; - uint32_t SDOPT; - uint32_t devicenumber; - uint32_t total_size; //size in sectors of the device - uint32_t res; - } mmcdevice; - - int sdmmc_sdcard_init(); - int sdmmc_sdcard_readsector(uint32_t sector_no, uint8_t *out); - int sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out); - int sdmmc_sdcard_writesector(uint32_t sector_no, const uint8_t *in); - int sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, const uint8_t *in); - - int sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out); - int sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, const uint8_t *in); - - int sdmmc_get_cid(bool isNand, uint32_t *info); - - mmcdevice *getMMCDevice(int drive); - - void InitSD(); - int Nand_Init(); - int SD_Init(); - -#ifdef __cplusplus -}; -#endif - -//--------------------------------------------------------------------------------- -static inline uint16_t sdmmc_read16(uint16_t reg) { -//--------------------------------------------------------------------------------- - return *(volatile uint16_t*)(SDMMC_BASE + reg); -} - -//--------------------------------------------------------------------------------- -static inline void sdmmc_write16(uint16_t reg, uint16_t val) { -//--------------------------------------------------------------------------------- - *(volatile uint16_t*)(SDMMC_BASE + reg) = val; -} - -//--------------------------------------------------------------------------------- -static inline uint32_t sdmmc_read32(uint16_t reg) { -//--------------------------------------------------------------------------------- - return *(volatile uint32_t*)(SDMMC_BASE + reg); -} - -//--------------------------------------------------------------------------------- -static inline void sdmmc_write32(uint16_t reg, uint32_t val) { -//--------------------------------------------------------------------------------- - *(volatile uint32_t*)(SDMMC_BASE + reg) = val; -} - -//--------------------------------------------------------------------------------- -static inline void sdmmc_mask16(uint16_t reg, const uint16_t clear, const uint16_t set) { -//--------------------------------------------------------------------------------- - uint16_t val = sdmmc_read16(reg); - val &= ~clear; - val |= set; - sdmmc_write16(reg, val); -} - -static inline void setckl(uint32_t data) -{ - sdmmc_mask16(REG_SDCLKCTL,0x100,0); - sdmmc_mask16(REG_SDCLKCTL,0x2FF,data&0x2FF); - sdmmc_mask16(REG_SDCLKCTL,0x0,0x100); -} - -#endif +u32 sdmmc_sdcard_init(); +int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out); +int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in); +int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out); +int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in); +void sdmmc_get_cid(bool isNand, u32 *info); +mmcdevice *getMMCDevice(int drive); \ No newline at end of file