[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