[openfirmware] [commit] r3337 - in dev: . mmc/sdhci mmc/sdhci/mv8686

repository service svn at openfirmware.info
Thu Sep 27 03:14:28 CEST 2012


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 at +  ( offset -- offset' byte )  dup 1+  swap 0 sdio-reg@  ;
+: skip-tuple  ( offset -- offset' )
+   cis at +  0  ?do  cis at +  drop  loop  ( code offset' )
+;
+
+0 instance value sdio-card-id
+: parse-funcid  ( offset -- offset' )
+   cis at + drop            ( offset )  \ Skip length
+   cis at + >r  cis at + >r  cis at + >r  cis at + >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 at + drop     ( offset' )  \ Skip length
+   cis at + 0=  if   ( offset' )  \ Function 0
+      cis at + >r  cis at +  r> swap bwjoin  to sdio-card-blocksize  ( offset' )
+      cis at + 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 at +                    ( 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  ;



More information about the openfirmware mailing list