Atheros AR6003 SDIO WiFi Integration
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:
- http://svn.openmoko.org/trunk/src/target/AR6kSDK.build_sw.18/host/support/loadAR6000.sh (I didn't know about /sbin/cardctl)
- http://nv-tegra.nvidia.com/gitweb/?p=3rdparty/atheros.git;a=summary
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