[openfirmware] [commit] r1740 - dev/mmc/sdhci
repository service
svn at openfirmware.info
Sat Feb 13 06:58:03 CET 2010
Author: wmb
Date: Sat Feb 13 06:58:02 2010
New Revision: 1740
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/1740
Log:
SDHCI - added support for erase-blocks and predeclaring the write size, and fixed a potential coherence problem with duplicate deblocker instances.
Modified:
dev/mmc/sdhci/sdhci.fth
dev/mmc/sdhci/sdmmc.fth
Modified: dev/mmc/sdhci/sdhci.fth
==============================================================================
--- dev/mmc/sdhci/sdhci.fth Sat Feb 13 06:52:26 2010 (r1739)
+++ dev/mmc/sdhci/sdhci.fth Sat Feb 13 06:58:02 2010 (r1740)
@@ -377,6 +377,13 @@
drop ( )
;
+\ Command register: --cccccc.TTDI.C-rr c-command# T-CmdType D-dataPresent I-CmdIndexCheck C-CmdCRCcheck r-responseType
+\ CmdType: 00-normal 01-suspend 10-resume 11-abort
+\ ResponseType: 00-none 01-136 10-48 11-48_and_check_busy
+\ Argument register:
+\ Mode register: --Md-ABD M-Multi d-Direction A-Auto_CMD12 B-BlockCntEnable D-DMAEnable
+
+
: cmd ( arg cmd mode -- )
debug? if ." CMD: " over 4 u.r space then
wait-ready
@@ -499,11 +506,13 @@
: protected? ( group# -- 32-bits ) h# 1e1a cmd response ; \ CMD30 R1 UNTESTED
: erase-blocks ( block# #blocks -- ) \ UNTESTED
+ intstat-on
dup 0= if 2drop exit then
1- bounds ( last first )
h# 201a 0 cmd ( last ) \ CMD32 - R1
h# 211a 0 cmd ( ) \ CMD33 - R1
- h# 261b 0 cmd \ CMD38 - R1b (wait for busy)
+ 0 h# 261b 0 cmd \ CMD38 - R1b (wait for busy)
+ intstat-off
;
\ CMD40 is MMC
@@ -517,11 +526,25 @@
: set-oc ( ocr -- ocr' ) app-prefix h# 2902 0 cmd response ; \ ACMD41 R3
-\ This sends back 512 bits in a single data block.
-: app-get-status ( -- status ) app-prefix 0 h# 0d1a h# 12 cmd response ; \ ACMD13 R1 UNTESTED
+\ This sends back 512 bits (64 bytes) in a single data block. See sdstatbits
+\ It contains things like the allocation unit size and the speed class.
+: app-get-status ( -- buf ) \ ACMD13 R1
+ intstat-on
+ scratch-buf d# 64 dup (dma-setup)
+ app-prefix 0 h# 0d3a h# 13 cmd
+ response h# 20 and 0= abort" ACMD13 not implemented!"
+ 2 wait
+ dma-release
+ scratch-buf
+ intstat-off
+;
: get-#write-blocks ( -- n ) app-prefix 0 h# 161a 0 cmd response ; \ ACMD22 R1 UNTESTED
+\ Using this before a write-multiple command speeds up the write by
+\ avoiding unnecessary preservation of data that will be clobbered.
+: pre-write-erase ( #blocks -- ) intstat-on app-prefix ( #blocks ) h# 171a 0 cmd ; \ ACMD23 R1
+
\ You might want to turn this off for data transfer, as it controls
\ a resistor on one of the data lines
: set-card-detect ( on/off -- ) app-prefix h# 2a1a 0 cmd ; \ ACMD42 R1 UNTESTED
@@ -934,24 +957,29 @@
dma-len /block /
;
-: r/w-blocks-start ( addr block# #blocks in? -- error? )
- wait-dma-done
- over 0= if 2drop 2drop false exit then \ Prevents hangs
- intstat-on
- >r ( addr block# #blocks r: in? )
- rot dma-setup ( block# r: in? )
- wait-write-done if true exit then
- address-shift lshift r> if
- read-multiple
- else
- write-multiple true to writing?
- then
- true to dma?
- false
+: r/w-blocks-start ( addr block# #blocks in? fresh? -- error? )
+ wait-dma-done ( addr block# #blocks fresh? in? )
+ 2 pick 0= if 3drop 2drop false exit then \ Prevents hangs
+ intstat-on ( addr block# #blocks fresh? in? )
+ 2 pick >r >r >r ( addr block# #blocks r: #blocks fresh? in? )
+ rot dma-setup ( block# r: #blocks fresh? in? )
+ wait-write-done if drop r> r> r> 3drop true exit then ( block# )
+ address-shift lshift r> if ( block# r: #blocks fresh? )
+ r> r> 2drop ( block# )
+ read-multiple ( )
+ else ( block# r: #blocks fresh? )
+ r> if r> pre-write-erase else r> drop then ( block# )
+ write-multiple true to writing? ( )
+ then ( )
+ true to dma? ( )
+ false ( error? )
+;
+: fresh-write-blocks-start ( addr block# #blocks -- error? )
+ false true r/w-blocks-start
;
: r/w-blocks ( addr block# #blocks in? -- actual )
- r/w-blocks-start if -1 exit then r/w-blocks-finish
+ false r/w-blocks-start if -1 exit then r/w-blocks-finish
;
: r/w-ioblocks ( reg# function# inc? addr len blksz in? -- actual )
@@ -1010,6 +1038,17 @@
swap 0 -rot do 2* i csdbit or -1 +loop
;
+\ Decoder for the result of ACMD13 - app-get-status
+: sdstatbit ( bit# -- b )
+ d# 511 swap - ( bit#' )
+ dup 3 rshift scratch-buf + c@ ( bit-offset byte )
+ swap 7 and 7 xor rshift 1 and
+;
+: sdstatbits ( high low -- bits )
+ swap 0 -rot do 2* i sdstatbit or -1 +loop
+;
+
+
\ The calculation below is shown on page 81 of the
\ SD Physical Layer Simplified Specification Version 2.00.
: size ( -- d.bytes )
Modified: dev/mmc/sdhci/sdmmc.fth
==============================================================================
--- dev/mmc/sdhci/sdmmc.fth Sat Feb 13 06:52:26 2010 (r1739)
+++ dev/mmc/sdhci/sdmmc.fth Sat Feb 13 06:58:02 2010 (r1740)
@@ -15,7 +15,7 @@
\ block or record oriented, but the OBP external interface is byte-oriented,
\ in order to be independent of particular device block sizes.
-0 instance value deblocker
+0 value deblocker
external
@@ -31,11 +31,15 @@
false " r/w-blocks" $call-parent
;
+: erase-blocks ( block# #blocks -- )
+ " erase-blocks" $call-parent
+;
+
\ Asynchronous write. Completes on the next call to
\ write-blocks-start, write-blocks-finish, or close.
\ (Don't do other read/write operations in between.)
: write-blocks-start ( adr block# #blocks -- error? )
- false " r/w-blocks-start" $call-parent
+ " fresh-write-blocks-start" $call-parent
;
: write-blocks-end ( -- error? )
false " r/w-blocks-end" $call-parent
@@ -48,33 +52,43 @@
: dma-free ( vadr size -- ) " dma-free" $call-parent ;
: set-unit ( -- ) 0 my-unit " set-address" $call-parent ;
+
+0 value open-count
: open ( -- )
set-unit
- " attach-card" $call-parent 0= if false exit then
+ open-count 0= if
+ " attach-card" $call-parent 0= if false exit then
- " " " deblocker" $open-package ?dup if
- to deblocker
- else
- ." Can't open deblocker package" cr
- false exit
+ " " " deblocker" $open-package to deblocker
+ deblocker 0= if
+ ." Can't open deblocker package" cr
+ false exit
+ then
then
- my-args " disk-label" $open-package ?dup if ( ihandle )
- to label-package
+ my-args " disk-label" $open-package to label-package
+ label-package if
0 0 " offset" label-package $call-method to offset-high to offset-low
else
." Can't open disk label package" cr
- deblocker close-package false exit
+ open-count 0= if
+ deblocker close-package
+ then
+ false exit
then
+ open-count 1+ to open-count
true
;
: close ( -- )
- label-package close-package
- deblocker close-package
- \ Close packages first in case of delayed write flush
- " detach-card" $call-parent
+ open-count dup 1- to open-count ( prev-open-count )
+ label-package close-package ( prev-open-count )
+ 1 = if ( )
+ deblocker close-package ( )
+ \ Close packages first in case of delayed write flush
+ " detach-card" $call-parent ( )
+ then ( )
;
: block-size ( -- n ) h# 200 ;
More information about the openfirmware
mailing list