Author: wmb Date: Thu Sep 27 03:14:27 2012 New Revision: 3337 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/3337
Log: OLPC WLAN driver - Support both 8686 and 8787 WLAN modules from the same driver.
Modified: dev/libertas.fth dev/mmc/sdhci/mv8686/fw8686.fth dev/mmc/sdhci/mv8686/mv8686.fth dev/mmc/sdhci/mv8686/sdio.fth dev/mmc/sdhci/sdhci.fth dev/mmc/sdhci/slot.fth
Modified: dev/libertas.fth ============================================================================== --- dev/libertas.fth Thu Sep 27 03:12:32 2012 (r3336) +++ dev/libertas.fth Thu Sep 27 03:14:27 2012 (r3337) @@ -51,6 +51,7 @@
ds-not-ready value driver-state
+: driver-is-not-ready ( -- ) ds-not-ready to driver-state ; : set-driver-state ( bit-mask -- ) driver-state or to driver-state ; : reset-driver-state ( bit-mask -- ) invert driver-state and to driver-state ;
@@ -155,7 +156,7 @@ 2 field >fw-seq 2 field >fw-result dup constant /fw-cmd -dup 4 - constant /fw-cmd-hdr \ Command header len (less /fw-transport) +dup /fw-transport - constant /fw-cmd-hdr \ Command header len (less /fw-transport) 0 field >fw-data \ Command payload starts here drop
@@ -207,6 +208,22 @@ 0 field >tx-pkt constant /tx-hdr
+struct + /fw-transport + + 1 field >tx14-bsstype + 1 field >tx14-bss# + 2 field >tx14-len + 2 field >tx14-offset + 2 field >tx14-type + 4 field >tx14-ctrl + 1 field >tx14-priority + 1 field >tx14-pwr + 1 field >tx14-delay \ in 2ms + 1+ + 0 field >tx14-pkt +constant /tx14-hdr + + 0 constant tx-ctrl \ Tx rates, etc : set-tx-ctrl ( n -- ) to tx-ctrl ;
@@ -216,32 +233,47 @@
: mesh-on? ( -- flag ) tx-ctrl TX_WDS and 0<> ;
-: (wrap-msg-thin) ( adr len dst-mac-adr -- adr' len' ) - outbuf /tx-hdr erase ( adr len dst-mac-adr ) - outbuf >tx-mac /mac-adr move ( adr len ) +: wrap-802.11 ( adr len -- adr' len' ) + outbuf /tx-hdr erase ( adr len ) + over 4 + outbuf >tx-mac /mac-adr move ( adr len ) dup outbuf >tx-len le-w! ( adr len ) tuck outbuf >tx-pkt-no-mesh swap move ( len )
- /tx-hdr-no-mesh 4 - outbuf >tx-offset le-l! ( len ) \ Offset from >tx-ctrl field + /tx-hdr-no-mesh /fw-transport - outbuf >tx-offset le-l! ( len ) \ Offset from >tx-stat field tx-ctrl outbuf >tx-ctrl le-l! ( len )
outbuf swap /tx-hdr-no-mesh + ( adr' len' ) ; -: (wrap-msg) ( adr len dst-mac-adr -- adr' len' ) - outbuf /tx-hdr erase ( adr len dst-mac-adr ) - outbuf >tx-mac /mac-adr move ( adr len ) + +: wrap-v9 ( adr len -- adr' len' ) + outbuf /tx-hdr erase ( adr len ) + over outbuf >tx-mac /mac-adr move ( adr len ) dup outbuf >tx-len le-w! ( adr len ) tuck outbuf >tx-pkt swap move ( len )
- /tx-hdr 4 - outbuf >tx-offset le-l! ( len ) \ Offset from >tx-ctrl field + /tx-hdr /fw-transport - outbuf >tx-offset le-l! ( len ) \ Offset from >tx-stat field tx-ctrl outbuf >tx-ctrl le-l! ( len )
mesh-on? if 1 outbuf >tx-mesh-ttl c! then ( len )
outbuf swap /tx-hdr + ( adr' len' ) ; -: wrap-802.11 ( adr len -- adr' len' ) over 4 + (wrap-msg-thin) ; -: wrap-msg ( adr len -- adr' len' ) over (wrap-msg) ; + +: wrap-v14 ( adr len -- adr' len' ) + \ Erasing sets the following fields to 0: + \ >tx14-bsstype (0=STA), >tx14-bss# (BSS#=0), >tx14-type (0=802.3) + \ >tx14-pri (PRI=0), >tx14-flags, >tx14-delay + outbuf /tx14-hdr erase ( adr len ) + + dup outbuf >tx14-len le-w! ( adr len ) + tuck outbuf >tx14-pkt swap move ( len ) + + /tx14-hdr /fw-transport - outbuf >tx14-offset le-w! ( len ) \ Offset from >tx14-bsstype field + tx-ctrl outbuf >tx14-ctrl le-l! ( len ) + + outbuf swap /tx14-hdr + ( adr' len' ) +; +instance defer wrap-ethernet
\ ========================================================================= \ Receive Packet Descriptor @@ -275,6 +307,24 @@ d# 22 + \ Size of an Ethernet header with SNAP constant /rx-min
+struct + /fw-transport + + 1 field >rx14-bsstype + 1 field >rx14-bss# + 2 field >rx14-len + 2 field >rx14-offset + 2 field >rx14-type \ 2:ethernet 3:802.3 w/ LLC+SNAP 5:802.11 e6:AMSDU e7:BAR ef:debug + 2 field >rx14-seq + 1 field >rx14-pri + 1 field >rx14-rate + 1 field >rx14-snr + 1 field >rx14-nf + 1 field >rx14-ht + 1 + +\ d# 14 + \ Size of an Ethernet header +\ d# 22 + \ Size of an Ethernet header with SNAP +constant /rx14-min + \ >rx-stat constants 1 constant rx-stat-ok 2 constant rx-stat-multicast @@ -297,11 +347,16 @@ drop ;
-: unwrap-pkt ( adr len -- data-adr data-len ) - /rx-min < if drop 0 0 then \ Invalid packet: too small +: unwrap-v9 ( adr len -- data-adr data-len false | true ) + over .rx-desc ( adr len ) + over >rx-stat le-w@ rx-stat-ok <> if ( adr len ) + 2drop true exit ( -- true ) + then ( adr len ) + + /rx-min < if drop true exit then ( adr ) \ Invalid packet: too small
\ Go to the payload, skipping the descriptor header - dup dup >rx-offset le-l@ + la1+ ( adr data-adr ) + dup dup >rx-offset le-l@ + /fw-transport + ( adr data-adr ) swap >rx-len le-w@ ( data-adr data-len )
\ Remove snap header by moving the MAC addresses up @@ -310,15 +365,39 @@ over dup 8 + d# 12 move ( data-adr data-len ) 8 /string ( adr' len' ) then + false +; +: unwrap-v14 ( adr len -- data-adr data-len ) + /rx14-min < if drop true exit then ( adr ) \ Invalid packet: too small + + \ Go to the payload, skipping the descriptor header + >r ( r: adr ) + r@ r@ >rx14-offset le-w@ + /fw-transport + ( data-adr r: adr ) + r@ >rx14-len le-w@ ( data-adr data-len r: adr ) + + r> >rx14-type c@ case ( data-adr data-len ) + 2 of endof \ Ethernet ( data-adr data-len ) + 3 of \ 802.3 with LLC + SNAP ( data-adr data-len ) + \ Remove snap header by moving the MAC addresses up + \ That's faster than moving the contents down + over d# 14 + snap-header comp 0= if ( data-adr data-len ) + over dup 8 + d# 12 move ( data-adr data-len ) + 8 /string ( adr' len' ) + then + endof + ( default ) ( adr len type ) + ." libertas.fth: Frame type not supported" cr + 3drop true exit + endcase + false ; +instance defer unwrap-ethernet
: process-data ( adr len -- ) 2dup vdump ( adr len ) - over .rx-desc ( adr len ) - - over >rx-stat le-w@ rx-stat-ok <> if 2drop exit then
- unwrap-pkt to /data to data ( ) + unwrap-ethernet if exit then ( adr' len' ) + to /data to data ( )
true to got-data? \ do-process-eapol may unset this
@@ -407,6 +486,8 @@ 0076 of ." CMD_802_11_RATE_ADAPT_RATESET" endof 007f of ." CMD_TX_RATE_QUERY" endof 00a5 of ." CMD_SET_BOOT2_VER" endof \ Thin firmware only + 00a9 of ." CMD_FUNC_INIT" endof \ Multifunction versions + 00aa of ." CMD_FUNC_SHUTDOWN" endof 00b0 of ." CMD_802_11_BEACON_CTRL" endof \ Thin firmware only 00cb of ." CMD_802_11_BEACON_SET" endof \ Thin firmware only 00cc of ." CMD_802_11_SET_MODE" endof \ Thin firmware only @@ -483,12 +564,15 @@ h# 0e of " Unicast MIC error" .event process-pmic-failure endof h# 0e of " WM awake" .event endof \ n h# 11 of " HWAC - adhoc BCN lost" .event endof + h# 17 of endof \ Suppress: " WMM status change" .event endof \ XXX supposed to issue CMD_WMM_GET_STATUS h# 19 of " RSSI low" .event endof h# 1a of " SNR low" .event endof h# 1b of " Max fail" .event endof h# 1c of " RSSI high" .event endof h# 1d of " SNR high" .event endof h# 23 of endof \ Suppress this; the user doesn't need to see it + h# 2b of endof \ Suppress this; the user doesn't need to see it +\ h# 2b of " Port release" .event endof \ h# 23 of ." Mesh auto-started" endof h# 30 of endof \ Handle this silently \ h# 30 of " Firmware ready" .event endof @@ -515,7 +599,7 @@
: check-for-rx ( -- ) got-packet? if ( error | buf len 0 ) - 0= if process-rx then ( ) + 0= if 2dup vdump process-rx then ( ) recycle-packet ( ) then ( ) ; @@ -603,13 +687,13 @@
: reset-wlan ( -- ) " wlan-reset" evaluate - ds-not-ready to driver-state + driver-is-not-ready reset-host-bus ; : sleep ( -- ) reset-wlan ; : wake ( -- ) ;
-: marvel-get-hw-spec ( -- true | adr false ) +: get-hw-spec ( -- true | adr false ) d# 38 h# 03 ( CMD_GET_HW_SPEC ) prepare-cmd outbuf-out ?dup if true exit then resp-wait-tiny to resp-wait @@ -618,13 +702,37 @@ respbuf >fw-data false ;
-\ The purpose of this is to work around a problem that I don't fully understand. -\ For some reason, when you reopen the device without re-downloading the -\ firmware, the first command silently fails - you don't get a response. -\ This is a "throwaway" command to handle that case without a long timeout -\ or a warning message. +: set-fw-params ( -- ) + get-hw-spec 0= if ( adr ) + + \ The 4-byte FWReleaseNumber field starts at offset d# 18. + \ Firmware version 2.3.4.p1 is represented in that field + \ as 04 03 02 01, i.e. the first three bytes are little-endian, + \ and the final byte is the "p-number". The "MSB" at offset + \ d# 20 reflects the major version number, corresponding to + \ the "v-number" of the firmware interface document. + + d# 20 + c@ d# 14 >= if + ['] wrap-v14 to wrap-ethernet + ['] unwrap-v14 to unwrap-ethernet + else + ['] wrap-v9 to wrap-ethernet + ['] unwrap-v9 to unwrap-ethernet + then + then +; + +\ This is necessary for multifunction devices like 8688 and 8787 that have +\ extra functions like BlueTooth in addition to WiFi +: init-function ( -- ) + 0 h# a9 ( CMD_FUNC_INIT ) prepare-cmd + outbuf-wait if exit then +;
-: nonce-cmd ( -- ) marvel-get-hw-spec 0= if drop then ; +: shutdown-function ( -- ) + 0 h# aa ( CMD_FUNC_SHUTDOWN ) prepare-cmd + outbuf-wait if exit then +;
\ ========================================================================= \ MAC address @@ -870,6 +978,14 @@ : mac-off ( -- ) 0 to mac-ctrl set-mac-control 3 to mac-ctrl ; + +: reconfig-tx-buffer ( bufsize -- ) \ mwifiex + 3 h# d9 ( RECONFIGURE_TX_BUFF ) prepare-cmd + ACTION_SET +xw + ( bufsize ) +xw + outbuf-wait drop +; + headers
\ ========================================================================= @@ -1661,7 +1777,7 @@
\ This is a heavy-handed way to force the device back into baseline state \ The recipe above is nicer. -\ ds-not-ready to driver-state \ Forces firmware reload on next open +\ driver-is-not-ready \ Forces firmware reload on next open \ reset-host-bus \ Primes module to accept new firmware \ false to ap-mode? ; @@ -1711,8 +1827,8 @@ ;
: .hw-spec ( -- ) - marvel-get-hw-spec if - ." marvel-get-hw-spec command failed" cr + get-hw-spec if + ." get-hw-spec command failed" cr else ." HW interface version: " dup le-w@ u. cr ." HW version: " dup 2 + le-w@ u. cr @@ -1901,6 +2017,7 @@ then ds-ready to driver-state then + multifunction? if init-function then ?make-mac-address-property ;
@@ -1932,11 +2049,12 @@ " " set-ssid \ Instance buffers aren't necessarily initially 0 opencount @ 0= if init-buf + driver-is-not-ready /inbuf /outbuf setup-bus-io if free-buf false exit then ?load-fw if release-bus-resources free-buf false exit then + set-fw-params my-args " supplicant" $open-package to supplicant-ih supplicant-ih 0= if release-bus-resources free-buf false exit then - nonce-cmd force-open? if ds-disconnected reset-driver-state else @@ -1965,7 +2083,9 @@ stop-nic mac-off supplicant-ih ?dup if close-package 0 to supplicant-ih then + multifunction? if shutdown-function then release-bus-resources + driver-is-not-ready then ;
@@ -1973,7 +2093,7 @@ \ Used by the /supplicant support package to perform key handshaking. : write-force ( adr len -- actual ) tuck ( actual adr len ) - wrap-msg ( actual adr' len' ) + wrap-ethernet ( actual adr' len' ) data-out ( actual ) ;
Modified: dev/mmc/sdhci/mv8686/fw8686.fth ============================================================================== --- dev/mmc/sdhci/mv8686/fw8686.fth Thu Sep 27 03:12:32 2012 (r3336) +++ dev/mmc/sdhci/mv8686/fw8686.fth Thu Sep 27 03:14:27 2012 (r3337) @@ -1,4 +1,4 @@ -purpose: Marvel 8686 firmware loader +purpose: Marvel SDIO WLAN module firmware loader \ See license at end of file
@@ -21,10 +21,7 @@ 0 value fw-tx-len 0 value dn-retry
-: fw-dn-blksz ( -- blksz ) - h# 10 1 sdio-reg@ - h# 11 1 sdio-reg@ bwjoin -; +: fw-dn-blksz ( -- blksz ) host-f1-rd-base-0-reg 1 sdio-reg-w@ ; : wait-for-fw-dn-blksz ( -- blksz ) \ Wait for the first non-zero value d# 5000 0 do fw-dn-blksz dup ?leave drop loop @@ -33,7 +30,7 @@
: fw-download-ok? ( -- flag ) false d# 100 0 do - sdio-scratch@ FIRMWARE_READY = if drop true leave then + sdio-fw-status@ FIRMWARE_READY = if drop true leave then d# 10 ms loop ; @@ -46,7 +43,7 @@ fw-len dn-idx - fw-tx-len min ( len ) fw-adr dn-idx + outbuf 2 pick move ( len ) outbuf over sdio-fw! <> if - 4 3 1 sdio-reg! \ FN1 CFG = write iomem fail + 4 config-reg 1 sdio-reg! \ FN1 CFG = write iomem fail then sdio-poll-dl-ready 0= if ." Download fw died" cr true exit then fw-dn-blksz ?dup 0= if false exit then @@ -65,7 +62,7 @@ : fw-image-ok? ( adr len -- flag ) 2drop true ;
: download-fw ( adr len -- error? ) - 2dup fw-image-ok? 0= if ." Bad WLAN firmware image" cr true exit then + 2dup fw-image-ok? 0= if ." Bad WLAN firmware image" cr true exit then ( adr len )
wait-for-fw-dn-blksz ?dup 0= if ." Failed to get firmware download block size" cr 2drop true exit then @@ -75,7 +72,10 @@
fw-download-ok? 0= if true exit then
- 3 4 1 sdio-reg! \ Enable host interrupt mask + 3 host-int-mask-reg 1 sdio-reg! \ Enable upload (1) and download (2) + mv8787? if + 2 config-reg 1 sdio-reg! \ Host power up + then false ;
@@ -97,26 +97,30 @@ ;
: download-helper ( adr len -- error? ) - sdio-scratch@ FIRMWARE_READY = if " Firmware downloaded" vtype 2drop true exit then + sdio-fw-status@ FIRMWARE_READY = if " Firmware downloaded" vtype 2drop true exit then 2dup fw-image-ok? 0= if ." Bad WLAN helper image" cr true exit then (download-helper) ;
-: load-8686-fw ( -- error? ) - wlan-helper find-fw dup if ( adr len ) - download-helper if true exit then - else ( adr len ) - 2drop ( ) - then ( ) +: load-sdio-fw ( -- error? ) + helper? if + wlan-helper find-fw dup if ( adr len ) + 2dup download-helper ( adr len error? ) + -rot free-mem ( error? ) + if true exit then ( ) + else ( adr len ) + 2drop ( ) + then ( ) + then
wlan-fw find-fw dup if ( adr len ) - download-fw ( error? ) + 2dup download-fw ( adr len error? ) + -rot free-mem ( error? ) else ( adr len ) - 2drop false ( error? ) + 2drop true ( error? ) then ( error? ) ; -' load-8686-fw to load-all-fw - +' load-sdio-fw to load-all-fw
\ LICENSE_BEGIN \ Copyright (c) 2007 FirmWorks
Modified: dev/mmc/sdhci/mv8686/mv8686.fth ============================================================================== --- dev/mmc/sdhci/mv8686/mv8686.fth Thu Sep 27 03:12:32 2012 (r3336) +++ dev/mmc/sdhci/mv8686/mv8686.fth Thu Sep 27 03:14:27 2012 (r3337) @@ -4,12 +4,6 @@ headers hex
-" mv8686" encode-string " module-type" property - -\ This really depends on the firmware that we load, but we don't want -\ to load the firmware in advance, so we hardcode this, assuming that -\ the firmware we include with OFW has both thin and fullmac capability. -0 0 encode-bytes " thin" property 0 0 encode-bytes " fullmac" property
\ ======================================================================= @@ -19,7 +13,7 @@ \ =======================================================================
: wlan-fw ( -- $ ) - " wlan-fw" " $getenv" evaluate if " rom:sd8686.bin" then + " wlan-fw" " $getenv" evaluate if default-fw$ then ; : wlan-helper ( -- $ ) " wlan-helper" " $getenv" evaluate if " rom:helper_sd.bin" then @@ -76,11 +70,8 @@
: release-bus-resources ( -- ) drain-queue detach-card ;
-0 value card-attached? - : ?attach-card ( -- ok? ) - card-attached? if true exit then - attach-card dup to card-attached? ( ok? ) + attach-card if set-version 0= else false then ;
: make-my-properties ( -- ) @@ -91,13 +82,13 @@ : setup-bus-io ( /inbuf /outbuf -- error? ) 2drop init-queue - ?attach-card 0= if ." Fail to attach card" cr true exit then + ?attach-card 0= if ." Failed to attach card" cr true exit then make-my-properties init-device false ;
-: reset-host-bus ( -- ) false to card-attached? ; +: reset-host-bus ( -- ) ;
\ LICENSE_BEGIN \ Copyright (c) 2009 FirmWorks
Modified: dev/mmc/sdhci/mv8686/sdio.fth ============================================================================== --- dev/mmc/sdhci/mv8686/sdio.fth Thu Sep 27 03:12:32 2012 (r3336) +++ dev/mmc/sdhci/mv8686/sdio.fth Thu Sep 27 03:14:27 2012 (r3337) @@ -4,97 +4,252 @@ hex headers
-0 value ioport -d# 320 constant blksz \ Block size for data tx/rx -d# 32 constant fw-blksz +: sdio-reg@ ( reg# function# -- value ) " sdio-reg@" $call-parent ; +: sdio-reg! ( value reg# function# -- ) " sdio-reg!" $call-parent ; +: sdio-reg-w@ ( reg# function# -- w.value ) + 2dup sdio-reg@ -rot ( low reg# function# ) + swap 1+ swap sdio-reg@ ( low high ) + bwjoin ( w.value ) +; +: sdio-w@ ( reg# -- w.value ) 1 sdio-reg-w@ ; + +false instance value multifunction? +false instance value helper? +false instance value mv8787? +instance defer rx-ready? ( -- len ) +instance defer get-ctrl-port ( -- port# ) +instance defer get-write-port ( -- port# )
-: roundup-blksz ( n -- n' ) blksz 1- + blksz / blksz * ; +0 0 2value default-fw$
-: set-address ( rca slot -- ) " set-address" $call-parent ; -: get-address ( -- rca ) " get-address" $call-parent ; -: attach-card ( -- ok? ) " attach-sdio-card" $call-parent ; -: detach-card ( -- ) " detach-sdio-card" $call-parent ; +0 value ioport +d# 256 constant blksz \ Block size for data tx/rx +d# 256 constant fw-blksz
-\ The following are CMD52 (SDIO) variants -\ Flags: 80:CRC_ERROR 40:ILLEGAL_COMMAND 30:IO_STATE (see spec) -\ 08:ERROR 04:reserved 02:INVALID_FUNCTION# 01:OUT_OF_RANGE - -h# cf constant SDIO_FLAG_MASK - -: .io-state ( flags & 30 -- ) - case - h# 00 of ." card disabled; " endof - h# 10 of ." CMD state; " endof - h# 20 of ." data transfer; " endof - h# 30 of ." reserved; " endof - endcase -; -: .sdio-flags ( flags -- ) - dup SDIO_FLAG_MASK and 0= if drop exit then - ." IO_RW_DIRECT response = " - dup h# 80 and if ." CRC error; " then - dup h# 40 and if ." illegal command; " then - dup h# 30 and .io-state - dup h# 08 and if ." error; " then - dup h# 02 and if ." invalid function; " then - dup h# 01 and if ." argument out of range" then - cr +h# 0 constant config-reg +h# 1 constant host-int-rsr-reg +h# 2 constant host-int-mask-reg +h# 3 constant host-intstatus-reg + +h# 4 constant rd-bitmap-reg +h# 6 constant wr-bitmap-reg +h# 8 constant rd-len-reg + +\ h# 20 constant host-f1-card-rdy-reg +\ h# 28 constant host-int-status-reg +h# 30 constant card-status-reg +h# 34 constant interrupt-mask-reg +\ h# 38 constant interrupt-status-reg +\ h# 3c constant interrupt-rsr-reg +h# 40 constant host-f1-rd-base-0-reg +\ h# 41 constant host-f1-rd-base-1-reg +h# 6c constant card-misc-cfg-reg +h# 60 constant card-fw-status0-reg +\ h# 61 constant card-fw-status1-reg +\ h# 62 constant card-rx-len-reg +\ h# 63 constant card-rx-unit-reg +h# 78 constant ioport-reg + +: ?set-module-property ( adr len -- ) + " module-type" get-my-property if ( adr len ) + encode-string " module-type" property ( ) + else ( adr len prop$ ) + 2drop 2drop + then ;
-: sdio-reg@ ( reg# function# -- value ) - " io-b@" $call-parent .sdio-flags +: sdio-fw-status@ ( -- n ) + card-fw-status0-reg sdio-w@ ;
-: sdio-reg! ( value reg# function# -- ) - " io-b!" $call-parent .sdio-flags +: mv8686-rx-ready? ( -- len ) + host-intstatus-reg 1 sdio-reg@ + dup 0= if exit then + dup invert 3 and host-intstatus-reg 1 sdio-reg! \ Clear UP_LD bit + 1 and if + sdio-fw-status@ + else + 0 + then ;
-: sdio-reg!@ ( value reg# function# -- value' ) - " io-b!@" $call-parent .sdio-flags +: use-mv8686 ( -- ) + h# 3 to config-reg + h# 4 to host-int-mask-reg + h# 5 to host-intstatus-reg + h# 20 to card-status-reg + h# 10 to host-f1-rd-base-0-reg + h# 34 to card-fw-status0-reg + h# 00 to ioport-reg + d# 320 to blksz + d# 32 to fw-blksz + false to mv8787? + false to multifunction? + true to helper? + ['] mv8686-rx-ready? to rx-ready? + ['] 0 to get-ctrl-port + ['] 0 to get-write-port + + " rom:sd8686.bin" to default-fw$ + " mv8686" ?set-module-property + + \ This really depends on the firmware that we load, but we don't want + \ to load the firmware in advance, so we hardcode this, assuming that + \ the firmware we include with OFW has both thin and fullmac capability. + " thin" get-my-property if + 0 0 encode-bytes " thin" property + else + 2drop + then +; +0 instance value rx-port# +0 instance value wr-bitmap +0 instance value rd-bitmap +: update-bitmaps ( -- ) + host-intstatus-reg 1 sdio-reg@ + dup 2 and if wr-bitmap-reg sdio-w@ to wr-bitmap then + 1 and if rd-bitmap-reg sdio-w@ to rd-bitmap then +; +: mv8787-rx-ready? ( -- len ) + rd-bitmap dup if ( bitmap ) + d# 16 0 do ( bitmap ) + dup 1 and if ( bitmap ) + drop i leave ( port# ) + then ( bitmap ) + 2/ ( bitmap' ) + loop ( port# ) + 1 over lshift invert rd-bitmap and to rd-bitmap ( port# ) + dup to rx-port# ( port# ) + 2* rd-len-reg + sdio-w@ ( len ) + else ( 0 ) + update-bitmaps ( 0 ) + then ;
-: sdio-scratch@ ( -- value ) - h# 34 1 sdio-reg@ ( lo ) - h# 35 1 sdio-reg@ ( lo hi ) - bwjoin ( value ) +: mv8787-get-ctrl-port ( -- n ) + 0 +; +: next-wr-port ( -- n ) + wr-bitmap 2/ ( bits ) + dup 0= if exit then ( bits ) + d# 16 1 do ( bits ) + dup 1 and if ( bits ) + drop ( ) + wr-bitmap 1 i lshift invert and to wr-bitmap + i leave ( n ) + then ( bits ) + 2/ ( bits' ) + loop ( n ) +; + +: mv8787-get-write-port ( -- n ) + begin next-wr-port ?dup 0= while ( ) + update-bitmaps ( ) + repeat ( n ) +; + +: use-mv8787 ( -- ) + h# 0 to config-reg + h# 1 to host-int-rsr-reg + h# 2 to host-int-mask-reg + h# 3 to host-intstatus-reg +\ h# 20 to host-f1-card-rdy-reg +\ h# 28 to host-restart-reg + h# 30 to card-status-reg + h# 34 to interrupt-mask-reg +\ h# 38 to interrupt-status-reg +\ h# 3c to interrupt-rsr-reg + h# 40 to host-f1-rd-base-0-reg +\ h# 41 to host-f1-rd-base-1-reg + h# 6c to card-misc-cfg-reg + h# 60 to card-fw-status0-reg +\ h# 61 to card-fw-status1-reg +\ h# 62 to card-rx-len-reg +\ h# 63 to card-rx-unit-reg + h# 78 to ioport-reg + d# 256 to blksz + d# 256 to fw-blksz + true to mv8787? + ['] mv8787-rx-ready? to rx-ready? + ['] mv8787-get-ctrl-port to get-ctrl-port + ['] mv8787-get-write-port to get-write-port + " rom:mv8787.bin" to default-fw$ + " mv8787" ?set-module-property + false to helper? + true to multifunction? +; + +: set-version ( -- error? ) + " sdio-card-id" $call-parent case + h# 02df9103 of use-mv8686 false endof + h# 02df9118 of use-mv8787 false endof + ( default ) + ." Unsupported SDIO card ID " dup . cr + true swap + endcase ;
+: roundup-blksz ( n -- n' ) blksz 1- + blksz / blksz * ; + +: set-address ( rca slot -- ) " set-address" $call-parent ; +: get-address ( -- rca ) " get-address" $call-parent ; +: attach-card ( -- ok? ) " attach-sdio-card" $call-parent ; +: detach-card ( -- ) " detach-sdio-card" $call-parent ; + : sdio-poll-dl-ready ( -- ready? ) false d# 100 0 do - h# 20 1 sdio-reg@ \ card status register + card-status-reg 1 sdio-reg@ h# 9 tuck and = if drop true leave then d# 100 usec loop dup 0= if ." sdio-poll-dl-ready failed" cr then ;
-: sdio-blocks@ ( adr len -- actual ) - >r >r - ioport 1 true r> r> blksz true " r/w-ioblocks" $call-parent ( actual ) +: sdio-fw! ( adr len -- actual ) + >r >r ioport 1 true r> r> fw-blksz false " r/w-ioblocks" $call-parent ;
-: sdio-blocks! ( adr len -- actual ) - >r >r ioport 1 true r> r> blksz false " r/w-ioblocks" $call-parent -; +: init-device ( -- ) + ioport-reg 3 bounds do i 1 sdio-reg@ loop \ Read the IO port + 0 bljoin to ioport
-: packet-out ( adr len -- error? ) tuck sdio-blocks! <> ; -: packet-out-async ( adr len -- ) sdio-blocks! drop ; + 7 0 sdio-reg@ h# 20 or 7 0 sdio-reg! \ Enable async interrupt mode
-: sdio-fw! ( adr len -- actual ) - >r >r ioport 1 true r> r> fw-blksz false " r/w-ioblocks" $call-parent -; + 2 2 0 sdio-reg! \ Enable IO function 1 (2 = 1 << 1) + 3 4 0 sdio-reg! \ Enable interrupts (1) for function 1 (1 << 1)
-: rx-ready? ( -- len ) - 5 1 sdio-reg@ \ Read interrupt status reg - dup 0= if exit then - dup invert 3 and 5 1 sdio-reg! \ Clear UP_LD bit - 1 and if - sdio-scratch@ \ Read payload length - else - 0 + mv8787? if + \ Set host interrupt reset to "read to clear" + host-int-rsr-reg 1 sdio-reg@ h# 3f or host-int-rsr-reg 1 sdio-reg! + +\ 3 host-int-mask-reg 1 sdio-reg! \ Enable upload (1) and download (2) + + \ Set Dnld/upld to "auto reset" + card-misc-cfg-reg 1 sdio-reg@ h# 10 or card-misc-cfg-reg 1 sdio-reg! then ;
+: sdio-blocks@ ( adr len -- actual ) + >r >r + rx-port# ioport + 1 true r> r> blksz true " r/w-ioblocks" $call-parent ( actual ) +; + +\ : sdio-blocks! ( adr len -- actual ) +\ >r >r x-get-write-port ioport + 1 true r> r> blksz false " r/w-ioblocks" $call-parent +\ ; + +\ 1 is the function number +: (sdio-blocks!) ( adr len port# -- actual ) + ioport + -rot ( port# adr len ) + 1 true 2swap ( port# function# inc? adr len ) + blksz false " r/w-ioblocks" $call-parent +; + +\ 0 is the control port number +: packet-out ( adr len -- error? ) tuck get-ctrl-port (sdio-blocks!) <> ; + +: packet-out-async ( adr len -- ) get-write-port (sdio-blocks!) drop ; + : read-poll ( -- ) begin rx-ready? ?dup while ( len ) new-buffer ( handle adr len ) @@ -103,15 +258,6 @@ repeat ;
-: init-device ( -- ) - 3 0 do i 1 sdio-reg@ loop \ Read the IO port - 0 bljoin to ioport - - 7 0 sdio-reg@ h# 20 or 7 0 sdio-reg! \ Enable async interrupt mode - - 2 2 0 sdio-reg! \ Enable IO function - 3 4 0 sdio-reg! \ Enable interrupts -;
headers
Modified: dev/mmc/sdhci/sdhci.fth ============================================================================== --- dev/mmc/sdhci/sdhci.fth Thu Sep 27 03:12:32 2012 (r3336) +++ dev/mmc/sdhci/sdhci.fth Thu Sep 27 03:14:27 2012 (r3337) @@ -930,9 +930,13 @@ false ;
+\ To dynamically probe, get the number of functions from bits 30..28 of OCR +0 instance value sdio-ocr \ Contains info about voltages and functions + : set-sdio-voltage ( -- ) 0 io-send-op-cond \ Cmd 5: get card voltage - h# ff.ffff and io-send-op-cond drop \ Cmd 5: set card voltage + h# ff.ffff and io-send-op-cond \ Cmd 5: set card voltage + to sdio-ocr ;
external @@ -1021,6 +1025,83 @@ \ unmap-regs ;
+: .io-state ( flags & 30 -- ) + case + h# 00 of ." card disabled; " endof + h# 10 of ." CMD state; " endof + h# 20 of ." data transfer; " endof + h# 30 of ." reserved; " endof + endcase +; +\ The following are CMD52 (SDIO) variants +\ Flags: 80:CRC_ERROR 40:ILLEGAL_COMMAND 30:IO_STATE (see spec) +\ 08:ERROR 04:reserved 02:INVALID_FUNCTION# 01:OUT_OF_RANGE + +h# cf constant SDIO_FLAG_MASK + +: .sdio-flags ( flags -- ) + dup SDIO_FLAG_MASK and 0= if drop exit then + ." IO_RW_DIRECT response = " + dup h# 80 and if ." CRC error; " then + dup h# 40 and if ." illegal command; " then + dup h# 30 and .io-state + dup h# 08 and if ." error; " then + dup h# 02 and if ." invalid function; " then + dup h# 01 and if ." argument out of range" then + cr +; + +: sdio-reg@ ( reg# func# -- b ) io-b@ .sdio-flags ; +: sdio-reg! ( b reg# func# -- ) io-b! .sdio-flags ; + +\ Can fetch a tuple list from this offset in function 0 +: sdio-cis-ptr ( function# -- reg# ) + h# 100 * 9 + 3 bounds do i 0 sdio-reg@ loop 0 bljoin +; + +: cis@+ ( offset -- offset' byte ) dup 1+ swap 0 sdio-reg@ ; +: skip-tuple ( offset -- offset' ) + cis@+ 0 ?do cis@+ drop loop ( code offset' ) +; + +0 instance value sdio-card-id +: parse-funcid ( offset -- offset' ) + cis@+ drop ( offset ) \ Skip length + cis@+ >r cis@+ >r cis@+ >r cis@+ >r ( offset r: ven.low,high prod.low,high ) + r> r> swap bwjoin r> r> swap bwjoin ( offset product vendor ) + wljoin to sdio-card-id ( vendor.product ) +; + +0 value sdio-card-blocksize +0 value sdio-card-speed +: parse-funce ( offset -- offset' ) + cis@+ drop ( offset' ) \ Skip length + cis@+ 0= if ( offset' ) \ Function 0 + cis@+ >r cis@+ r> swap bwjoin to sdio-card-blocksize ( offset' ) + cis@+ to sdio-card-speed + else ( offset ) \ Not function 0 + 2- ( offset' ) \ Back up to length + skip-tuple ( offset' ) \ Skip it + then ( offset ) +; + +: parse-tuples ( function# -- ) + sdio-cis-ptr begin ( offset ) + cis@+ ( offset' tuple-code ) + dup h# ff <> + while ( offset tuple-code ) + \ Another potentially interesting tuples si h# 15 from which + \ you can get strings naming the product. + case + h# 20 of parse-funcid endof + h# 22 of parse-funce endof + ( default: offset code ) + swap skip-tuple swap + endcase + repeat ( offset tuple-code ) + 2drop +; + : attach-sdio-card ( -- okay? ) setup-host power-up-sdio-card if ( retry? ) @@ -1045,8 +1126,11 @@ select-card \ Cmd 7 - Select set-timeout 4-bit - 22 7 0 io-b! \ Cmd 52 - Set 4-bit bus width and ECSI bit - h# cf and 0= + d# 22 7 0 io-b! \ Cmd 52 - Set 4-bit bus width and ECSI bit + h# cf and 0= ( okay? ) + dup if + 0 parse-tuples \ Get the card ID and other info + then ;
: detach-sdio-card ( -- ) @@ -1129,7 +1213,7 @@ 2dup tuck 1- + swap / to io-#blocks ( reg# function# inc? addr len blksz r: in? ) 4 pick write-blksz ( reg# function# inc? addr len r: in? ) iodma-setup ( reg# function# inc? r: in? ) - wait-write-done if -1 exit then + wait-write-done if r> 2drop 2drop -1 exit then r> if ( reg# function# inc? ) io-read-blocks else
Modified: dev/mmc/sdhci/slot.fth ============================================================================== --- dev/mmc/sdhci/slot.fth Thu Sep 27 03:12:32 2012 (r3336) +++ dev/mmc/sdhci/slot.fth Thu Sep 27 03:14:27 2012 (r3337) @@ -2,8 +2,13 @@
0 " #address-cells" integer-property 0 " #size-cells" integer-property -: open true ; -: close ; +: open + [ifdef] my-clock-on my-clock-on [then] + true +; +: close + [ifdef] my-clock-off my-clock-off [then] +;
: r/w-blocks " r/w-blocks" $call-parent ; : erase-blocks " erase-blocks" $call-parent ; @@ -27,3 +32,7 @@ : io-b@ " io-b@" $call-parent ; : io-b! " io-b!" $call-parent ; : io-b!@ " io-b!@" $call-parent ; +: sdio-reg@ " sdio-reg@" $call-parent ; +: sdio-reg! " sdio-reg!" $call-parent ; +: sdio-card-id " sdio-card-id" $call-parent ; +: sdio-card-blocksize " sdio-card-blocksize" $call-parent ;