; -------------------------------------------------------------------------------- ; @Title: eMMC/SD FLASH Program script for the RCARS4 Evaluation Board ; @Description: ; eMMC FLASH, MTFC32GAZAQHD ; The eMMC is connected to the SDHI/MMC0 Controller ; ; GP1_24 - SD_WP ; GP1_23 - SD_CD ; GP1_20 - MMC_DS ; GP1_22 - MMC_SD_CMD ; GP1_13 - MMC_SD_D0 ; GP1_14 - MMC_SD_D1 ; GP1_15 - MMC_SD_D2 ; GP1_16 - MMC_SD_D3 ; GP1_12 - MMC_SD_CLK ; GP1_18 - MMC_D4 ; GP1_17 - MMC_D5 ; GP1_19 - MMC_D6 ; GP1_21 - MMC_D7 ; ; SRAM: 0xE6328000 ; SDHI(MMC) controller Base: 0xEE140000 ; ; @Keywords: ARM, Cortex-CR52, RCarS4 ; @Author: JIM ; @Board: R-CarS4 System Evaluation Board "Spider" ; @Chip: R8A779F0LA80-CR52 ; @Copyright: (C) 1989-2024 Lauterbach GmbH, licensed for use with TRACE32(R) only ; -------------------------------------------------------------------------------- ; $Id: rcars4-cr52-emmc.cmm 13187 2024-03-18 09:11:20Z jjeong $ &MMC_BASE=0xEE140000 &SDCARD=FALSE() ; SDCARD=TRUE() for SDCARD , SDCARD=FALSE() for eMMC ; -------------------------------------------------------------------------------- ; Initialize and start the debugger RESet SYStem.RESet IF VERSION.BUILD()<143697. ; 22-Jan-2022 SYStem.CPU RCARS4-CR52 ELSE SYStem.CPU R8A779F0LA80-CR52 SYStem.MemAccess DAP SYStem.JtagClock 10MHz SYStem.Option.ResBreak OFF MAP.DenyAccess 0xE3000000--0xE3FFFFFF MAP.DenyAccess 0xE4008000--0xE40FFFFF SYStem.Up ; -------------------------------------------------------------------------------- ; Enable ATCM PER.Set.simple C15:0x19 %Long 0xE400001b ; -------------------------------------------------------------------------------- ; DRCR.RBE=0 (RPC Read cache = OFF) for flash region access Data.Set AD:0xEE20000C %LE %Long 0yXXXXxxxxXXXXxxxxXXXXxxx0XXXXxxxx ; -------------------------------------------------------------------------------- ; Enable SDHI controller GOSUB POWER_ON_SDHI ; -------------------------------------------------------------------------------- ; Pin Mux for SDHI GOSUB PIN_MUX ; -------------------------------------------------------------------------------- ; Initialize SDHI/MMC GOSUB INIT_MMC0 GOSUB READ_ID_TEST Break.RESet FLASHFILE.RESet //FLASHFILE.CONFIG FLASHFILE.CONFIG &MMC_BASE //FLASHFILE.TARGET FLASHFILE.TARGET 0xE6328000++0x1FFF E:0xE632A000++0x21FF ~~/demo/arm/flash/byte/emmc_shsdhi.bin /KEEP /STACKSIZE 0x200 /DualPort GOSUB CLK_DOWN_400KHz FLASHFILE.GETID GOSUB CLK_UP_20MHz //Get EXTended CSD registers FLASHFILE.GETEXTCSD //End of the test prepareonly IF "&arg1"=="PREPAREONLY" ENDDO //When you access to the other partition on the flash ; FLASHFILE.SETEXTCSD 179. 0x00 ; access: partition null, no boot, access: no boot partition ; FLASHFILE.SETEXTCSD 179. 0x48 ; access: partition null ; FLASHFILE.SETEXTCSD 179. 0x49 ; access: partition boot 1 ; FLASHFILE.SETEXTCSD 179. 0x4A ; access: partition boot 2 FLASHFILE.DUMP 0x0 ; Read eMMC ;FLASHFILE.ERASE 0x0--0xFFFFF ; Erase eMMC ;FLASHFILE.LOAD * 0x0 ; Write eMMC ENDDO CLK_UP_20MHz: ( PER.Set.simple A:&MMC_BASE+0x0090 %Long 0x0 //*((volatile uint32_t*)MMC_CH0_SD_CLK_CTRL) = 0x101; //1/4 ; 20Mhz PER.Set.simple A:&MMC_BASE+0x0090 %Quad 0x108 //*((volatile uint32_t*)(MMC_CH0_SCC_DTCNTL)) = 0x00080000; // SCC_DTCNTL.TAPEN=0 PER.Set.simple A:&MMC_BASE+0x1000 %Long 0x00080000 //*((volatile uint32_t*)(MMC_CH0_SCC_TAPSET)) = 2; // SCC_TAPSET PER.Set.simple A:&MMC_BASE+0x1008 %Long 0x2 //*((volatile uint32_t*)(MMC_CH0_SCC_CKSEL)) = 0x00000000; // SCC_CKSEL=0 PER.Set.simple A:&MMC_BASE+0x1018 %Long 0x0 RETURN ) CLK_DOWN_400KHz: ( // *((volatile uint32_t*)MMC_CH0_SD_CLK_CTRL) = 0x00000000; // Automatic Control=Disable, Clock Output=Disable PER.Set.simple A:&MMC_BASE+0x0090 %Long 0x0 // *((volatile uint32_t*)MMC_CH0_SD_CLK_CTRL) = 0x180; //1/512 ; 400KHz PER.Set.simple A:&MMC_BASE+0x0090 %Quad 0x140 //*((volatile uint32_t*)(MMC_CH0_SCC_DTCNTL)) = 0x00080000; // SCC_DTCNTL.TAPEN=0 PER.Set.simple A:&MMC_BASE+0x1000 %Long 0x00080000 //*((volatile uint32_t*)(MMC_CH0_SCC_TAPSET)) = 2; // SCC_TAPSET PER.Set.simple A:&MMC_BASE+0x1008 %Long 0x2 //*((volatile uint32_t*)(MMC_CH0_SCC_CKSEL)) = 0x00000000; // SCC_CKSEL=0 PER.Set.simple A:&MMC_BASE+0x1018 %Long 0x0 RETURN ) INIT_MMC0: ( //SW Reset for the MMC memory Data.Set A:&MMC_BASE+0x380 %LE %Quad 0x0 WAIT 100.ms Data.Set A:&MMC_BASE+0x380 %LE %Quad 0x7 // *((volatile uint32_t*)MMC_CH0_HOST_MODE) = 0x00000000; // SD_BUF access width = 64-bit PER.Set.simple A:&MMC_BASE+0x0390 %Long 0x0 // *((volatile uint32_t*)MMC_CH0_SD_OPTION) = 0x0000C0EE; // Bus width = 1bit, timeout=MAX PER.Set.simple A:&MMC_BASE+0x00A0 %Long 0xc0EE // *((volatile uint32_t*)MMC_CH0_SD_CLK_CTRL) = 0x00000000; // Automatic Control=Disable, Clock Output=Disable PER.Set.simple A:&MMC_BASE+0x0090 %Long 0x0 // *((volatile uint32_t*)MMC_CH0_SD_CLK_CTRL) = 0x180; //1/512 ; 400KHz PER.Set.simple A:&MMC_BASE+0x0090 %Quad 0x180 //*((volatile uint32_t*)(MMC_CH0_SCC_DTCNTL)) = 0x00080000; // SCC_DTCNTL.TAPEN=0 PER.Set.simple A:&MMC_BASE+0x1000 %Long 0x00080000 //*((volatile uint32_t*)(MMC_CH0_SCC_TAPSET)) = 2; // SCC_TAPSET PER.Set.simple A:&MMC_BASE+0x1008 %Long 0x2 //*((volatile uint32_t*)(MMC_CH0_SCC_CKSEL)) = 0x00000000; // SCC_CKSEL=0 PER.Set.simple A:&MMC_BASE+0x1018 %Long 0x0 // *((volatile uint32_t*)MMC_CH0_SD_INFO1_MASK) = 0x0001031D; // all mask (0x0000FFFE in HWM) PER.Set.simple A:&MMC_BASE+0x0080 %Quad 0x1031D // *((volatile uint32_t*)MMC_CH0_SD_INFO2_MASK) = 0x00008B7F; // all mask (0x00007F80 in HWM) PER.Set.simple A:&MMC_BASE+0x0088 %Quad 0x8B7F RETURN ) READ_ID_TEST: ( LOCAL &cardaddress IF !&SDCARD &OCR=0x40FF8080 ; init with low voltage power 1.7~1.95v, ex. eMMC ELSE &OCR=0x40FF8000 ; init with defualt voltage power 2.7~3.6v, ex. SD //CMD0, resp0 RePeaT 2. ( //MMC_CH0_SD_INFO1 PER.Set.simple A:&MMC_BASE+0x0070 %Long 0xFFFE ;clear resp end BIT0 // SendMmc0Cmd0(0x00000000); PER.Set.simple A:&MMC_BASE+0x0010 %Long 0x0 ;arg PER.Set.simple A:&MMC_BASE+0x0000 %Quad 0x0 ;cmd , resp[10:8], cmd_type[7:6] WAIT 100.ms ) IF &SDCARD //SD(HC) interface, not MMC ( //CMD8, resp1 is madatory to intialize High Capacity SD Memory Card RePeaT 2. ( PER.Set.simple A:&MMC_BASE+0x0070 %Long 0xFFFE ;clear resp end BIT0 PER.Set.simple A:&MMC_BASE+0x0010 %Long 0x1AA ;arg PER.Set.simple A:&MMC_BASE+0x0000 %Quad 0x00000008|0x400 ;cmd8, resp1 WAIT 10.ms &status=Data.Long(A:&MMC_BASE+0x30) IF (&status&0x30000)==0x0 ( PRINT "passed CMD8(voltage check)" GOTO jump_cmd55 ) ELSE ( //CMD0, resp0 PER.Set.simple A:&MMC_BASE+0x0070 %Long 0xFFFE ;clear resp end BIT0 PER.Set.simple A:&MMC_BASE+0x0010 %Long 0x0 ;arg PER.Set.simple A:&MMC_BASE+0x0000 %Quad 0x0 ;cmd WAIT 200.ms ) ) ) ELSE //MMC interface ( //CMD1, resp3 RePeaT 10. ( //SendMmc0Command(MMC_CMD1,ocr); //MMC_CH0_SD_INFO1 PER.Set.simple A:&MMC_BASE+0x0070 %Long 0xFFFE ;clear resp end BIT0 PER.Set.simple A:&MMC_BASE+0x0010 %Long &OCR ;arg PER.Set.simple A:&MMC_BASE+0x0000 %Quad 0x001|0x700 ;cmd1, resp3 WAIT 100.ms &resp=Data.Long(A:&MMC_BASE+0x0030) //print "CMD1 resp: 0x" &resp IF (&resp&0x80000000)==0x80000000 ( GOTO jump_cmd2 ) ) PRINT "CMD1 fail" END ) jump_cmd55: //CMD55, resp1 RePeaT 10. ( PER.Set.simple A:&MMC_BASE+0x0070 %Long 0xFFFE ;clear resp end BIT0 PER.Set.simple A:&MMC_BASE+0x0010 %Long 0x0 ;arg PER.Set.simple A:&MMC_BASE+0x0000 %Quad 0x37|0x400 ;cmd55,resp1 WAIT 10.ms //ACMD41 PER.Set.simple A:&MMC_BASE+0x0070 %Long 0xFFFE ;clear resp end BIT0 PER.Set.simple A:&MMC_BASE+0x0010 %Long 0x1AA ;arg PER.Set.simple A:&MMC_BASE+0x0000 %Quad 0x29|0x740 ;cmd1, resp3, acmd WAIT 100.ms &resp=Data.Long(A:&MMC_BASE+0x0030) //print "CMD1 resp: 0x" &resp IF (&resp&0x80000000)==0x80000000 ( GOTO jump_cmd2 ) ) PRINT "ACMD41 fail" END jump_cmd2: //CMD2 PER.Set.simple A:&MMC_BASE+0x0070 %Long 0xFFFE ;clear resp end BIT0 PER.Set.simple A:&MMC_BASE+0x0010 %Long 0x0 ;arg PER.Set.simple A:&MMC_BASE+0x0000 %Quad 0x2 ;cmd WAIT 10.ms //CMD3 PER.Set.simple A:&MMC_BASE+0x0070 %Long 0xFFFE ;clear resp end BIT0 PER.Set.simple A:&MMC_BASE+0x0010 %Long 0x10000 ;arg PER.Set.simple A:&MMC_BASE+0x0000 %Quad 0x3|0x400 ;cmd, resp1(48bits) WAIT 10.ms &cardaddress=Data.Long(A:&MMC_BASE+0x0030) &cardaddress=&cardaddress&0xFFFF0000 IF !&SDCARD ( &cardaddress=0x00010000 ; arg, MMC RCA is (0x0001<<16.) ) //CMD10 PER.Set.simple A:&MMC_BASE+0x0070 %Long 0xFFFE ;clear resp end BIT0 PER.Set.simple A:&MMC_BASE+0x0010 %Long &cardaddress ;arg PER.Set.simple A:&MMC_BASE+0x0000 %Quad 0x0000000A ;cmd, resp2(136Bits) WAIT 10.ms //Response2 PRINT "CID register" PRINT "[127:104] 0x" Data.Long(A:&MMC_BASE+0x0060) PRINT "[103:72] 0x" Data.Long(A:&MMC_BASE+0x0050) PRINT "[71:40] 0x" Data.Long(A:&MMC_BASE+0x0040) PRINT "[39:8] 0x" Data.Long(A:&MMC_BASE+0x0030) RETURN ) POWER_ON_SDHI: ( ;SD0CKCR0 PER.Set.simple AHD:0xE6150000 %Long ~0x208 PER.Set.simple AHD:0xE6150870 %Long 0x208 ;SD0CKCR1 PER.Set.simple AHD:0xE6150000 %Long ~0x0FFF0000 PER.Set.simple AHD:0xE61508A4 %Long 0x0FFF0000 ;SRCR7 [6] ,SDHI/MMC software module reset PER.Set.simple AHD:0xE6150000 %Long ~0x0 PER.Set.simple AHD:0xE6152C1C %Long 0x0 ;MSTPCR7 [6], SDHI/MMC PER.Set.simple AHD:0xE6150000 %Long ~0x1FFBE000 PER.Set.simple AHD:0xE6152D1C %Long 0x1FFBE000 RETURN ) PIN_MUX: ( //GP1_[12-24] for SD/MMC pins ;GPSR1 PER.Set.simple AHD:0xE6050800 %Long ~0x1FFF000 PER.Set.simple AHD:0xE6050840 %Long 0x1FFF000 ;TD0SEL PER.Set.simple AHD:0xE6050800 %Long ~0x0 PER.Set.simple AHD:0xE6050920 %Long 0x0 RETURN )