OpenWrt WiFi Driver Configuration: Complete ath9k Device-Tree Guide
OpenWrt configures Atheros ath9k WiFi chipsets through device-tree nodes, the kmod-ath9k kernel module, and hot-plug firmware scripts that load calibration EEPROM data at boot.
OpenWrt supports PCI-based Atheros WiFi hardware via the ath9k driver integrated through the mac80211 package in the openwrt/openwrt repository. This OpenWrt WiFi driver configuration relies on hardware descriptions in the device-tree for chip discovery, GPIO mapping, and EEPROM handling, supplemented by build system integration that packages the correct kernel modules and firmware handlers.
How the ath9k Driver Is Loaded
The ath9k driver is part of the mac80211 subsystem and binds to PCI devices automatically when the correct kernel module is present.
Kernel Module Packaging
OpenWrt includes the ath9k driver via the kmod-ath9k package, which builds from the mac80211 source tree. Device targets add this module to their default image through DEVICE_PACKAGES directives in target-specific makefiles:
DEVICE_PACKAGES += kmod-ath9k wpad-basic-mbedtls
For example, in target/linux/mvebu/image/cortexa9.mk, boards append ath9k support alongside wireless authentication packages (lines 108–114)【/cache/repos/github.com/openwrt/openwrt/main/target/linux/mvebu/image/cortexa9.mk#L108-L114】. Similarly, MT7621 profiles include the module in target/linux/ramips/image/mt7621.mk (line 2251)【/cache/repos/github.com/openwrt/openwrt/main/target/linux/ramips/image/mt7621.mk#L2251】.
PCI Auto-Probe Mechanism
When the kernel detects a PCI device with vendor ID 0x168c and device ID 0x0030 (Atheros AR9xxx series), the ath9k driver binds automatically. No additional udev rules or manual loading scripts are required, as the driver registers the standard pci168c,0030 compatible string during initialization.
Device-Tree Configuration for ath9k
The device-tree (DT) supplies hardware-specific parameters including EEPROM handling, MAC address sources, and GPIO mappings for LEDs.
Defining the WiFi Node
The ath9k chip appears as a child node under the PCI controller. In target/linux/ramips/dts/mt7621_mikrotik_ltap-2hnd.dts, the WiFi node uses the following structure:
&pcie0 {
status = "okay";
ath9k: wifi@0,0 {
compatible = "pci168c,0030";
reg = <0x0000 0 0 0 0>;
qca,no-eeprom;
nvmem-cells = <&macaddr_hard 1>;
nvmem-cell-names = "mac-address";
gpio-controller;
#gpio-cells = <2>;
};
};
(Source: target/linux/ramips/dts/mt7621_mikrotik_ltap-2hnd.dts lines 46–57【/cache/repos/github.com/openwrt/openwrt/main/target/linux/ramips/dts/mt7621_mikrotik_ltap-2hnd.dts#L46-L57】)
The qca,no-eeprom property disables automatic EEPROM loading from the card, forcing the driver to rely on external firmware files. The nvmem-cells property links the wireless MAC address to a specific offset in factory partition data.
Mapping LEDs to GPIO Pins
The driver exposes internal GPIOs for signal strength indicators through a dedicated sub-node. The following DT excerpt maps five RSSI LEDs to ath9k GPIO pins:
ath9k-leds {
compatible = "gpio-leds";
rssi0 { label = "green:rssi0"; gpios = <&ath9k 0 GPIO_ACTIVE_LOW>; };
rssi1 { label = "green:rssi1"; gpios = <&ath9k 1 GPIO_ACTIVE_LOW>; };
rssi2 { label = "green:rssi2"; gpios = <&ath9k 2 GPIO_ACTIVE_LOW>; };
rssi3 { label = "green:rssi3"; gpios = <&ath9k 3 GPIO_ACTIVE_LOW>; };
rssi4 { label = "green:rssi4"; gpios = <&ath9k 4 GPIO_ACTIVE_LOW>; };
};
(Source: target/linux/ramips/dts/mt7621_mikrotik_ltap-2hnd.dts lines 17–40【/cache/repos/github.com/openwrt/openwrt/main/target/linux/ramips/dts/mt7621_mikrotik_ltap-2hnd.dts#L17-L40】)
For this mapping to function, the driver must export GPIOs by setting gpio-controller and #gpio-cells = <2> in the parent WiFi node.
EEPROM and Calibration Data
When qca,no-eeprom is absent, the driver searches for ath9k-eeprom-pci-0000:01:00.0.bin (matching the PCI address) under /lib/firmware. OpenWrt provides calibration data through hot-plug scripts located at:
target/linux/*/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom
These scripts copy the appropriate binary from persistent storage (such as a factory partition) to /lib/firmware during boot, ensuring the driver receives valid calibration data for regulatory compliance and power tuning.
Build System Integration
Beyond device-tree definitions, OpenWrt integrates ath9k support through Makefile configurations and kernel patches.
Device Package Makefiles
Target-specific image makefiles declare ath9k as a default package. The build system references these when generating firmware images for specific boards.
ath9k Patch Series
Hardware-specific patches reside in package/kernel/mac80211/patches/ath9k/. Critical patches include:
- 341-wifi-ath9k-obtain-system-gpios.patch: Enables system-wide GPIO lookup for LED control
- 530-ath9k_extra_leds.patch: Adds support for additional LED triggers and RSSI monitoring
These patches apply automatically when building the kmod-ath9k package, extending the upstream driver for OpenWrt's LED infrastructure.
Runtime Wireless Configuration
Once the kernel module loads successfully, OpenWrt's wireless configuration (/etc/config/wireless) references the interface using the mac80211 type and the PCI path from the device-tree:
config wifi-device 'radio0'
option type 'mac80211'
option hwmode '11g'
option path 'pci0000:01/0000:01:00.0'
option channel '11'
option country 'US'
option disabled '0'
option htmode 'HT20'
config wifi-iface
option device 'radio0'
option network 'lan'
option mode 'ap'
option ssid 'OpenWrt'
option encryption 'psk2'
option key 'your-password'
The path option must match the PCI device hierarchy defined in the device-tree for the driver to attach correctly to the radio configuration.
Debugging Common ath9k Issues
When the wireless interface fails to initialize or behaves unexpectedly, verify these common configuration points:
- No interface appears: Confirm
kmod-ath9kis installed usinglsmod | grep ath9k. If missing, add it toDEVICE_PACKAGESin the target Makefile and rebuild. - LEDs remain dark: Check that the
ath9k-ledsdevice-tree node exists and GPIO numbers match the chip's exported pins. Reviewdmesg | grep ath9kfor GPIO registration errors. - Incorrect MAC address: Remove
qca,no-eepromfrom the device-tree to allow EEPROM loading, or ensure the calibration binary exists in/lib/firmwarewith the correct PCI address in the filename. - Unstable connections: Verify power regulator definitions in the device-tree, particularly for
pcie_vcc_regnodes supplying voltage to the WiFi card.
Summary
- OpenWrt configures ath9k through the
kmod-ath9kpackage integrated in target-specific makefiles liketarget/linux/mvebu/image/cortexa9.mk. - The device-tree defines the PCI node with
compatible = "pci168c,0030", optionalqca,no-eeprom, and GPIO controller properties for LED support. - Hot-plug scripts in
target/linux/*/base-files/etc/hotplug.d/firmware/provision calibration EEPROM binaries to/lib/firmwareat boot. - mac80211 patches in
package/kernel/mac80211/patches/ath9k/extend the driver for OpenWrt's GPIO LED infrastructure. - Runtime configuration uses standard
/etc/config/wirelesswith the PCI path matching the device-tree reg property.
Frequently Asked Questions
How do I enable LED support for ath9k in OpenWrt?
Add an ath9k-leds sub-node under the device-tree root with compatible = "gpio-leds", then define individual LED entries using gpios = <&ath9k N GPIO_ACTIVE_LOW> where N is the GPIO number. Ensure the parent WiFi node declares gpio-controller and #gpio-cells = <2> to export the chip's internal pins.
What does the qca,no-eeprom property do in the device-tree?
This property instructs the driver to skip automatic EEPROM loading from the WiFi card. When present, the driver relies on firmware files in /lib/firmware supplied by hot-plug scripts, or uses factory partition aliases via nvmem-cells for calibration data and MAC addresses.
Why is my ath9k wireless interface not showing up after boot?
Verify the PCI ID matches 0x168c:0x0030 using lspci, confirm kmod-ath9k is loaded with lsmod | grep ath9k, and check that the device-tree node uses compatible = "pci168c,0030". Also ensure the path option in /etc/config/wireless correctly reflects the PCI bus hierarchy from the device-tree.
Where does OpenWrt store ath9k calibration data?
Calibration binaries follow the naming pattern ath9k-eeprom-pci-0000:01:00.0.bin (adjusting the PCI address to match your hardware) and reside in /lib/firmware. OpenWrt populates these files at boot through 10-ath9k-eeprom hot-plug scripts that extract data from the device's factory partition or persistent storage.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →