[OpenBIOS] r484 - dev/mmc/sdhci

svn at openbios.org svn at openbios.org
Mon Jul 23 08:51:55 CEST 2007


Author: wmb
Date: 2007-07-23 08:51:54 +0200 (Mon, 23 Jul 2007)
New Revision: 484

Modified:
   dev/mmc/sdhci/sdhci.fth
Log:
SDHCI: OLPC trac 1377 - added MMC support and prefixed error message with "SDHCI:"




Modified: dev/mmc/sdhci/sdhci.fth
===================================================================
--- dev/mmc/sdhci/sdhci.fth	2007-07-22 08:49:28 UTC (rev 483)
+++ dev/mmc/sdhci/sdhci.fth	2007-07-23 06:51:54 UTC (rev 484)
@@ -89,6 +89,7 @@
 ;
 
 0 instance value sd-clk
+0 instance value mmc?
 
 \ 1 is reset_all, 2 is reset CMD line, 4 is reset DAT line
 : sw-reset  ( mask -- )
@@ -138,6 +139,12 @@
 : card-clock-on   ( -- )  h# 2c cw@  4 or  h# 2c cw!  ;
 : card-clock-off  ( -- )  h# 2c cw@  4 invert and  h# 2c cw!  ;
 
+: card-clock-slow  ( -- )  \ Less than 400 kHz, for init
+   card-clock-off
+   h# 8003 h# 2c cw!   \ Set divisor to 2^128, leaving internal clock on
+   card-clock-on
+;
+
 : card-clock-25  ( -- )
    card-clock-off
    h# 103 h# 2c cw!   \ Set divisor to 2^1, leaving internal clock on
@@ -219,7 +226,7 @@
       dup 1 =  if  true to timeout?  2drop exit  then
    then                    ( isr esr )
 
-   ." Error: ISR = " swap u.
+   ." SDHCI: Error: ISR = " swap u.
    ." ESR = " dup u.  decode-esr
    ." Stopping" cr abort
    \      debug-me
@@ -242,7 +249,7 @@
    get-msecs d# 1000 +                    ( limit )
    begin    present-state@  1 and  while  ( limit )
       dup get-msecs - 0<  if
-         ." SDHCI command ready timeout" cr
+         ." SDHCI: command ready timeout" cr
          abort
       then
    repeat                                 ( limit )
@@ -283,7 +290,12 @@
 
 \ Store in the buffer in little-endian form
 : get-response136  ( buf -- )  \ 128 bits (16 bytes) of data.
-   h# 20  h# 10  do  i cl@ buf+!  4 +loop  drop
+\   h# 20  h# 10  do  i cl@ buf+!  4 +loop  drop
+    >r
+    h# 1c cl@  8 lshift  h# 1b cb@ or  r@ 0 la+ l!
+    h# 18 cl@  8 lshift  h# 17 cb@ or  r@ 1 la+ l!
+    h# 14 cl@  8 lshift  h# 13 cb@ or  r@ 2 la+ l!
+    h# 10 cl@  8 lshift                r> 3 la+ l!
 ;
 
 d# 64 instance buffer: scratch-buf
@@ -297,11 +309,14 @@
 
 : reset-card  ( -- )  0 0 0 cmd  0 to rca  ;  \ 0 -
 
+: send-op-cond  ( voltage-range -- ocr )  h# 0102 0 cmd  response  ; \ R3
+
 \ Get card ID; Result is in cid buffer
 : get-all-cids  ( -- )  0 h# 0209 0 cmd  cid get-response136  ;  \ 2 R2
 
 \ Get relative card address
-: get-rca  ( -- )  0 h# 031a 0 cmd  response  h# ffff0000 and  to rca  ; \ 3 R6
+: get-rca  ( -- )  0 h# 031a 0 cmd  response  h# ffff0000 and  to rca  ; \ 3 R6 - SD
+: set-rca  ( rca -- )  to rca  rca h# 031a 0 cmd  ; \ 3 R1 - MMC
 
 : set-dsr  ( -- )  0 h# 0400 0 cmd  ;  \ 4 - UNTESTED
 
@@ -317,8 +332,10 @@
 : deselect-card  ( -- )   0   h# 0700 0 cmd  ;  \ 7 - with null RCA
 : select-card    ( -- )   rca h# 071b 0 cmd  ;  \ 7 R1b
 
-: send-if-cond  ( -- )  h# 1aa h# 081a 0 cmd  ( response h# 1aa <>  if  ." Error"  then )   ;  \ 8 R7
+: send-if-cond  ( -- )  h# 1aa h# 081a 0 cmd  ( response h# 1aa <>  if  ." Error"  then )   ;  \ 8 R7 (SD)
 
+\ : send-ext-csd  ( adr -- )  0 h# 0812 0 cmd  ;  \ 8 R1 (MMC) Untested - requires data transfer
+
 \ Get Card-specific data
 : get-csd    ( -- )  rca  h# 0909 0 cmd  csd get-response136  ;  \ 9 R2
 : get-cid    ( -- )  rca  h# 0a09 0 cmd  cid get-response136  ;  \ 10 R2 UNTESTED
@@ -385,67 +402,114 @@
    scratch-buf
 ;
 
-\ Version 2 of the spec add CMD8.  Pre-v2 cards will time out on CMD8.
-: sd2?  ( -- flag )
-   true to allow-timeout?  false to timeout?
-   send-if-cond
-   false to allow-timeout?
+9 instance value address-shift
+h# 8010.0000 value oc-mode  \ Voltage settings, etc.
 
-   timeout? 0=
-;
+: wait-powered  ( -- error? )
+   false to mmc?
 
-0 instance value address-shift
-h# 8010.0000 value oc-mode  \ Voltage settings, etc.
+   9 to address-shift
 
-: wait-powered  ( -- ocr )
    d# 100 0  do
-      oc-mode set-oc         ( ocr )  \ acmd41
-      dup h# 8000.0000 and   ( card-powered-on? )
-      if  unloop exit  then
+
+      false to timeout?
+      mmc?  if
+         oc-mode send-op-cond   \ cmd2              ( ocr )
+         timeout?  if  drop true  unloop exit  then ( ocr )
+      else
+         oc-mode set-oc         \ acmd41            ( ocr )
+         timeout?  if  drop  true to mmc?  0  then  ( ocr )
+      then                                       ( ocr )
+
+      dup h# 8000.0000 and  if ( card-powered-on? )
+
+         \ Card Capacity Status bit - High Capacity cards are addressed
+         \ in blocks, so the block number does not have to be shifted.
+         \ Standard capacity cards are addressed in bytes, so the block
+         \ number must be left-shift by 9 (multiplied by 512).
+         h# 4000.0000 and  if  0 to address-shift  then
+
+         unloop false exit
+      then
       drop d# 10 ms
    loop                      ( )
-   ." Card didn't power up after 1 second" cr
+
+   ." SDHCI: Card didn't power up after 1 second" cr
    abort
 ;
 
-: set-operating-conditions  ( -- )
-   sd2?  if  h# 4030.0000  else  h# 0030.0000  then  to oc-mode
+: set-operating-conditions  ( -- error? )
+   false to mmc?
+   true to allow-timeout?
 
-   wait-powered
+   \ SD version 2 adds CMD3.  Pre-v2 cards will time out.
+   false to timeout?  send-if-cond      (  )
+   timeout?   if  h# 0030.0000  else  h# 4030.0000  then  to oc-mode
 
-   \ Card Capacity Status bit - High Capacity cards are addressed
-   \ in blocks, so the block number does not have to be shifted.
-   \ Standard capacity cards are addressed in bytes, so the block
-   \ number must be left-shift by 9 (multiplied by 512).
+   wait-powered  if  true exit  then
 
-   h# 4000.0000 and  if  0  else  9  then  to address-shift
+   false to allow-timeout?
+   false
 ;
 
-: configure-transfer  ( -- )
-   2 set-bus-width  \ acmd6 - bus width 4
-   4-bit
+: set-timeout  ( -- )
    \ The h# c below is supposed to be h# b, but there is a CaFe bug
    \ in which the timeout code is off by one, which makes the timeout
    \ be half the requested length.
    h# c data-timeout!   \ 2^24 / 48 MHz = 0.35 sec
-   /block set-blocklen  \ Cmd 16
 ;
 
-: ?high-speed  ( -- )
-   \ High speed didn't exist until SD spec version 1.10
-   \ The low nibble of the first byte of SCR data is 0 for v1.0 and v1.01,
-   \ 1 for v1.10, and 2 for v2.
-   get-scr c@  h# f and  0=  if  exit  then
+: configure-transfer  ( -- )
+   mmc?  if
+      1-bit
+      \ We don't support 4-bit mode for MMC yet
 
-   \ Ask if high-speed is supported
-   h# 00ff.fff1 switch-function d# 13 + c@  2  and  if
-      h# 80ff.fff1 switch-function drop   \ Perform the switch
-      \ Bump the host controller clock
-      host-high-speed  \ Changes the clock edge
-      card-clock-50
+      \ We don't support switching to high speed on MMC yet.
+      \ Doing so requires reading the EXT_CSD block
+   else
+      2 set-bus-width  \ acmd6 - bus width 4
+      4-bit
+      /block set-blocklen  \ Cmd 16
+
+      \ High speed didn't exist until SD spec version 1.10
+      \ The low nibble of the first byte of SCR data is 0 for v1.0 and v1.01,
+      \ 1 for v1.10, and 2 for v2.
+      get-scr c@  h# f and  0=  if  exit  then
+
+      \ Ask if high-speed is supported
+      h# 00ff.fff1 switch-function d# 13 + c@  2  and  if
+         h# 80ff.fff1 switch-function drop   \ Perform the switch
+         \ Bump the host controller clock
+         host-high-speed  \ Changes the clock edge
+         card-clock-50
+      else
+         card-clock-25
+      then
    then
 ;
 
+\ Extract bit fields from CSD or CID  (adr is either csd or cid)
+: @bits   ( bit# #bits adr -- bits )
+   rot 8 -                     ( #bits adr bit# )  \ -8 accounts for elided CRC
+   d# 32 /mod                  ( #bits adr off long#  )
+   /l* rot + >r                ( #bits off  r: ladr )
+   2dup + d# 32 >  if          ( #bits off  r: ladr )
+      \ Get two longs and splice
+      r@ l@ over rshift        ( #bits off l.low  r: ladr )
+      r> la1+ l@               ( #bits off l.low l.high )
+      rot  d# 32 swap -        ( #bits l.low l.high #shift )
+      lshift or                ( #bits l )
+   else                        ( #bits off  r: ladr )
+      \ The field is contained in one longword
+      r> l@  swap rshift       ( #bits l )
+   then                        ( #bits l )
+   swap dup d# 32 = if         ( l #bits )
+      drop                     ( bits )
+   else                        ( l #bits )
+      1 swap lshift 1-  and    ( bits )
+   then                        ( bits )
+;
+
 0 instance value writing?
 
 \ This is the correct way to wait for programming complete.
@@ -455,7 +519,7 @@
    get-msecs d# 1000 +                              ( limit )
    begin  get-status 9 rshift h# f and  7 =  while  ( limit )
       dup get-msecs - 0<  if
-         ." SDHCI wait-write-done timeout" cr
+         ." SDHCI: wait-write-done timeout" cr
          abort
       then
    repeat                                           ( limit )
@@ -473,20 +537,29 @@
 
    card-inserted?  0=  if  card-power-off  false exit  then   
 
-   card-clock-25  d# 10 ms  \ This delay is just a guess
+   card-clock-slow  d# 10 ms  \ This delay is just a guess
 
    reset-card     \ Cmd 0
 
-   ['] set-operating-conditions  catch  if  false exit  then
+   set-operating-conditions  if  false exit  then
 
    get-all-cids   \ Cmd 2
-   get-rca        \ Cmd 3 - Get relative card address
-   get-csd        \ Cmd 9 - Get card-specific data
-   select-card    \ Cmd 7 - Select
+   mmc?  if
+      h# 10000 set-rca   \ Cmd 3 (MMC) - Get relative card address
+   else
+      get-rca        \ Cmd 3 (SD) - Get relative card address
+   then
 
+   card-clock-25
+
+   get-csd           \ Cmd 9 - Get card-specific data
+
+   select-card       \ Cmd 7 - Select
+
    configure-transfer
-   ?high-speed
 
+   set-timeout
+
    true
 ;
 




More information about the OpenBIOS mailing list