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 ;