[openfirmware] [commit] r3206 - dev/mmc/sdhci

repository service svn at openfirmware.info
Mon Aug 20 23:53:06 CEST 2012


Author: wmb
Date: Mon Aug 20 23:53:06 2012
New Revision: 3206
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/3206

Log:
SDHCI - handle host controllers that spuriously set the transfer interrupt bit during cmd13.

Modified:
   dev/mmc/sdhci/sdhci.fth

Modified: dev/mmc/sdhci/sdhci.fth
==============================================================================
--- dev/mmc/sdhci/sdhci.fth	Mon Aug 20 12:37:59 2012	(r3205)
+++ dev/mmc/sdhci/sdhci.fth	Mon Aug 20 23:53:06 2012	(r3206)
@@ -92,10 +92,16 @@
 \ hardware has a bug that blocks the card detection status bits
 \ unless the interrupt enables are on.
 0 instance value intstat-count
+: xfer-int-on  ( -- )  h# 34 cw@  2 or  h# 34 cw!  ;
+: xfer-int-off ( -- )  h# 34 cw@  2 invert and  h# 34 cw!  ;
+
 : intstat-on  ( -- )
    intstat-count 0=  if
-      h# 00cb h# 34 cw!  \ normal interrupt status en reg
-      \ Enable: Remove, Insert, DMA Interrupt, Transfer Complete, CMD Complete
+      \ Enable: Remove, Insert, DMA Interrupt, CMD Complete
+      \ Transfer complete is handled separately because some host controllers
+      \ (e.g. Marvell MMP3) set it spuriously during commands that shouldn't set it.
+      h# 00c9 h# 34 cw!  \ normal interrupt status en reg
+
       \ Disable: Card Interrupt, Read Ready, Write Ready, Block Gap
       h# f1ff h# 36 cw!  \ error interrupt status en reg
    then
@@ -218,6 +224,7 @@
    true  " dma-map-in" $call-parent  ( padr )        \ Prepare DMA buffer
    dup to dma-padr                   ( padr )        \ Remember for later
    0 cl!                                             \ Set address
+   xfer-int-on
 ;
 
 : dma-setup  ( #blocks adr -- )
@@ -374,6 +381,10 @@
 
 : cmd  ( arg cmd mode -- )
    debug?  if  ." CMD: " over 4 u.r space   then
+
+   \ R1B-class commands have an implied data transfer phase
+   over h# ff and  h# 1b  =  if  xfer-int-on  then
+
    over add-cmd
    wait-ready
    h# c cw!              ( arg cmd )  \ Mode
@@ -451,6 +462,7 @@
 : mmc-switch  ( arg -- )    \ CMD6 for MMC - no data
    h# 061b 0 cmd  response  h# 80 and  if  ." MMC SWITCH_ERROR" cr  then
    2 wait  \ This command appears to have a transfer-complete
+   xfer-int-off
 ;
 
 : deselect-card  ( -- )   0   h# 0700 0 cmd  ;  \ CMD7 - with null RCA
@@ -461,6 +473,7 @@
    \ commands, so we must clear that bit if it is set.
    d# 16 ms   \ Give the operation time to complete
    isr@ isr!
+   xfer-int-off
 ;
 
 : send-if-cond  ( -- )  h# 1aa h# 081a 0 cmd  ( response h# 1aa <>  if  ." Error"  then )   ;  \ CMD8 R7 (SD)
@@ -1063,12 +1076,9 @@
    then      
 ;
 
-: wait-dat  ( -- )  d# 10 ms  begin  2 ms present-state@  4 and  0= until  ;
-
 \ Wait for completion
 : r/w-blocks-end  ( in? -- error? )
    drop
-   wait-dat
    wait-dma-done
    intstat-on  wait-write-done  intstat-off
 ;
@@ -1080,11 +1090,18 @@
 
 : r/w-blocks-start  ( addr block# #blocks in? fresh? -- error? )
    wait-dma-done    ( addr block# #blocks fresh? in? )
+
+   \ wait-write-done used to be after dma-setup in an attempt to overlap
+   \ work with waiting time, but that doesn't work now that dma-setup
+   \ enables transfer interrupts, which can happen spuriously during
+   \ wait-write-done on some host controllers.
+   wait-write-done  if  3drop  2drop true exit  then  ( 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> drop                           ( block# r: #blocks )
       r> issue-read                     ( )
@@ -1097,8 +1114,6 @@
    false                                ( error? )
 ;
 : fresh-write-blocks-start  ( addr block# #blocks -- error? )
-   intstat-on
-   wait-dat
    false true r/w-blocks-start
 ;
 



More information about the openfirmware mailing list