emmc.fs (3310B) - raw
1 extends Drive struct[ EMMCDrive 2 $20000000 const MMIO_BASE 3 MMIO_BASE $300000 + const EMMC_BASE 4 EMMC_BASE $04 + const EMMC_BLKSIZECNT 5 EMMC_BASE $08 + const EMMC_ARG1 6 EMMC_BASE $0c + const EMMC_CMDTM 7 EMMC_BASE $10 + const EMMC_RESP0 8 EMMC_BASE $20 + const EMMC_DATA 9 EMMC_BASE $24 + const EMMC_STATUS 10 EMMC_BASE $28 + const EMMC_CONTROL0 11 EMMC_BASE $2c + const EMMC_CONTROL1 12 EMMC_BASE $30 + const EMMC_INTERRUPT 13 EMMC_BASE $34 + const EMMC_IRPT_MASK 14 $017e8000 const INT_ERROR_MASK 15 $00000020 const INT_READ_READY 16 $00000001 const INT_CMD_DONE 17 $80000000 const ACMD41_COMPLETE 18 $40000000 const ACMD41_CCS 19 $01000000 const SRST_HT 20 $00000002 const CLK_STABLE 21 22 0 value rca \ RCA of current card, stored in higher 16b 23 0 value ccs 24 25 : err abort" EMMC error" ; 26 : # not if err then ; 27 : delay ( n -- ) begin 1- ?dup not until ; 28 : delayus ( us -- ) 1000 * delay ; \ TODO: use actual timer 29 : status ( mask -- ) 30 $10000 for 31 EMMC_STATUS @ over and not if drop break then 32 EMMC_INTERRUPT @ INT_ERROR_MASK and not # 33 1 delayus next abort" status timeout" then ; 34 : cmdwait 1 status ; \ CMD_INHIBIT mask 35 : datawait 2 status ; \ DAT_INHIBIT mask 36 : intclr EMMC_INTERRUPT @ EMMC_INTERRUPT ! ; 37 : intwait ( mask -- ) 38 INT_ERROR_MASK or $10000 for 39 EMMC_INTERRUPT @ over and if break then 1 delayus next 40 abort" intwait timeout" then 41 EMMC_INTERRUPT @ INT_ERROR_MASK and not # 42 ( mask ) EMMC_INTERRUPT ! ; 43 : readready INT_READ_READY intwait ; 44 : cmddone INT_CMD_DONE intwait ; 45 : cmd ( arg cmdidx -- ) cmdwait intclr swap EMMC_ARG1 ! EMMC_CMDTM ! cmddone ; 46 : cmdr ( arg cmdidx -- resp ) cmd EMMC_RESP0 @ ; 47 : acmd ( arg cmdidx -- ) 0 $37020000 cmd ( CMD55 ) 100 delayus cmd ; 48 : cmd0 0 0 cmd ; \ CMD_GO_IDLE 49 : cmd2 0 $02010000 cmd ; \ CMD_ALL_SEND_CID 50 : cmd3 ( -- rca ) 0 $03020000 cmdr ; \ CMD_SEND_REL_ADDR 51 : cmd7 ( rca -- ) $07030000 cmd ; 52 : cmd8 ( arg -- resp ) $08020000 cmd 1000 delayus EMMC_RESP0 @ ; 53 : cmd17 ( lba -- ) $11220010 cmd ; 54 : acmd41 ( arg -- resp ) $29020000 acmd 1000 delayus EMMC_RESP0 @ ; 55 : clk! ( div -- ) 56 cmdwait datawait 8 lshift $000e0005 or EMMC_CONTROL1 ! 10000 for 57 10 delayus 58 EMMC_CONTROL1 @ CLK_STABLE and if break then next 59 abort" clk failed" then ; 60 : sec@ ( sec dst self -- ) drop 61 datawait $00010200 EMMC_BLKSIZECNT ! 62 swap ccs not if $200 * then cmd17 readready 63 $200 >> >> for EMMC_DATA @ swap !+ next drop ; 64 : sec! err ; 65 \ We assume the EMMC base clock to be 100 MHz. During identification, we need 66 \ 400 kHz, which means a 250 divider. Then, later, we go to a "normal" frequency 67 \ of 25 MHz, which means a 4 divider. 68 : :init ( self -- ) 69 drop SRST_HT EMMC_CONTROL1 ! \ reset 70 100 for 1 delayus EMMC_CONTROL1 @ SRST_HT and not if break then next err then 71 250 clk! \ 400 kHz 72 INT_READ_READY INT_CMD_DONE or INT_ERROR_MASK or EMMC_IRPT_MASK ! 73 cmd0 $1aa cmd8 $fff and $1aa <> if abort" CMD8 error" then 10 for 74 $50ff8000 acmd41 ACMD41_COMPLETE and if break then 400 delayus next 75 abort" CMD41 timeout" then 76 EMMC_RESP0 @ ACMD41_CCS and bool to ccs 77 cmd2 cmd3 $ffff0000 and to rca 78 4 clk! \ 25 MHz 79 rca cmd7 ; 80 : :new $200 -1 Drive :new ,[ :[methods] ], move, ; 81 ]struct 82 83 EMMCDrive :new structbind EMMCDrive emmc