Atheros AR6003 SDIO WiFi Integration

From RidgeRun Developer Wiki


Aug 15, 2011 -- This page is only half complete. It still contains SD8686 references.

Open Source project

The Wireless Linux project has an Atheros ath6k driver available.

Helpful links:

Atheros proprietary driver

Atheros provides two tarballs containing their proprietary Linux driver

  • AR6K_PKG_FW.build_3.1_RC.329.tgz
  • AR6K_SDK_ISC.build_3.1_RC.329.tgz

Adding drivers to development directory

This requires proper credentials as some of the code was provided under NDA.

cd $DEVDIR/proprietary
svn co https://source.ridgerun.net/svn/bsp/proprietary/atheros/ar6003/trunk ar6003
svn co  https://source.ridgerun.net/svn/bsp/proprietary/atheros/nv-ar6003/trunk nv-ar6003
make -C $DEVDIR config # Proprietary software -> Atheros AR6003 SDIO Wireless support
cd $DEVDIR/proprietary/ar6003
make VERBOSE=1
cd $DEVDIR/proprietary/nv-ar6003
make VERBOSE=1

Long term, only the ar6003 source code directory will be used. The nv-ar6003 is just for reference.

Add chip code files to target file system

Marvell should have supplied the 88W8686 chip code files with the hardware. These files need to be copied to target file system, with a minor file rename. The driver expects to find these files in /lib/firmware on the target file system.

mkdir -p $DEVDIR/fs/overlay/lib/firmware 
cp /tmp/helper_sd.bin $DEVDIR/fs/overlay/lib/firmware/sd8686_helper.bin
cp /tmp/sd8686.bin $DEVDIR/fs/overlay/lib/firmware

files="$DEVDIR/fs/overlay/lib $DEVDIR/fs/overlay/lib/firmware $DEVDIR/fs/overlay/lib/firmware/sd8686_helper.bin $DEVDIR/fs/overlay/lib/firmware/sd8686.bin"
svn add $files
svn ci -m "Added code images for 88W8686 chipset" $files

Enable kernel drivers

Configure the kernel so there variable are set as follows:

CONFIG_LIBERTAS=m
CONFIG_LIBERTAS_SDIO=m
CONFIG_MMC=y
CONFIG_MMC_DAVINCI=y

Enable helper applications

Configure the Wifi tools so they get built.

CONFIG_FS_APPS_WIRELESS_TOOLS=y
CONFIG_FS_APPS_WPASUPPLICANT=y

AR6003 as a WiFi client

Runtime driver module loading

Boot target hardware without wifi sdio card installed. Install card. You should see:

mmc0: new SDIO card at address 0001


Verifying AR6003 chip properly detected

On a DM365, the following entries should exist in sysfs.


cd /sys/devices/platform/davinci_mmc.0/mmc_host/mmc0/mmc0:0001/mmc0:0001:1
echo class: `cat class`, vendor: `cat vendor`, device: `cat device`

The output should be:

class: 0x00, vendor: 0x0271, device: 0x0301

Verifying SDIO hardware interface configuration

The debugfs file system contains entries that contain the current settings for the MMC/SD/SDIO interface of interest.

mount -t debugfs none /sys/kernel/debug
cat /sys/kernel/debug/mmc0/ios

You should see something like

clock:		50000000 Hz
vdd:		20 (3.2 ~ 3.3 V)
bus mode:	2 (push-pull)
chip select:	0 (don't care)
power mode:	2 (on)
bus width:	2 (4 bits)
timing spec:	2 (sd high-speed)

Forcing timing spec: 0 (legacy) caused the first bmiloader command to stall. Forcing bus width: 0 (1 bits) didn't change whereloadAR6000.sh stalled.

Pin multiplexing

mount -t debugfs none /sys/kernel/debug
cat /sys/kernel/debug/dm365_mux

Loading drivers

Option 1: using /usr/sbin/loadAR6000.sh

export WORKAREA=/usr/share/ar6k
export ATH_PLATFORM=V210_ARM_NATIVEMMC-SDIO
sh -x /usr/sbin/loadAR6000.sh

Option 2: manual load driver and firmware

export IMAGE=/usr/share/ar6k/host/.output/V210_ARM_NATIVEMMC-SDIO/image
export PATH=$PATH:$IMAGE

inetd &
ifconfig eth0 | fgrep 'inet addr' | cut -f2 -d: | cut -f1 -d' '

insmod $IMAGE/ar6000.ko bmienable=1 busspeedlow=0 nohifscattersupport=1 debuglevel=3

recEvent -gg --logfile=/tmp/dbglog.out --srcdir=/usr/share/ar6k/include/ &

bmiloader -i eth1 --quiet --info
bmiloader -i eth1 --quiet --set --address=0x180c0 --or=8
bmiloader -i eth1 --quiet --set --address=0x40c4 --or=1
bmiloader -i eth1 --quiet --set --address=0x1c284 --param=0xF9104001
bmiloader -i eth1 --quiet --set --address=0x4020 --param=1
bmiloader -i eth1 --quiet --set --address=0x14050 --param=0x20
miloader -i eth1 --quiet --set --address=0x14054 --param=0x20
bmiloader -i eth1 --quiet --set --address=0x14058 --param=0x20
bmiloader -i eth1 --quiet --set --address=0x1405c --param=0x20
bmiloader -i eth1 --quiet --set --address=0x40e0 --param=0x100000
eeprom --transfer --file=/usr/share/ar6k/host/support/calData_AR6103_v42_DVT_golden.bin --interface=eth1
bmiloader -i eth1 --write --file=/usr/share/ar6k/target/AR6003/hw2.1.1/bin/otp.bin
bmiloader -i eth1 --execute --address=0x945d00 --param=0
bmiloader -i eth1 --write --file=/usr/share/ar6k/target/AR6003/hw2.1.1/bin/athwlan.bin
bmiloader -i eth1 --write --address=0x57ff74 --file=/usr/share/ar6k/target/AR6003/hw2.1.1/bin/data.patch.hw3_0.bin
bmiloader -i eth1 --write --address=5506584 --param=0x57ff74
bmiloader -i eth1 --set --address=0x5406a4 --param=0x16
bmiloader -i eth1 --set --address=0x540680 --param=8
bmiloader -i eth1 --set --address=0x40c4 --param=0x1d
bmiloader -i eth1 --set --address=0x180c0 --param=0x0
bmiloader -i eth1 --done

Video ar6000.ko driver parameters

ls /sys/module/ar6000/parameters

with results similar to

allow_trace_signal      ifname                  setupbtdev
ar3khcibaud             irqprocmode             setuphci
bmienable               logWmiRawMsgs           setuphcipal
busspeedlow             loghci                  skipflash
bypasswmi               mac_addr_method         submode
csumOffload             mbox_yield_limit        targetconf
debuglevel              nohifscattersupport     testmode
devmode                 onebitmode              tspecCompliance
enablerssicompensation  panic_on_assert         tx_attempt
enabletimerwar          processDot11Hdr         tx_complete
enableuartprint         reduce_credit_dribble   tx_post
eppingtest              regcode                 war23838_disabled
firmware_bridge         regscanmode             wlanNodeCaching
hciuartscale            reset_sdio_on_unload    wlaninitmode
hciuartstep             resetok                 wmitimeout
hifBusRequestNumMax     rtc_reset_only_on_exit

or if driver was built with debug enabled:

allow_trace_signal           panic_on_assert
ar3khcibaud                  processDot11Hdr
bmienable                    reduce_credit_dribble
busspeedlow                  refClock
bypasswmi                    regcode
csumOffload                  regscanmode
debugbmi                     reset_sdio_on_unload
debugdriver                  resetok
debugflags                   rtc_reset_only_on_exit
debughif                     setupbtdev
debughtc                     setuphci
debuglevel                   setuphcipal
devmode                      skipflash
enablerssicompensation       submode
enabletimerwar               targetconf
enableuartprint              testmode
eppingtest                   tspecCompliance
firmware_bridge              tx_attempt
hciuartscale                 tx_complete
hciuartstep                  tx_post
hifBusRequestNumMax          txcreditintrenable
ifname                       txcreditintrenableaggregate
irqprocmode                  txcreditsavailable
logWmiRawMsgs                txcreditsconsumed
loghci                       war23838_disabled
mac_addr_method              wlanNodeCaching
mbox_yield_limit             wlaninitmode
nohifscattersupport          wmitimeout
onebitmode

Installing Libertas WiFi module

modprobe libertas

Output will only be generated if there is an error.

Installing Libertas SDIO module

modmodprobe ar6000

You should see:


If you don't see any output, you may need to increase the printk debug level:

echo 8 > /proc/sys/kernel/printk

or you can look in the kernel message buffer

dmesg | tail -n 6

Verifying wlan0 exists

Make sure Linux network interface and wireless LAN interface are both found

ifconfig wlan0
iwconfig wlan0

You should get output like:

wlan0     Link encap:Ethernet  HWaddr 00:19:88:3D:D3:77  
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

and for iwconfig, the output will be similar to:

wlan0     IEEE 802.11b/g  ESSID:""  
          Mode:Managed  Frequency:2.412 GHz  Access Point: Not-Associated   
          Bit Rate:0 kb/s   Tx-Power=15 dBm   
          Retry short limit:8   RTS thr=2347 B   Fragment thr=2346 B   
          Encryption key:off
          Power Management:off
          Link Quality:0  Signal level:0  Noise level:0
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

Power on WiFi sub-system

ifconfig wlan0 up

No output will be generated if successful.

Scan for access points

iwlist wlan0 scan

which lists access points that are in range, like:

wlan0     Scan completed :
          Cell 01 - Address: 00:12:25:57:61:B5
                    ESSID:"Hawley"
                    Mode:Managed
                    Frequency:2.462 GHz (Channel 11)
                    Quality=97/100  Signal level=-28 dBm  Noise level=-96 dBm
                    Encryption key:off
                    Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 18 Mb/s
                              24 Mb/s; 36 Mb/s; 54 Mb/s; 6 Mb/s; 9 Mb/s
                              12 Mb/s; 48 Mb/s

Attaching WiFi to access point

Security disabled

iwconfig wlan0 essid "Hawley"

WEP security

iwconfig wlan0 essid "Hawley"
iwconfig wlan0 key 0001020304

WPA security

mkdir -p /etc/wpa_supplicant
cat <<EOF >/etc/wpa_supplicant/wpa_supplicant.conf
# Example wpa_supplicant 
network={
	ssid="Baily"
	psk="very secret passphrase"
	priority=5
}
EOF

wpa_supplicant -d -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf -Dwext &

With debug output enabled, you will have lots of information on what is not working if you run into a problem.

Verifying access point association

You can check you are associated with an access point using

iwconfig wlan0

With example output being:

wlan0     IEEE 802.11b/g  ESSID:"Baily"  
          Mode:Managed  Frequency:2.437 GHz  Access Point: 00:13:10:EA:BD:66   
          Bit Rate:1 Mb/s   Tx-Power=13 dBm   
          Retry short limit:8   RTS thr=2347 B   Fragment thr=2346 B   
          Encryption key:<too big>   Security mode:open
          Power Management:off
          Link Quality=95/100  Signal level=-44 dBm  Noise level=-89 dBm
          Rx invalid nwid:0  Rx invalid crypt:121  Rx invalid frag:0
          Tx excessive retries:6  Invalid misc:13   Missed beacon:0

If you are having trouble associating with an access point, I find connecting to the AP with my laptop is a good way to verify the AP is configured as expected.

Configuring IP networking

ifconfig wlan0 10.111.0.157
route add -net 0.0.0.0 gw 10.111.0.1 netmask 0.0.0.0 dev wlan0
route -n

With example output:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.111.0.0      0.0.0.0         255.255.255.0   U     0      0        0 eth0
10.0.0.0        0.0.0.0         255.0.0.0       U     0      0        0 wlan0
0.0.0.0         10.111.0.1      0.0.0.0         UG    0      0        0 wlan0
0.0.0.0         10.111.0.1      0.0.0.0         UG    0      0        0 eth0

Note that the routing table is traversed from top to bottom, so packets for the Internet will go out wlan0 since that entry is closer to the top.

Functional test

The Google nameserver, which supports ping, is at IP address 8.8.8.8.

ping -c 5 8.8.8.8

Unconfiguring WiFi client mode of operation

ifconfig wlan0 down
rmmod libertas_sdio
rmmod libertas

Using loadAR6000.sh

killall psplash
killall jpeg-capture
killall ipiped
killall  dbus-daemon
modprobe bluetooth

export WORKAREA=/usr/share/ar6000
export ATH_PLATFORM=V210_ARM_NATIVEMMC-SDIO
loadAR6000.sh --debug

Problems and how to fix them

Unknown symbol hci_free_dev

When you load the ar6000 kernel module, you may see

ar6000: Unknown symbol hci_free_dev
ar6000: Unknown symbol hci_alloc_dev
ar6000: Unknown symbol hci_unregister_dev
ar6000: Unknown symbol hci_register_dev

If you built Bluetooth as a module, first load it before running loadAR6000.sh.

modprobe bluethooth


wmi_control_rx: Unknown id 0x101e

When you run loadAR6000.sh, you might see:

AR6K: ** HIF layer does not support scatter requests (17)
wmi_control_rx() : Unknown id 0x101e

configuration opcode 7 is only used for RTOS systems, not Linux systems

When you load the ar6000 kernel module, you may see

Bluetooth: HCI device and connection manager initialized
Bluetooth: HCI socket layer initialized
AR6000: configuration opcode 7 is only used for RTOS systems, not Linux systems
 Timeout waiting for recv message 
Target debug interrupt
ar6000_target_failure: target asserted

task kmmcd blocked for more than 120 seconds

From the backtrace below, you find:

[<c02388d8>] (sdio_memcpy_toio+0x0/0x30) from [<bf001c00>] (async_task+0x444/0x78c [ar6000])

Using arm-none-linux-gnueabi-objdump you can identify where in the ar6k driver the call is being made to sdio_memcpy_toio() that is waiting for the interrupt that never occurs:

arm-none-linux-gnueabi-objdump -d -S $DEVDIR/proprietary/ar6k/src/host/os/linux/ar6000.o | less -p sdio_memcpy_toio

You will find something like

   1bfc:       ebfffffe        bl      0 <sdio_memcpy_toio>

a similar search for async_task turns up

000017bc <async_task>:

where 0x17bc + 0x444 = 0x1bfa which is 4 greater than the call to sdio_memcpy_toio(), thus being the return address that is used after the call.

Looking in the source code (around line 263), we find only $DEVDIR/proprietary/ar6k/src/host/hif/sdio/linux_sdio/src/hif.c contains a call to sdio_memcpy_toio():

            if (opcode == CMD53_FIXED_ADDRESS) {
                ret = sdio_writesb(device->func, address, tbuffer, length);
                AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writesb ret=%d address: 0x%X, len: %d, 0x%X\n",
						  ret, address, length, *(int *)tbuffer));
            } else {
                ret = sdio_memcpy_toio(device->func, address, tbuffer, length);
                AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writeio ret=%d address: 0x%X, len: %d, 0x%X\n",
						  ret, address, length, *(int *)tbuffer));
            }

with the backtrace that started all of this analysis being:

ar6000_init() WMI is ready
INFO: task kmmcd:194 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
kmmcd         D c02ec9e8     0   194      2 0x00000000
Backtrace: 
[<c02ec6f8>] (schedule+0x0/0x380) from [<c02331f0>] (__mmc_claim_host+0xc8/0x190)
[<c0233128>] (__mmc_claim_host+0x0/0x190) from [<c02374dc>] (mmc_sdio_detect+0x30/0x74)
[<c02374ac>] (mmc_sdio_detect+0x0/0x74) from [<c023386c>] (mmc_rescan+0x8c/0x314)
 r5:60000013 r4:c5116800
[<c02337e0>] (mmc_rescan+0x0/0x314) from [<c0053cc8>] (worker_thread+0x134/0x1f0)
 r6:c50639a0 r5:c5116938 r4:c511693c
[<c0053b94>] (worker_thread+0x0/0x1f0) from [<c0057770>] (kthread+0x88/0x90)
[<c00576e8>] (kthread+0x0/0x90) from [<c0044cfc>] (do_exit+0x0/0x640)
 r7:00000000 r6:00000000 r5:00000000 r4:00000000
INFO: task AR6K Async:1100 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
AR6K Async    D c02ec9e8     0  1100      2 0x00000000
Backtrace: 
[<c02ec6f8>] (schedule+0x0/0x380) from [<c02ed0a0>] (schedule_timeout+0x20/0x1f4)
[<c02ed080>] (schedule_timeout+0x0/0x1f4) from [<c02ecefc>] (wait_for_common+0xf4/0x1bc)
 r7:7fffffff r6:c548be54 r5:c509f5e0 r4:c548be10
[<c02ece08>] (wait_for_common+0x0/0x1bc) from [<c02ed054>] (wait_for_completion+0x18/0x1c)
[<c02ed03c>] (wait_for_completion+0x0/0x1c) from [<c0233bfc>] (mmc_wait_for_req+0x108/0x118)
[<c0233af4>] (mmc_wait_for_req+0x0/0x118) from [<c023769c>] (mmc_io_rw_extended+0x17c/0x1e4)
 r5:c548be7c r4:c548bed4
[<c0237520>] (mmc_io_rw_extended+0x0/0x1e4) from [<c0238848>] (sdio_io_rw_ext_helper+0x154/0x18c)
[<c02386f4>] (sdio_io_rw_ext_helper+0x0/0x18c) from [<c0238900>] (sdio_memcpy_toio+0x28/0x30)
[<c02388d8>] (sdio_memcpy_toio+0x0/0x30) from [<bf001c00>] (async_task+0x444/0x78c [ar6000])
[<bf0017bc>] (async_task+0x0/0x78c [ar6000]) from [<c0057770>] (kthread+0x88/0x90)
[<c00576e8>] (kthread+0x0/0x90) from [<c0044cfc>] (do_exit+0x0/0x640)
 r7:00000000 r6:00000000 r5:00000000 r4:00000000