162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2008-2009 Atheros Communications Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1162306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1362306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1462306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <linux/nl80211.h> 2062306a36Sopenharmony_ci#include <linux/pci.h> 2162306a36Sopenharmony_ci#include <linux/etherdevice.h> 2262306a36Sopenharmony_ci#include <linux/module.h> 2362306a36Sopenharmony_ci#include "../ath.h" 2462306a36Sopenharmony_ci#include "ath5k.h" 2562306a36Sopenharmony_ci#include "debug.h" 2662306a36Sopenharmony_ci#include "base.h" 2762306a36Sopenharmony_ci#include "reg.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* Known PCI ids */ 3062306a36Sopenharmony_cistatic const struct pci_device_id ath5k_pci_id_table[] = { 3162306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ 3262306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ 3362306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ 3462306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ 3562306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ 3662306a36Sopenharmony_ci { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ 3762306a36Sopenharmony_ci { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ 3862306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ 3962306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 compatible */ 4062306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 compatible */ 4162306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 compatible */ 4262306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 compatible */ 4362306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 compatible */ 4462306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 compatible */ 4562306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ 4662306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ 4762306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ 4862306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ 4962306a36Sopenharmony_ci { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */ 5062306a36Sopenharmony_ci { 0 } 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* return bus cachesize in 4B word units */ 5562306a36Sopenharmony_cistatic void ath5k_pci_read_cachesize(struct ath_common *common, int *csz) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci struct ath5k_hw *ah = (struct ath5k_hw *) common->priv; 5862306a36Sopenharmony_ci u8 u8tmp; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci pci_read_config_byte(ah->pdev, PCI_CACHE_LINE_SIZE, &u8tmp); 6162306a36Sopenharmony_ci *csz = (int)u8tmp; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /* 6462306a36Sopenharmony_ci * This check was put in to avoid "unpleasant" consequences if 6562306a36Sopenharmony_ci * the bootrom has not fully initialized all PCI devices. 6662306a36Sopenharmony_ci * Sometimes the cache line size register is not set 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci if (*csz == 0) 7062306a36Sopenharmony_ci *csz = L1_CACHE_BYTES >> 2; /* Use the default size */ 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* 7462306a36Sopenharmony_ci * Read from eeprom 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_cistatic bool 7762306a36Sopenharmony_ciath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct ath5k_hw *ah = (struct ath5k_hw *) common->ah; 8062306a36Sopenharmony_ci u32 status, timeout; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* 8362306a36Sopenharmony_ci * Initialize EEPROM access 8462306a36Sopenharmony_ci */ 8562306a36Sopenharmony_ci if (ah->ah_version == AR5K_AR5210) { 8662306a36Sopenharmony_ci AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); 8762306a36Sopenharmony_ci (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); 8862306a36Sopenharmony_ci } else { 8962306a36Sopenharmony_ci ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); 9062306a36Sopenharmony_ci AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, 9162306a36Sopenharmony_ci AR5K_EEPROM_CMD_READ); 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { 9562306a36Sopenharmony_ci status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); 9662306a36Sopenharmony_ci if (status & AR5K_EEPROM_STAT_RDDONE) { 9762306a36Sopenharmony_ci if (status & AR5K_EEPROM_STAT_RDERR) 9862306a36Sopenharmony_ci return false; 9962306a36Sopenharmony_ci *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & 10062306a36Sopenharmony_ci 0xffff); 10162306a36Sopenharmony_ci return true; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci usleep_range(15, 20); 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return false; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciint ath5k_hw_read_srev(struct ath5k_hw *ah) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci ah->ah_mac_srev = ath5k_hw_reg_read(ah, AR5K_SREV); 11262306a36Sopenharmony_ci return 0; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* 11662306a36Sopenharmony_ci * Read the MAC address from eeprom or platform_data 11762306a36Sopenharmony_ci */ 11862306a36Sopenharmony_cistatic int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci u8 mac_d[ETH_ALEN] = {}; 12162306a36Sopenharmony_ci u32 total, offset; 12262306a36Sopenharmony_ci u16 data; 12362306a36Sopenharmony_ci int octet; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci AR5K_EEPROM_READ(0x20, data); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { 12862306a36Sopenharmony_ci AR5K_EEPROM_READ(offset, data); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci total += data; 13162306a36Sopenharmony_ci mac_d[octet + 1] = data & 0xff; 13262306a36Sopenharmony_ci mac_d[octet] = data >> 8; 13362306a36Sopenharmony_ci octet += 2; 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (!total || total == 3 * 0xffff) 13762306a36Sopenharmony_ci return -EINVAL; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci memcpy(mac, mac_d, ETH_ALEN); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci return 0; 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/* Common ath_bus_opts structure */ 14662306a36Sopenharmony_cistatic const struct ath_bus_ops ath_pci_bus_ops = { 14762306a36Sopenharmony_ci .ath_bus_type = ATH_PCI, 14862306a36Sopenharmony_ci .read_cachesize = ath5k_pci_read_cachesize, 14962306a36Sopenharmony_ci .eeprom_read = ath5k_pci_eeprom_read, 15062306a36Sopenharmony_ci .eeprom_read_mac = ath5k_pci_eeprom_read_mac, 15162306a36Sopenharmony_ci}; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/********************\ 15462306a36Sopenharmony_ci* PCI Initialization * 15562306a36Sopenharmony_ci\********************/ 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic int 15862306a36Sopenharmony_ciath5k_pci_probe(struct pci_dev *pdev, 15962306a36Sopenharmony_ci const struct pci_device_id *id) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci void __iomem *mem; 16262306a36Sopenharmony_ci struct ath5k_hw *ah; 16362306a36Sopenharmony_ci struct ieee80211_hw *hw; 16462306a36Sopenharmony_ci int ret; 16562306a36Sopenharmony_ci u8 csz; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci /* 16862306a36Sopenharmony_ci * L0s needs to be disabled on all ath5k cards. 16962306a36Sopenharmony_ci * 17062306a36Sopenharmony_ci * For distributions shipping with CONFIG_PCIEASPM (this will be enabled 17162306a36Sopenharmony_ci * by default in the future in 2.6.36) this will also mean both L1 and 17262306a36Sopenharmony_ci * L0s will be disabled when a pre 1.1 PCIe device is detected. We do 17362306a36Sopenharmony_ci * know L1 works correctly even for all ath5k pre 1.1 PCIe devices 17462306a36Sopenharmony_ci * though but cannot currently undue the effect of a blacklist, for 17562306a36Sopenharmony_ci * details you can read pcie_aspm_sanity_check() and see how it adjusts 17662306a36Sopenharmony_ci * the device link capability. 17762306a36Sopenharmony_ci * 17862306a36Sopenharmony_ci * It may be possible in the future to implement some PCI API to allow 17962306a36Sopenharmony_ci * drivers to override blacklists for pre 1.1 PCIe but for now it is 18062306a36Sopenharmony_ci * best to accept that both L0s and L1 will be disabled completely for 18162306a36Sopenharmony_ci * distributions shipping with CONFIG_PCIEASPM rather than having this 18262306a36Sopenharmony_ci * issue present. Motivation for adding this new API will be to help 18362306a36Sopenharmony_ci * with power consumption for some of these devices. 18462306a36Sopenharmony_ci */ 18562306a36Sopenharmony_ci pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci ret = pci_enable_device(pdev); 18862306a36Sopenharmony_ci if (ret) { 18962306a36Sopenharmony_ci dev_err(&pdev->dev, "can't enable device\n"); 19062306a36Sopenharmony_ci goto err; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* XXX 32-bit addressing only */ 19462306a36Sopenharmony_ci ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 19562306a36Sopenharmony_ci if (ret) { 19662306a36Sopenharmony_ci dev_err(&pdev->dev, "32-bit DMA not available\n"); 19762306a36Sopenharmony_ci goto err_dis; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci /* 20162306a36Sopenharmony_ci * Cache line size is used to size and align various 20262306a36Sopenharmony_ci * structures used to communicate with the hardware. 20362306a36Sopenharmony_ci */ 20462306a36Sopenharmony_ci pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); 20562306a36Sopenharmony_ci if (csz == 0) { 20662306a36Sopenharmony_ci /* 20762306a36Sopenharmony_ci * Linux 2.4.18 (at least) writes the cache line size 20862306a36Sopenharmony_ci * register as a 16-bit wide register which is wrong. 20962306a36Sopenharmony_ci * We must have this setup properly for rx buffer 21062306a36Sopenharmony_ci * DMA to work so force a reasonable value here if it 21162306a36Sopenharmony_ci * comes up zero. 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_ci csz = L1_CACHE_BYTES >> 2; 21462306a36Sopenharmony_ci pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci /* 21762306a36Sopenharmony_ci * The default setting of latency timer yields poor results, 21862306a36Sopenharmony_ci * set it to the value used by other systems. It may be worth 21962306a36Sopenharmony_ci * tweaking this setting more. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ci pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* Enable bus mastering */ 22462306a36Sopenharmony_ci pci_set_master(pdev); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* 22762306a36Sopenharmony_ci * Disable the RETRY_TIMEOUT register (0x41) to keep 22862306a36Sopenharmony_ci * PCI Tx retries from interfering with C3 CPU state. 22962306a36Sopenharmony_ci */ 23062306a36Sopenharmony_ci pci_write_config_byte(pdev, 0x41, 0); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci ret = pci_request_region(pdev, 0, "ath5k"); 23362306a36Sopenharmony_ci if (ret) { 23462306a36Sopenharmony_ci dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); 23562306a36Sopenharmony_ci goto err_dis; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci mem = pci_iomap(pdev, 0, 0); 23962306a36Sopenharmony_ci if (!mem) { 24062306a36Sopenharmony_ci dev_err(&pdev->dev, "cannot remap PCI memory region\n"); 24162306a36Sopenharmony_ci ret = -EIO; 24262306a36Sopenharmony_ci goto err_reg; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci /* 24662306a36Sopenharmony_ci * Allocate hw (mac80211 main struct) 24762306a36Sopenharmony_ci * and hw->priv (driver private data) 24862306a36Sopenharmony_ci */ 24962306a36Sopenharmony_ci hw = ieee80211_alloc_hw(sizeof(*ah), &ath5k_hw_ops); 25062306a36Sopenharmony_ci if (hw == NULL) { 25162306a36Sopenharmony_ci dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); 25262306a36Sopenharmony_ci ret = -ENOMEM; 25362306a36Sopenharmony_ci goto err_map; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci ah = hw->priv; 25962306a36Sopenharmony_ci ah->hw = hw; 26062306a36Sopenharmony_ci ah->pdev = pdev; 26162306a36Sopenharmony_ci ah->dev = &pdev->dev; 26262306a36Sopenharmony_ci ah->irq = pdev->irq; 26362306a36Sopenharmony_ci ah->devid = id->device; 26462306a36Sopenharmony_ci ah->iobase = mem; /* So we can unmap it on detach */ 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* Initialize */ 26762306a36Sopenharmony_ci ret = ath5k_init_ah(ah, &ath_pci_bus_ops); 26862306a36Sopenharmony_ci if (ret) 26962306a36Sopenharmony_ci goto err_free; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* Set private data */ 27262306a36Sopenharmony_ci pci_set_drvdata(pdev, hw); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci return 0; 27562306a36Sopenharmony_cierr_free: 27662306a36Sopenharmony_ci ieee80211_free_hw(hw); 27762306a36Sopenharmony_cierr_map: 27862306a36Sopenharmony_ci pci_iounmap(pdev, mem); 27962306a36Sopenharmony_cierr_reg: 28062306a36Sopenharmony_ci pci_release_region(pdev, 0); 28162306a36Sopenharmony_cierr_dis: 28262306a36Sopenharmony_ci pci_disable_device(pdev); 28362306a36Sopenharmony_cierr: 28462306a36Sopenharmony_ci return ret; 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic void 28862306a36Sopenharmony_ciath5k_pci_remove(struct pci_dev *pdev) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci struct ieee80211_hw *hw = pci_get_drvdata(pdev); 29162306a36Sopenharmony_ci struct ath5k_hw *ah = hw->priv; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci ath5k_deinit_ah(ah); 29462306a36Sopenharmony_ci pci_iounmap(pdev, ah->iobase); 29562306a36Sopenharmony_ci pci_release_region(pdev, 0); 29662306a36Sopenharmony_ci pci_disable_device(pdev); 29762306a36Sopenharmony_ci ieee80211_free_hw(hw); 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 30162306a36Sopenharmony_cistatic int ath5k_pci_suspend(struct device *dev) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci struct ieee80211_hw *hw = dev_get_drvdata(dev); 30462306a36Sopenharmony_ci struct ath5k_hw *ah = hw->priv; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci ath5k_led_off(ah); 30762306a36Sopenharmony_ci return 0; 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic int ath5k_pci_resume(struct device *dev) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(dev); 31362306a36Sopenharmony_ci struct ieee80211_hw *hw = pci_get_drvdata(pdev); 31462306a36Sopenharmony_ci struct ath5k_hw *ah = hw->priv; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* 31762306a36Sopenharmony_ci * Suspend/Resume resets the PCI configuration space, so we have to 31862306a36Sopenharmony_ci * re-disable the RETRY_TIMEOUT register (0x41) to keep 31962306a36Sopenharmony_ci * PCI Tx retries from interfering with C3 CPU state 32062306a36Sopenharmony_ci */ 32162306a36Sopenharmony_ci pci_write_config_byte(pdev, 0x41, 0); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci ath5k_led_enable(ah); 32462306a36Sopenharmony_ci return 0; 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); 32862306a36Sopenharmony_ci#define ATH5K_PM_OPS (&ath5k_pm_ops) 32962306a36Sopenharmony_ci#else 33062306a36Sopenharmony_ci#define ATH5K_PM_OPS NULL 33162306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic struct pci_driver ath5k_pci_driver = { 33462306a36Sopenharmony_ci .name = KBUILD_MODNAME, 33562306a36Sopenharmony_ci .id_table = ath5k_pci_id_table, 33662306a36Sopenharmony_ci .probe = ath5k_pci_probe, 33762306a36Sopenharmony_ci .remove = ath5k_pci_remove, 33862306a36Sopenharmony_ci .driver.pm = ATH5K_PM_OPS, 33962306a36Sopenharmony_ci}; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cimodule_pci_driver(ath5k_pci_driver); 342