duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 754d92b947842fbde4df0cf23827f3a72bc8c581
parent d9ad228c80f1133d8ee94d3592b6e841c9542986
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Mon, 19 Jun 2023 16:17:08 -0400

rpi: can read block from EMMC on real hardware!

When I run "emmc$ 0 here block@ here @ .x" on a rpi1 with a SanDisk Ultra HC-I,
I reliably get proper initialization and the number I get corresponds to the
beginning of the first sector of the card. Hell yeah!

Diffstat:
Mfs/drv/rpi/emmc.fs | 49++++++++++++++++++++++++++++---------------------
Mfs/xcomp/arm/rpi/build.fs | 2+-
2 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/fs/drv/rpi/emmc.fs b/fs/drv/rpi/emmc.fs @@ -12,40 +12,48 @@ EMMC_BASE $30 + const EMMC_INTERRUPT EMMC_BASE $34 + const EMMC_IRPT_MASK $017e8000 const INT_ERROR_MASK $00000020 const INT_READ_READY +$00000001 const INT_CMD_DONE $80000000 const ACMD41_COMPLETE $01000000 const SRST_HT $00000002 const CLK_STABLE -0 value rca \ RCA of current card +0 value rca \ RCA of current card, stored in higher 16b : err abort" EMMC error" ; : # not if err then ; : delay ( n -- ) begin 1- ?dup not until ; : delayus ( us -- ) 1000 * delay ; \ TODO: use actual timer -: status ( mask -- f ) \ f=1 if things are ok +: status ( mask -- ) $10000 for - EMMC_STATUS @ over and not if drop 1 break then + EMMC_STATUS @ over and not if drop break then EMMC_INTERRUPT @ INT_ERROR_MASK and not # - 1 delayus next drop 0 then ( f ) ; -: cmdwait 1 status # ; \ CMD_INHIBIT mask -: datawait 2 status # ; \ DAT_INHIBIT mask + 1 delayus next abort" status timeout" then ; +: cmdwait 1 status ; \ CMD_INHIBIT mask +: datawait 2 status ; \ DAT_INHIBIT mask : intclr EMMC_INTERRUPT @ EMMC_INTERRUPT ! ; : intwait ( mask -- ) INT_ERROR_MASK or $10000 for - EMMC_INTERRUPT @ over and if break then 1 delayus next err then + EMMC_INTERRUPT @ over and if break then 1 delayus next + abort" intwait timeout" then EMMC_INTERRUPT @ INT_ERROR_MASK and not # ( mask ) EMMC_INTERRUPT ! ; : readready INT_READ_READY intwait ; -: cmd ( arg cmdidx -- ) cmdwait intclr swap EMMC_ARG1 ! EMMC_CMDTM ! cmdwait ; -: cmdr cmd EMMC_RESP0 @ ; -: acmd ( arg cmdidx -- ) 0 $37000000 cmd ( CMD55 ) 100 delayus cmd ; +: cmddone INT_CMD_DONE intwait ; +: cmd ( arg cmdidx -- ) cmdwait intclr swap EMMC_ARG1 ! EMMC_CMDTM ! cmddone ; +: cmdr ( arg cmdidx -- resp ) cmd EMMC_RESP0 @ ; +: acmd ( arg cmdidx -- ) 0 $37020000 cmd ( CMD55 ) 100 delayus cmd ; : cmd0 0 0 cmd ; \ CMD_GO_IDLE : cmd2 0 $02010000 cmd ; \ CMD_ALL_SEND_CID -: cmd3 ( -- rca ) 0 $03010000 cmdr ; \ CMD_SEND_REL_ADDR +: cmd3 ( -- rca ) 0 $03020000 cmdr ; \ CMD_SEND_REL_ADDR : cmd7 ( rca -- ) $07030000 cmd ; -: cmd8 ( arg -- resp ) $08020000 cmd 2000 delayus EMMC_RESP0 @ ; +: cmd8 ( arg -- resp ) $08020000 cmd 1000 delayus EMMC_RESP0 @ ; : cmd17 ( lba -- ) $11220010 cmd ; : acmd41 ( arg -- resp ) $29020000 acmd 1000 delayus EMMC_RESP0 @ ; +: clk! ( div -- ) + cmdwait datawait 8 lshift $000e0005 or EMMC_CONTROL1 ! 10000 for + 10 delayus + EMMC_CONTROL1 @ CLK_STABLE and if break then next + abort" clk failed" then ; : block@ ( lba dst -- ) datawait $00010200 EMMC_BLKSIZECNT ! swap $200 * cmd17 readready \ TODO: check CCS flag to know if we do "$200 *" @@ -56,12 +64,11 @@ $00000002 const CLK_STABLE : emmc$ SRST_HT EMMC_CONTROL1 ! \ reset 100 for 1 delayus EMMC_CONTROL1 @ SRST_HT and not if break then next err then - $000efa05 EMMC_CONTROL1 ! \ enable clock, 400khz - 10000 for - 10 delayus - EMMC_CONTROL1 @ CLK_STABLE and if break then next err then - INT_READ_READY INT_ERROR_MASK or EMMC_IRPT_MASK ! \ enable INTs we use - cmd0 $1aa cmd8 $fff and $1aa = # 0 acmd41 drop 6 for - 400 delay $40ff8000 acmd41 ACMD41_COMPLETE and if break then next err then - cmd2 \ no idea why it's needed - cmd3 dup to rca cmd7 ; + 250 clk! \ 400 kHz + INT_READ_READY INT_CMD_DONE or INT_ERROR_MASK or EMMC_IRPT_MASK ! + cmd0 $1aa cmd8 $fff and $1aa <> if abort" CMD8 error" then 10 for + $50ff8000 acmd41 ACMD41_COMPLETE and if break then 400 delayus next + abort" CMD41 timeout" then + cmd2 cmd3 dup $ffff0000 and to rca + 4 clk! \ 25 MHz + rca cmd7 ; diff --git a/fs/xcomp/arm/rpi/build.fs b/fs/xcomp/arm/rpi/build.fs @@ -15,11 +15,11 @@ org value kernel kernel kernellen V1 IO :write S" /xcomp/bootlo.fs" V1 spitfile S" /drv/rpi/uart.fs" V1 spitfile - S" /drv/rpi/emmc.fs" V1 spitfile S" /xcomp/arm/rpi/glue.fs" V1 spitfile S" /lib/struct.fs" V1 spitfile S" /sys/io.fs" V1 spitfile S" /lib/fmt.fs" V1 spitfile + S" /drv/rpi/emmc.fs" V1 spitfile S" /sys/rdln.fs" V1 spitfile S" /xcomp/arm/rpi/init.fs" V1 spitfile r> IO :flush ;