CHROMIUM: ath9k: Merges for BTCOEX on 9462
authorPaul Stewart <pstew@chromium.org>
Wed, 25 Jul 2012 20:21:59 +0000 (13:21 -0700)
committerGerrit <chrome-bot@google.com>
Tue, 7 Aug 2012 18:38:34 +0000 (11:38 -0700)
This commit has the suggested upstream merge list for Bluetooth
coexistence for the Atheros AR9462.  There are a lot of untested
changes here, so we leave the current ath9k driver alone for the
most part and create a new "ath9k_btcoex" driver and apply the
merge list to that.  This way, we can carry the original driver
in parallel (modified only to remove support for ar9462).

The symbols in the ath9k_btcoex driver tree are modified so they
do not match those from ath9k, and modprobe dependencies work
correctly.  Also, the rate control algorithm has been renamed to
"ath9k_btcoex_rate_control" so ath9k and ath9k_btcoex modules
can be loaded simultaneously.

This driver is accessible using the following configuration
options:

   ATH9K_BTCOEX (ATH9K)
   ATH9K_BTCOEX_COMMON (ATH9K_COMMON)
   ATH9K_BTCOEX_HW (ATH9K_HW)

Committed changes follow below:

ath9k: Use atomic operations
   (cherry picked with fixup from 781b14a3153a722fec820374271316537881076e)
ath9k: Reconfigure VIF state properly
   (cherry picked from commit 6dcc344469d60a1f0d72cc638967e8c83c6e166e)
ath9k: Cleanup the beacon tasklet
   (cherry picked from commit fb6e252f8d262d05da3ae023b4a6f83d0eec17d9)
ath9k: Set the TSF adjust value properly
   (cherry picked from commit 2f8e82e8ab4629e648925c566cc26bdcf25f0aec)
ath9k: Cleanup beacon queue configuration
   (cherry picked from commit 7e52c8aa35c987236a80b7063c418a3d29b51052)
ath9k: Remove is_bslot_active
   (cherry picked from commit aa45fe9683ba861bf49d51479b11b3d482b57416)
ath9k: Cleanup beacon logic
   (cherry picked with fixup from ef4ad63368e6162fb0b18861748fac49edfcbd03)
ath9k: Simplify ASSOC handling
   (cherry picked with fixup from 6c43c090a92938c3e89ce3b7459f91c5159535e2)
ath9k: Cleanup interface handling
   (cherry picked with fixup from df35d29e171ef043976b339812276ff96d1f4c21)
ath9k_hw: Cleanup ath9k_hw_set_tsfadjust
   (cherry picked with fixup from 60ca9f8744d29b8fdfd33d3dec8fc2cfc9ec381a)
ath9k: Fix beacon setup
   (cherry picked with fixup from 130ef6e9dc76f821caf98fa9ed6e2dafe15f3b1f)
ath9k_hw: remove debugging masks from AR_MCI_INTERRUPT_RX_MSG_DEFAULT
   (cherry picked from commit d081257c78ace442db2a59f0aa4c52c69b252663)
ath9k: Stop the BTCOEX timers before disabling BTCOEX
   (cherry picked from commit 6454bf2921c73b47dde9f989bd99aeff25171110)
ath9k: Fix MCI cleanup
   (cherry picked from commit df171637109b8760dd28dc15eb06eb0901689117)
ath9k_hw: fix AR9462 2g5g switch on full reset
   (cherry picked from commit 2250fe4a94863a647683e09b0b798772e01e062c)
ath9k: fix power consumption on network sleep when BTCOEX is enabled
   (cherry picked from commit 8a795aec91c98b6e5a734b32e0e37205ba2c95d2)
ath9k: fix fullsleep power consumption when BTCOEX is enabled
   (cherry picked from commit 84db9667b177cb4ba01b117297a89b0a34d8c45a)
ath9k_hw: start noisefloor calibration after MCI reset
   (cherry picked with fixup from 678dffdcb7e53c11e93ac5beb4ca8ac710720f93)
ath9k: fixing register bit shift values of control packets to support TPC
   (cherry picked from commit 912f81412f9362737deae9dd4f9472e0b73fc4b5)
ath9k: Fix clearing of BTCOEX flags
   (cherry picked from commit e790eab9ef203ff2843b5f9c80efb1339e1d867b)
ath9k: de-duplicate initvals
   (cherry picked with fixup from 469979173ecda9c472c495608d6d540ec33ab85d)
ath9k: update AR934x initvals to latest version
   (cherry picked from commit 589ebd85268293e64ff6b7e0dd4ed8fb26811aa7)
ath9k: Fix signedness in a MCI debug message
   (cherry picked from commit d8fffb4a9e13d1130b4fd0e577973704cad79f40)
ath9k_hw: make use of the wrapper to check for MCI init
   (cherry picked from commit 812944891c598300afcc5628905d775019f25310)
ath9k: Fix compilation breakage
   (cherry picked from commit bf52592fe4901f486a5266fd73e4ee80205b18b4)
ath9k: Fix lockdep splat
   (cherry picked from commit fad29cd2f59949581050a937786c2c9bc78b2f04)
ath9k: raise aggregation limit to 64k for HT IBSS
   (cherry picked from commit 313eb87f1e2f93d83836de7f5c1947b75d7752c8)
ath9k_hw: fix smatch warning in ar9003_hw_spur_mitigate_mrc_cck
   (cherry picked from commit 4b5237cc86872319a321ca1a694dee8866f7d9a3)
ath9k_hw: rename mrcCCKOff to fix smatch warning
   (cherry picked from commit 81b67fd60a75cac36092aa37cd0728aab3a7a938)
ath9k: do not sampling on ani timer when chip is in sleep
   (cherry picked with fixup from 5039f38e16695a0a5c72b08c6a6cc66844a657b1)
ath9k_hw: fix LNA control on WLAN sleep
   (cherry picked from commit 4ff6a9d200c66f192da61822c36ad14424e218d6)
ath9k_hw: update ar9462 dac_async_fifo initval
   (cherry picked from commit 0967d862315366e2ef2401301ff2b1756928b4c1)
ath9k: fix mci_is_enabled utility
   (cherry picked from commit e1ecad78e5c5c32f331925f340141a38aaa64cef)
ath9k_hw: fix BT mute at hw init
   (cherry picked from commit a68807e9177a083dc09c24b141158539d71db21c)
ath9k: fix incorrect profile type manupulation
   (cherry picked from commit 305dd09f8ce05cc8a8cce4e790a6d3d02e5c4f1d)
ath9k_hw: clean up ANI OFDM trigger handling
   (cherry picked from commit 058a6385cb876d4b1b97610ee4e73a845e7bea71)
ath9k: remove MIB interrupt support
   (cherry picked from commit 198823fd002a7f9784648c24c72b7e8c9e73fd14)
ath9k_hw: clean up defines and variables from the ANI implementation split
   (cherry picked from commit 465dce62cdb35f49bc0e859fb23787e1229b62a3)
ath9k_hw: remove the old ANI implementation
   (cherry picked with fixup from 6790ae7a1383db07842b3fd03208dd86f55da57e)
ath9k_hw: clean up / fix ANI mode checks related to beacon RSSI
   (cherry picked from commit 5330df7b178f4f050c67451413020bdd4ec75262)
ath9k_hw: remove confusing logic inversion in an ANI variable
   (cherry picked with fixup from 7067e7014d7013645f7e866b74814f1e59e6a7cd)
ath9k_hw: fix OFDM weak signal detection handling
   (cherry picked with fixup from 0b81cc3922bce79d0f21189648bf4f9992e9a533)
ath9k_hw: remove aniState->noiseFloor
   (cherry picked from commit 35e808b7e4e9ddac1086716867fe686f52fb78ff)
ath9k_hw: remove MCI_STATE_SET_BT_SLEEP
   (cherry picked from commit 9330969b8fd1304fdcb7c1825f1528eea38d321c)
ath9k_hw: remove MCI_STATE_CONT_* state
   (cherry picked from commit 26e942b790eddc757b5be179ef67907e025ff87b)
ath9k_hw: remove MCI_STATE_BT
   (cherry picked from commit 6d97be48e27603f99743fc0e94e57dce2edb9cbf)
ath9k_hw: remove p_data argument from ar9003_mci_state
   (cherry picked from commit b98ccec0a497a9f08d705f1a7d63d5690bb48e70)
ath9k_hw: remove MCI_STATE_NEED_FLUSH_BT_INFO
   (cherry picked from commit d02ca07e6fdf89ed6f453fe1c9229c71a0358886)
ath9k_hw: remove MCI_STATE_SEND_WLAN_CHANNELS
   (cherry picked from commit 2d340ac81e7474535db7a14f35c80b45b02b63a1)
ath9k_hw: add utility function to set BT version
   (cherry picked from commit e1763d3f3388968d622a340fed711ae16fc1bc11)
ath9k_hw: cleanup MCI gpm offset state
   (cherry picked from commit 506847ad34c08fe4f766ffe1b955713628acf6bd)
ath9k: fix btcoex duty cycle
   (cherry picked from commit a197b76c230725962dc8e13102b24468e8621bfb)
ath9k: defer btcoex scheme update
   (cherry picked from commit 3c7992e33ab8d0c625a45ded11cc10d5b622bcd4)
ath9k: keep btcoex period in milliseconds
   (cherry picked from commit dfd0587a7d99d42cc2d608324991169494d2dbba)
ath9k: simplify btcoex profile management
   (cherry picked from commit 9e2e0c84699ce7adeddb5cd5763956493ca7d331)
ath9k_hw: process MCI interrupts only when btcoex is enabled
   (cherry picked from commit 92a33298e9a329d4bed9f723811c5bedc7d92b9c)
ath9k_hw: program OBS register only when MCI is disabled
   (cherry picked from commit ed6ebd8bc852845e34e8160eed43b29236b1892f)
ath9k_hw: fix incorrect LNA register settings
   (cherry picked from commit 1bde95fa7ed84094d0606d9e79356a9dd8d0e01b)
ath9k_hw: check GPM HW write pointer before chip reset
   (cherry picked from commit 3863495b86d8ee8e7e70a328de5b88d555d7305a)
ath9k_hw: Fix AR9462 power consumption on idle associated
   (cherry picked from commit 9dd9b0dc1de8031a31b3eaebc6a9c0ab60612026)
ath9k: restore power state on set channel failure
   (cherry picked from commit 8389fb3fd7c0bbe3289578f698917f594e0b6fc9)
ath9k: choose legacy rate as last rate of MRR series
   (cherry picked from commit cec429dd65ef1ccc693e5fa1468b0a12982b4283)
ath9k_hw: Update initvals for AR9462
   (cherry picked from commit 6304c20167337e21699bb3f7d25fcf099263416e)
ath9k: Move LNA code to antenna.c
   (cherry picked with fixup from 8da07830e10a91cbe7badf9767230aafdd520b9c)
ath9k: improve BT FTP/PAN performance
   (cherry picked from commit 6995fb805ed5de852a7d49413730980bc7173e82)
ath9k_hw: fix power state for MCI
   (cherry picked from commit 153dccd467b818b1dd3a6801b14e94a7a48ef859)
ath9k: BT coex performance tuning for AR9462
   (cherry picked from commit 0603143e47a34d0485a13fd7f46e56a97e687e34)
ath9k_hw: fix BT RF performance
   (cherry picked from commit 99922a45e96b22df387823ad5ecfe4dc26a96c9e)
ath9k_hw: program BT to control SPDT
   (cherry picked from commit 9dc08eceb7491331e81acde625e0d9c82aa86a16)
ath9k: cleanup MCI indentation
   (cherry picked from commit 4f6bd1a8dfcc649912310777a44c49849ae2a63d)
ath9k: Use separate operational flags for BTCOEX
   (cherry picked from commit e6930c4b32aaa30fb9510984509afcc9f61fa39c)
ath9k: Remove SC_OP_OFFCHANNEL
   (cherry picked with fixup from 4cb54fa3a2456e66d8e3bae663d66f00cbb9e483)
ath9k_hw: Fix variable usage
   (cherry picked from commit 2fd5d35bc87a301d5c10397c5b38a4ec8532a975)
ath9k: Add MCI interrupt to debugfs statistics
   (cherry picked with fixup from 97ba515a201bc61c7d36c41ad728b0a7debd5d88)
ath9k_hw: Cleanup power mode API
   (cherry picked from commit 31604cf0a73ffd63929f3a646d5402d5901c6e4b)
ath9k: Ensure a fair beacon distribution in IBSS mode
   (cherry picked from commit d202caff28d69f4ec6cf56568f79b0916294cade)
ath9k: fix beacon descriptor
   (cherry picked from commit cd484aeb4976899a4c6efbed951ac2fc8c51e097)
ath9k: skip beaconing when reset work is pending
   (cherry picked from commit 4e7fb7187d69132cf8223d4f8a49f86a6aba529d)
ath9k: add possible wiphy interface combinations
   (cherry picked from commit 20c8e8dc4e9baf0c1b7c77c860726788896f2d9c)
ath9k_hw: remove ATH_BTCOEX_CFG_MCI
   (cherry picked from commit 0466e2547d05a9ae8d49afc67a3851d034a528f8)
ath9k: stop rx dma before stopping tx
   (cherry picked from commit ceea2a51969f8b578777c99ec2718021427770c3)
ath9k: fix a tx rate duration calculation bug
   (cherry picked from commit 76591bea9714a58d8924154068c78d702eb2cb17)
ath9k: fix invalid pointer access in the tx path
   (cherry picked from commit 80b08a8d8829a58b5db14b1417151094cc28face)

Signed-off-by: Paul Stewart <pstew@chromium.org>
BUG=chrome-os-partner:11082
TEST=Boot device, join WiFi (no Bluetooth testing done yet)

Change-Id: I114ad8a5a1068da0dc2c3c84dd89738d2116401b
Reviewed-on: https://gerrit.chromium.org/gerrit/28420
Commit-Ready: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
74 files changed:
drivers/net/wireless/ath/Kconfig
drivers/net/wireless/ath/Makefile
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/ath9k_btcoex/Kconfig [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/Makefile [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ahb.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ani.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ani.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/antenna.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar5008_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar5008_phy.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9001_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9002_calib.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9002_hw.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9002_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9002_mac.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9002_phy.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9002_phy.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_2p2_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_calib.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_eeprom.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_eeprom.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_hw.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_mac.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_mac.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_mci.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_mci.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_paprd.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_phy.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_phy.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_rtt.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9003_rtt.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9330_1p1_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9330_1p2_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9340_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9462_2p0_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9485_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ar9580_1p0_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/ath9k.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/beacon.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/btcoex.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/btcoex.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/calib.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/calib.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/common.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/common.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/debug.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/debug.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/dfs.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/dfs.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/dfs_debug.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/dfs_debug.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/eeprom.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/eeprom.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/eeprom_4k.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/eeprom_9287.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/eeprom_def.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/gpio.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/hw-ops.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/hw.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/hw.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/init.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/mac.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/mac.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/main.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/mci.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/mci.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/pci.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/phy.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/rc.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/rc.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/recv.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/reg.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k_btcoex/xmit.c [new file with mode: 0644]

index 0960224..0b9a868 100644 (file)
@@ -24,6 +24,7 @@ config ATH_DEBUG
 
 source "drivers/net/wireless/ath/ath5k/Kconfig"
 source "drivers/net/wireless/ath/ath9k/Kconfig"
+source "drivers/net/wireless/ath/ath9k_btcoex/Kconfig"
 source "drivers/net/wireless/ath/carl9170/Kconfig"
 source "drivers/net/wireless/ath/ath6kl/Kconfig"
 
index d716b74..3f61aa2 100644 (file)
@@ -1,5 +1,6 @@
 obj-$(CONFIG_ATH5K)            += ath5k/
 obj-$(CONFIG_ATH9K_HW)         += ath9k/
+obj-$(CONFIG_ATH9K_HW)         += ath9k_btcoex/
 obj-$(CONFIG_CARL9170)         += carl9170/
 obj-$(CONFIG_ATH6KL)           += ath6kl/
 
index c42cc99..23ccd5b 100644 (file)
@@ -34,7 +34,6 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
        { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E  AR9300 */
        { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E  AR9485 */
        { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E  AR9580 */
-       { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E  AR9462 */
        { 0 }
 };
 
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/Kconfig b/drivers/net/wireless/ath/ath9k_btcoex/Kconfig
new file mode 100644 (file)
index 0000000..897c7c5
--- /dev/null
@@ -0,0 +1,24 @@
+config ATH9K_BTCOEX_HW
+       tristate
+config ATH9K_BTCOEX_COMMON
+       tristate
+
+config ATH9K_BTCOEX
+       tristate "Atheros 802.11n wireless cards support"
+       depends on MAC80211
+       select ATH9K_BTCOEX_HW
+       select MAC80211_LEDS
+       select LEDS_CLASS
+       select NEW_LEDS
+       select ATH9K_BTCOEX_COMMON
+       ---help---
+         This module adds support for wireless adapters based on
+         Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family
+         of chipsets. For a specific list of supported external
+         cards, laptops that already ship with these cards and
+         APs that come with these cards refer to to ath9k wiki
+         products page:
+
+         http://wireless.kernel.org/en/users/Drivers/ath9k/products
+
+         If you choose to build a module, it'll be called ath9k.
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/Makefile b/drivers/net/wireless/ath/ath9k_btcoex/Makefile
new file mode 100644 (file)
index 0000000..3c41427
--- /dev/null
@@ -0,0 +1,48 @@
+ath9k_btcoex-y += \
+               beacon.o \
+               gpio.o \
+               init.o \
+               main.o \
+               recv.o \
+               xmit.o \
+               antenna.o
+
+ath9k_btcoex-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
+ath9k_btcoex-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
+ath9k_btcoex-$(CONFIG_ATH9K_PCI) += pci.o
+ath9k_btcoex-$(CONFIG_ATH9K_AHB) += ahb.o
+ath9k_btcoex-$(CONFIG_ATH9K_DEBUGFS) += debug.o
+ath9k_btcoex-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
+ath9k_btcoex-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o
+
+obj-$(CONFIG_ATH9K_BTCOEX) += ath9k_btcoex.o
+
+ath9k_hw_btcoex-y:=    \
+               ar9002_hw.o \
+               ar9003_hw.o \
+               hw.o \
+               ar9003_phy.o \
+               ar9002_phy.o \
+               ar5008_phy.o \
+               ar9002_calib.o \
+               ar9003_calib.o \
+               ar9003_rtt.o \
+               calib.o \
+               eeprom.o \
+               eeprom_def.o \
+               eeprom_4k.o \
+               eeprom_9287.o \
+               ani.o \
+               mac.o \
+               ar9002_mac.o \
+               ar9003_mac.o \
+               ar9003_eeprom.o \
+               ar9003_paprd.o
+
+ath9k_hw_btcoex-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \
+                                          ar9003_mci.o
+obj-$(CONFIG_ATH9K_BTCOEX_HW) += ath9k_hw_btcoex.o
+
+obj-$(CONFIG_ATH9K_BTCOEX_COMMON) += ath9k_common_btcoex.o
+ath9k_common_btcoex-y:=        common.o
+
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ahb.c b/drivers/net/wireless/ath/ath9k_btcoex/ahb.c
new file mode 100644 (file)
index 0000000..357cd00
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/platform_device.h>
+#include <linux/ath9k_platform.h>
+#include <linux/module.h>
+#include "ath9k.h"
+
+static const struct platform_device_id ath9k_platform_id_table[] = {
+       {
+               .name = "ath9k",
+               .driver_data = AR5416_AR9100_DEVID,
+       },
+       {
+               .name = "ar933x_wmac",
+               .driver_data = AR9300_DEVID_AR9330,
+       },
+       {
+               .name = "ar934x_wmac",
+               .driver_data = AR9300_DEVID_AR9340,
+       },
+       {},
+};
+
+/* return bus cachesize in 4B word units */
+static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
+{
+       *csz = L1_CACHE_BYTES >> 2;
+}
+
+static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
+{
+       struct ath_softc *sc = (struct ath_softc *)common->priv;
+       struct platform_device *pdev = to_platform_device(sc->dev);
+       struct ath9k_platform_data *pdata;
+
+       pdata = (struct ath9k_platform_data *) pdev->dev.platform_data;
+       if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
+               ath_err(common,
+                       "%s: flash read failed, offset %08x is out of range\n",
+                       __func__, off);
+               return false;
+       }
+
+       *data = pdata->eeprom_data[off];
+       return true;
+}
+
+static struct ath_bus_ops ath_ahb_bus_ops  = {
+       .ath_bus_type = ATH_AHB,
+       .read_cachesize = ath_ahb_read_cachesize,
+       .eeprom_read = ath_ahb_eeprom_read,
+};
+
+static int ath_ahb_probe(struct platform_device *pdev)
+{
+       void __iomem *mem;
+       struct ath_softc *sc;
+       struct ieee80211_hw *hw;
+       struct resource *res;
+       const struct platform_device_id *id = platform_get_device_id(pdev);
+       int irq;
+       int ret = 0;
+       struct ath_hw *ah;
+       char hw_name[64];
+
+       if (!pdev->dev.platform_data) {
+               dev_err(&pdev->dev, "no platform data specified\n");
+               ret = -EINVAL;
+               goto err_out;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no memory resource found\n");
+               ret = -ENXIO;
+               goto err_out;
+       }
+
+       mem = ioremap_nocache(res->start, resource_size(res));
+       if (mem == NULL) {
+               dev_err(&pdev->dev, "ioremap failed\n");
+               ret = -ENOMEM;
+               goto err_out;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no IRQ resource found\n");
+               ret = -ENXIO;
+               goto err_iounmap;
+       }
+
+       irq = res->start;
+
+       hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
+       if (hw == NULL) {
+               dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
+               ret = -ENOMEM;
+               goto err_iounmap;
+       }
+
+       SET_IEEE80211_DEV(hw, &pdev->dev);
+       platform_set_drvdata(pdev, hw);
+
+       sc = hw->priv;
+       sc->hw = hw;
+       sc->dev = &pdev->dev;
+       sc->mem = mem;
+       sc->irq = irq;
+
+       /* Will be cleared in ath9k_start() */
+       set_bit(SC_OP_INVALID, &sc->sc_flags);
+
+       ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
+       if (ret) {
+               dev_err(&pdev->dev, "request_irq failed\n");
+               goto err_free_hw;
+       }
+
+       ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to initialize device\n");
+               goto err_irq;
+       }
+
+       ah = sc->sc_ah;
+       ath9k_btcoex_ath9k_hw_name(ah, hw_name, sizeof(hw_name));
+       wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+                  hw_name, (unsigned long)mem, irq);
+
+       return 0;
+
+ err_irq:
+       free_irq(irq, sc);
+ err_free_hw:
+       ieee80211_free_hw(hw);
+       platform_set_drvdata(pdev, NULL);
+ err_iounmap:
+       iounmap(mem);
+ err_out:
+       return ret;
+}
+
+static int ath_ahb_remove(struct platform_device *pdev)
+{
+       struct ieee80211_hw *hw = platform_get_drvdata(pdev);
+
+       if (hw) {
+               struct ath_softc *sc = hw->priv;
+               void __iomem *mem = sc->mem;
+
+               ath9k_deinit_device(sc);
+               free_irq(sc->irq, sc);
+               ieee80211_free_hw(sc->hw);
+               iounmap(mem);
+               platform_set_drvdata(pdev, NULL);
+       }
+
+       return 0;
+}
+
+static struct platform_driver ath_ahb_driver = {
+       .probe      = ath_ahb_probe,
+       .remove     = ath_ahb_remove,
+       .driver         = {
+               .name   = "ath9k",
+               .owner  = THIS_MODULE,
+       },
+       .id_table    = ath9k_platform_id_table,
+};
+
+MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table);
+
+int ath_ahb_init(void)
+{
+       return platform_driver_register(&ath_ahb_driver);
+}
+
+void ath_ahb_exit(void)
+{
+       platform_driver_unregister(&ath_ahb_driver);
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ani.c b/drivers/net/wireless/ath/ath9k_btcoex/ani.c
new file mode 100644 (file)
index 0000000..b642a22
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include "hw.h"
+#include "hw-ops.h"
+
+struct ani_ofdm_level_entry {
+       int spur_immunity_level;
+       int fir_step_level;
+       int ofdm_weak_signal_on;
+};
+
+/* values here are relative to the INI */
+
+/*
+ * Legend:
+ *
+ * SI: Spur immunity
+ * FS: FIR Step
+ * WS: OFDM / CCK Weak Signal detection
+ * MRC-CCK: Maximal Ratio Combining for CCK
+ */
+
+static const struct ani_ofdm_level_entry ofdm_level_table[] = {
+       /* SI  FS  WS */
+       {  0,  0,  1  }, /* lvl 0 */
+       {  1,  1,  1  }, /* lvl 1 */
+       {  2,  2,  1  }, /* lvl 2 */
+       {  3,  2,  1  }, /* lvl 3  (default) */
+       {  4,  3,  1  }, /* lvl 4 */
+       {  4,  3,  1  }, /* lvl 5 */
+       {  5,  4,  1  }, /* lvl 6 */
+       {  6,  5,  0  }, /* lvl 7 */
+       {  7,  6,  0  }, /* lvl 8 */
+       {  7,  7,  0  }, /* lvl 9 */
+};
+#define ATH9K_ANI_OFDM_NUM_LEVEL \
+       ARRAY_SIZE(ofdm_level_table)
+#define ATH9K_ANI_OFDM_MAX_LEVEL \
+       (ATH9K_ANI_OFDM_NUM_LEVEL-1)
+#define ATH9K_ANI_OFDM_DEF_LEVEL \
+       3 /* default level - matches the INI settings */
+
+/*
+ * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
+ * With OFDM for single stream you just add up all antenna inputs, you're
+ * only interested in what you get after FFT. Signal aligment is also not
+ * required for OFDM because any phase difference adds up in the frequency
+ * domain.
+ *
+ * MRC requires extra work for use with CCK. You need to align the antenna
+ * signals from the different antenna before you can add the signals together.
+ * You need aligment of signals as CCK is in time domain, so addition can cancel
+ * your signal completely if phase is 180 degrees (think of adding sine waves).
+ * You also need to remove noise before the addition and this is where ANI
+ * MRC CCK comes into play. One of the antenna inputs may be stronger but
+ * lower SNR, so just adding after alignment can be dangerous.
+ *
+ * Regardless of alignment in time, the antenna signals add constructively after
+ * FFT and improve your reception. For more information:
+ *
+ * http://en.wikipedia.org/wiki/Maximal-ratio_combining
+ */
+
+struct ani_cck_level_entry {
+       int fir_step_level;
+       int mrc_cck_on;
+};
+
+static const struct ani_cck_level_entry cck_level_table[] = {
+       /* FS  MRC-CCK  */
+       {  0,  1  }, /* lvl 0 */
+       {  1,  1  }, /* lvl 1 */
+       {  2,  1  }, /* lvl 2  (default) */
+       {  3,  1  }, /* lvl 3 */
+       {  4,  0  }, /* lvl 4 */
+       {  5,  0  }, /* lvl 5 */
+       {  6,  0  }, /* lvl 6 */
+       {  6,  0  }, /* lvl 7 (only for high rssi) */
+       {  7,  0  }  /* lvl 8 (only for high rssi) */
+};
+
+#define ATH9K_ANI_CCK_NUM_LEVEL \
+       ARRAY_SIZE(cck_level_table)
+#define ATH9K_ANI_CCK_MAX_LEVEL \
+       (ATH9K_ANI_CCK_NUM_LEVEL-1)
+#define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
+       (ATH9K_ANI_CCK_NUM_LEVEL-3)
+#define ATH9K_ANI_CCK_DEF_LEVEL \
+       2 /* default level - matches the INI settings */
+
+static void ath9k_hw_update_mibstats(struct ath_hw *ah,
+                                    struct ath9k_mib_stats *stats)
+{
+       stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
+       stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
+       stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
+       stats->rts_good += REG_READ(ah, AR_RTS_OK);
+       stats->beacons += REG_READ(ah, AR_BEACON_CNT);
+}
+
+static void ath9k_ani_restart(struct ath_hw *ah)
+{
+       struct ar5416AniState *aniState;
+
+       if (!DO_ANI(ah))
+               return;
+
+       aniState = &ah->curchan->ani;
+       aniState->listenTime = 0;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_PHY_ERR_1, 0);
+       REG_WRITE(ah, AR_PHY_ERR_2, 0);
+       REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+       REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+
+       aniState->ofdmPhyErrCount = 0;
+       aniState->cckPhyErrCount = 0;
+}
+
+/* Adjust the OFDM Noise Immunity Level */
+static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
+                                 bool scan)
+{
+       struct ar5416AniState *aniState = &ah->curchan->ani;
+       struct ath_common *common = ath9k_hw_common(ah);
+       const struct ani_ofdm_level_entry *entry_ofdm;
+       const struct ani_cck_level_entry *entry_cck;
+       bool weak_sig;
+
+       ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
+               aniState->ofdmNoiseImmunityLevel,
+               immunityLevel, BEACON_RSSI(ah),
+               aniState->rssiThrLow, aniState->rssiThrHigh);
+
+       if (!scan)
+               aniState->ofdmNoiseImmunityLevel = immunityLevel;
+
+       entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
+       entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
+
+       if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
+               ath9k_hw_ani_control(ah,
+                                    ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+                                    entry_ofdm->spur_immunity_level);
+
+       if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
+           entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
+               ath9k_hw_ani_control(ah,
+                                    ATH9K_ANI_FIRSTEP_LEVEL,
+                                    entry_ofdm->fir_step_level);
+
+       weak_sig = entry_ofdm->ofdm_weak_signal_on;
+       if (ah->opmode == NL80211_IFTYPE_STATION &&
+           BEACON_RSSI(ah) <= aniState->rssiThrHigh)
+               weak_sig = true;
+
+       if (aniState->ofdmWeakSigDetect != weak_sig)
+                       ath9k_hw_ani_control(ah,
+                               ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                               entry_ofdm->ofdm_weak_signal_on);
+
+       if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
+               ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
+               ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI;
+       } else {
+               ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI;
+               ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
+       }
+}
+
+static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
+{
+       struct ar5416AniState *aniState;
+
+       if (!DO_ANI(ah))
+               return;
+
+       aniState = &ah->curchan->ani;
+
+       if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
+               ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1,
+                                     false);
+}
+
+/*
+ * Set the ANI settings to match an CCK level.
+ */
+static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
+                                bool scan)
+{
+       struct ar5416AniState *aniState = &ah->curchan->ani;
+       struct ath_common *common = ath9k_hw_common(ah);
+       const struct ani_ofdm_level_entry *entry_ofdm;
+       const struct ani_cck_level_entry *entry_cck;
+
+       ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
+               aniState->cckNoiseImmunityLevel, immunityLevel,
+               BEACON_RSSI(ah), aniState->rssiThrLow,
+               aniState->rssiThrHigh);
+
+       if (ah->opmode == NL80211_IFTYPE_STATION &&
+           BEACON_RSSI(ah) <= aniState->rssiThrLow &&
+           immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
+               immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
+
+       if (!scan)
+               aniState->cckNoiseImmunityLevel = immunityLevel;
+
+       entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
+       entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
+
+       if (aniState->firstepLevel != entry_cck->fir_step_level &&
+           entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
+               ath9k_hw_ani_control(ah,
+                                    ATH9K_ANI_FIRSTEP_LEVEL,
+                                    entry_cck->fir_step_level);
+
+       /* Skip MRC CCK for pre AR9003 families */
+       if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah))
+               return;
+
+       if (aniState->mrcCCK != entry_cck->mrc_cck_on)
+               ath9k_hw_ani_control(ah,
+                                    ATH9K_ANI_MRC_CCK,
+                                    entry_cck->mrc_cck_on);
+}
+
+static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
+{
+       struct ar5416AniState *aniState;
+
+       if (!DO_ANI(ah))
+               return;
+
+       aniState = &ah->curchan->ani;
+
+       if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
+               ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1,
+                                    false);
+}
+
+/*
+ * only lower either OFDM or CCK errors per turn
+ * we lower the other one next time
+ */
+static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
+{
+       struct ar5416AniState *aniState;
+
+       aniState = &ah->curchan->ani;
+
+       /* lower OFDM noise immunity */
+       if (aniState->ofdmNoiseImmunityLevel > 0 &&
+           (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
+               ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1,
+                                     false);
+               return;
+       }
+
+       /* lower CCK noise immunity */
+       if (aniState->cckNoiseImmunityLevel > 0)
+               ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1,
+                                    false);
+}
+
+/*
+ * Restore the ANI parameters in the HAL and reset the statistics.
+ * This routine should be called for every hardware reset and for
+ * every channel change.
+ */
+void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
+{
+       struct ar5416AniState *aniState = &ah->curchan->ani;
+       struct ath9k_channel *chan = ah->curchan;
+       struct ath_common *common = ath9k_hw_common(ah);
+       int ofdm_nil, cck_nil;
+
+       if (!DO_ANI(ah))
+               return;
+
+       BUG_ON(aniState == NULL);
+       ah->stats.ast_ani_reset++;
+
+       /* only allow a subset of functions in AP mode */
+       if (ah->opmode == NL80211_IFTYPE_AP) {
+               if (IS_CHAN_2GHZ(chan)) {
+                       ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
+                                           ATH9K_ANI_FIRSTEP_LEVEL);
+                       if (AR_SREV_9300_20_OR_LATER(ah))
+                               ah->ani_function |= ATH9K_ANI_MRC_CCK;
+               } else
+                       ah->ani_function = 0;
+       }
+
+       /* always allow mode (on/off) to be controlled */
+       ah->ani_function |= ATH9K_ANI_MODE;
+
+       ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
+                        aniState->ofdmNoiseImmunityLevel);
+       cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
+                       aniState->cckNoiseImmunityLevel);
+
+       if (is_scanning ||
+           (ah->opmode != NL80211_IFTYPE_STATION &&
+            ah->opmode != NL80211_IFTYPE_ADHOC)) {
+               /*
+                * If we're scanning or in AP mode, the defaults (ini)
+                * should be in place. For an AP we assume the historical
+                * levels for this channel are probably outdated so start
+                * from defaults instead.
+                */
+               if (aniState->ofdmNoiseImmunityLevel !=
+                   ATH9K_ANI_OFDM_DEF_LEVEL ||
+                   aniState->cckNoiseImmunityLevel !=
+                   ATH9K_ANI_CCK_DEF_LEVEL) {
+                       ath_dbg(common, ANI,
+                               "Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
+                               ah->opmode,
+                               chan->channel,
+                               chan->channelFlags,
+                               is_scanning,
+                               aniState->ofdmNoiseImmunityLevel,
+                               aniState->cckNoiseImmunityLevel);
+
+                       ofdm_nil = ATH9K_ANI_OFDM_DEF_LEVEL;
+                       cck_nil = ATH9K_ANI_CCK_DEF_LEVEL;
+               }
+       } else {
+               /*
+                * restore historical levels for this channel
+                */
+               ath_dbg(common, ANI,
+                       "Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
+                       ah->opmode,
+                       chan->channel,
+                       chan->channelFlags,
+                       is_scanning,
+                       aniState->ofdmNoiseImmunityLevel,
+                       aniState->cckNoiseImmunityLevel);
+       }
+       ath9k_hw_set_ofdm_nil(ah, ofdm_nil, is_scanning);
+       ath9k_hw_set_cck_nil(ah, cck_nil, is_scanning);
+
+       /*
+        * enable phy counters if hw supports or if not, enable phy
+        * interrupts (so we can count each one)
+        */
+       ath9k_ani_restart(ah);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+       REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ar5416AniState *aniState = &ah->curchan->ani;
+       u32 phyCnt1, phyCnt2;
+       int32_t listenTime;
+
+       ath_hw_cycle_counters_update(common);
+       listenTime = ath_hw_get_listen_time(common);
+
+       if (listenTime <= 0) {
+               ah->stats.ast_ani_lneg_or_lzero++;
+               ath9k_ani_restart(ah);
+               return false;
+       }
+
+       aniState->listenTime += listenTime;
+
+       ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+
+       phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+       phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+
+       ah->stats.ast_ani_ofdmerrs += phyCnt1 - aniState->ofdmPhyErrCount;
+       aniState->ofdmPhyErrCount = phyCnt1;
+
+       ah->stats.ast_ani_cckerrs += phyCnt2 - aniState->cckPhyErrCount;
+       aniState->cckPhyErrCount = phyCnt2;
+
+       return true;
+}
+
+void ath9k_btcoex_ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       struct ar5416AniState *aniState;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 ofdmPhyErrRate, cckPhyErrRate;
+
+       if (!DO_ANI(ah))
+               return;
+
+       aniState = &ah->curchan->ani;
+       if (WARN_ON(!aniState))
+               return;
+
+       if (!ath9k_hw_ani_read_counters(ah))
+               return;
+
+       ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
+                        aniState->listenTime;
+       cckPhyErrRate =  aniState->cckPhyErrCount * 1000 /
+                        aniState->listenTime;
+
+       ath_dbg(common, ANI,
+               "listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n",
+               aniState->listenTime,
+               aniState->ofdmNoiseImmunityLevel,
+               ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
+               cckPhyErrRate, aniState->ofdmsTurn);
+       if (aniState->listenTime > ah->aniperiod) {
+               if (cckPhyErrRate < ah->config.cck_trig_low &&
+                   ofdmPhyErrRate < ah->config.ofdm_trig_low) {
+                       ath9k_hw_ani_lower_immunity(ah);
+                       aniState->ofdmsTurn = !aniState->ofdmsTurn;
+               } else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) {
+                       ath9k_hw_ani_ofdm_err_trigger(ah);
+                       aniState->ofdmsTurn = false;
+               } else if (cckPhyErrRate > ah->config.cck_trig_high) {
+                       ath9k_hw_ani_cck_err_trigger(ah);
+                       aniState->ofdmsTurn = true;
+               }
+               ath9k_ani_restart(ah);
+       }
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_ani_monitor);
+
+void ath9k_enable_mib_counters(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       ath_dbg(common, ANI, "Enable MIB counters\n");
+
+       ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_FILT_OFDM, 0);
+       REG_WRITE(ah, AR_FILT_CCK, 0);
+       REG_WRITE(ah, AR_MIBC,
+                 ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
+                 & 0x0f);
+       REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+       REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+/* Freeze the MIB counters, get the stats and then clear them */
+void ath9k_btcoex_ath9k_hw_disable_mib_counters(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       ath_dbg(common, ANI, "Disable MIB counters\n");
+
+       REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
+       ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+       REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
+       REG_WRITE(ah, AR_FILT_OFDM, 0);
+       REG_WRITE(ah, AR_FILT_CCK, 0);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_disable_mib_counters);
+
+void ath9k_hw_ani_setup(struct ath_hw *ah)
+{
+       int i;
+
+       static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
+       static const int coarseHigh[] = { -14, -14, -14, -14, -12 };
+       static const int coarseLow[] = { -64, -64, -64, -64, -70 };
+       static const int firpwr[] = { -78, -78, -78, -78, -80 };
+
+       for (i = 0; i < 5; i++) {
+               ah->totalSizeDesired[i] = totalSizeDesired[i];
+               ah->coarse_high[i] = coarseHigh[i];
+               ah->coarse_low[i] = coarseLow[i];
+               ah->firpwr[i] = firpwr[i];
+       }
+}
+
+void ath9k_hw_ani_init(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       int i;
+
+       ath_dbg(common, ANI, "Initialize ANI\n");
+
+       ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
+       ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
+
+       ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
+       ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
+
+       for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
+               struct ath9k_channel *chan = &ah->channels[i];
+               struct ar5416AniState *ani = &chan->ani;
+
+               ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
+
+               ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
+
+               ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false;
+
+               ani->ofdmsTurn = true;
+
+               ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
+               ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
+               ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
+               ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+               ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
+       }
+
+       /*
+        * since we expect some ongoing maintenance on the tables, let's sanity
+        * check here default level should not modify INI setting.
+        */
+       ah->aniperiod = ATH9K_ANI_PERIOD;
+       ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL;
+
+       if (ah->config.enable_ani)
+               ah->proc_phyerr |= HAL_PROCESS_ANI;
+
+       ath9k_ani_restart(ah);
+       ath9k_enable_mib_counters(ah);
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ani.h b/drivers/net/wireless/ath/ath9k_btcoex/ani.h
new file mode 100644 (file)
index 0000000..372a8dc
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ANI_H
+#define ANI_H
+
+#define HAL_PROCESS_ANI           0x00000001
+
+#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI) && ah->curchan)
+
+#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
+
+/* units are errors per second */
+#define ATH9K_ANI_OFDM_TRIG_HIGH          3500
+#define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000
+
+/* units are errors per second */
+#define ATH9K_ANI_OFDM_TRIG_LOW           400
+#define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900
+
+/* units are errors per second */
+#define ATH9K_ANI_CCK_TRIG_HIGH           600
+
+/* units are errors per second */
+#define ATH9K_ANI_CCK_TRIG_LOW            300
+
+#define ATH9K_ANI_NOISE_IMMUNE_LVL        4
+#define ATH9K_ANI_USE_OFDM_WEAK_SIG       true
+#define ATH9K_ANI_CCK_WEAK_SIG_THR        false
+
+#define ATH9K_ANI_SPUR_IMMUNE_LVL         3
+
+#define ATH9K_ANI_FIRSTEP_LVL             2
+
+#define ATH9K_ANI_RSSI_THR_HIGH           40
+#define ATH9K_ANI_RSSI_THR_LOW            7
+
+#define ATH9K_ANI_PERIOD                  300
+
+/* in ms */
+#define ATH9K_ANI_POLLINTERVAL            1000
+
+#define HAL_NOISE_IMMUNE_MAX              4
+#define HAL_SPUR_IMMUNE_MAX               7
+#define HAL_FIRST_STEP_MAX                2
+
+#define ATH9K_SIG_FIRSTEP_SETTING_MIN     0
+#define ATH9K_SIG_FIRSTEP_SETTING_MAX     20
+#define ATH9K_SIG_SPUR_IMM_SETTING_MIN    0
+#define ATH9K_SIG_SPUR_IMM_SETTING_MAX    22
+
+/* values here are relative to the INI */
+
+enum ath9k_ani_cmd {
+       ATH9K_ANI_PRESENT = 0x1,
+       ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2,
+       ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4,
+       ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8,
+       ATH9K_ANI_FIRSTEP_LEVEL = 0x10,
+       ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20,
+       ATH9K_ANI_MODE = 0x40,
+       ATH9K_ANI_PHYERR_RESET = 0x80,
+       ATH9K_ANI_MRC_CCK = 0x100,
+       ATH9K_ANI_ALL = 0xfff
+};
+
+struct ath9k_mib_stats {
+       u32 ackrcv_bad;
+       u32 rts_bad;
+       u32 rts_good;
+       u32 fcs_bad;
+       u32 beacons;
+};
+
+/* INI default values for ANI registers */
+struct ath9k_ani_default {
+       u16 m1ThreshLow;
+       u16 m2ThreshLow;
+       u16 m1Thresh;
+       u16 m2Thresh;
+       u16 m2CountThr;
+       u16 m2CountThrLow;
+       u16 m1ThreshLowExt;
+       u16 m2ThreshLowExt;
+       u16 m1ThreshExt;
+       u16 m2ThreshExt;
+       u16 firstep;
+       u16 firstepLow;
+       u16 cycpwrThr1;
+       u16 cycpwrThr1Ext;
+};
+
+struct ar5416AniState {
+       struct ath9k_channel *c;
+       u8 noiseImmunityLevel;
+       u8 ofdmNoiseImmunityLevel;
+       u8 cckNoiseImmunityLevel;
+       bool ofdmsTurn;
+       u8 mrcCCK;
+       u8 spurImmunityLevel;
+       u8 firstepLevel;
+       u8 ofdmWeakSigDetect;
+       u8 cckWeakSigThreshold;
+       u32 listenTime;
+       int32_t rssiThrLow;
+       int32_t rssiThrHigh;
+       u32 ofdmPhyErrCount;
+       u32 cckPhyErrCount;
+       int16_t pktRssi[2];
+       int16_t ofdmErrRssi[2];
+       int16_t cckErrRssi[2];
+       struct ath9k_ani_default iniDef;
+};
+
+struct ar5416Stats {
+       u32 ast_ani_niup;
+       u32 ast_ani_nidown;
+       u32 ast_ani_spurup;
+       u32 ast_ani_spurdown;
+       u32 ast_ani_ofdmon;
+       u32 ast_ani_ofdmoff;
+       u32 ast_ani_cckhigh;
+       u32 ast_ani_ccklow;
+       u32 ast_ani_stepup;
+       u32 ast_ani_stepdown;
+       u32 ast_ani_ofdmerrs;
+       u32 ast_ani_cckerrs;
+       u32 ast_ani_reset;
+       u32 ast_ani_lneg_or_lzero;
+       u32 avgbrssi;
+       struct ath9k_mib_stats ast_mibstats;
+};
+#define ah_mibStats stats.ast_mibstats
+
+void ath9k_enable_mib_counters(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_disable_mib_counters(struct ath_hw *ah);
+void ath9k_hw_ani_setup(struct ath_hw *ah);
+void ath9k_hw_ani_init(struct ath_hw *ah);
+
+#endif /* ANI_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/antenna.c b/drivers/net/wireless/ath/ath9k_btcoex/antenna.c
new file mode 100644 (file)
index 0000000..bbcfeb3
--- /dev/null
@@ -0,0 +1,776 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta,
+                                              int mindelta, int main_rssi_avg,
+                                              int alt_rssi_avg, int pkt_count)
+{
+       return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
+                (alt_rssi_avg > main_rssi_avg + maxdelta)) ||
+               (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50);
+}
+
+static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio,
+                                             int curr_main_set, int curr_alt_set,
+                                             int alt_rssi_avg, int main_rssi_avg)
+{
+       bool result = false;
+       switch (div_group) {
+       case 0:
+               if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
+                       result = true;
+               break;
+       case 1:
+       case 2:
+               if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) &&
+                     (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) &&
+                     (alt_rssi_avg >= (main_rssi_avg - 5))) ||
+                    ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) &&
+                     (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) &&
+                     (alt_rssi_avg >= (main_rssi_avg - 2)))) &&
+                   (alt_rssi_avg >= 4))
+                       result = true;
+               else
+                       result = false;
+               break;
+       }
+
+       return result;
+}
+
+static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
+                                     struct ath_hw_antcomb_conf ant_conf,
+                                     int main_rssi_avg)
+{
+       antcomb->quick_scan_cnt = 0;
+
+       if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
+               antcomb->rssi_lna2 = main_rssi_avg;
+       else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1)
+               antcomb->rssi_lna1 = main_rssi_avg;
+
+       switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
+       case 0x10: /* LNA2 A-B */
+               antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+               antcomb->first_quick_scan_conf =
+                       ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+               antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
+               break;
+       case 0x20: /* LNA1 A-B */
+               antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+               antcomb->first_quick_scan_conf =
+                       ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+               antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
+               break;
+       case 0x21: /* LNA1 LNA2 */
+               antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
+               antcomb->first_quick_scan_conf =
+                       ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+               antcomb->second_quick_scan_conf =
+                       ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+               break;
+       case 0x12: /* LNA2 LNA1 */
+               antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
+               antcomb->first_quick_scan_conf =
+                       ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+               antcomb->second_quick_scan_conf =
+                       ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+               break;
+       case 0x13: /* LNA2 A+B */
+               antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+               antcomb->first_quick_scan_conf =
+                       ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+               antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
+               break;
+       case 0x23: /* LNA1 A+B */
+               antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+               antcomb->first_quick_scan_conf =
+                       ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+               antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
+               break;
+       default:
+               break;
+       }
+}
+
+static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
+                                      struct ath_hw_antcomb_conf *div_ant_conf,
+                                      int main_rssi_avg, int alt_rssi_avg,
+                                      int alt_ratio)
+{
+       /* alt_good */
+       switch (antcomb->quick_scan_cnt) {
+       case 0:
+               /* set alt to main, and alt to first conf */
+               div_ant_conf->main_lna_conf = antcomb->main_conf;
+               div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf;
+               break;
+       case 1:
+               /* set alt to main, and alt to first conf */
+               div_ant_conf->main_lna_conf = antcomb->main_conf;
+               div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf;
+               antcomb->rssi_first = main_rssi_avg;
+               antcomb->rssi_second = alt_rssi_avg;
+
+               if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
+                       /* main is LNA1 */
+                       if (ath_is_alt_ant_ratio_better(alt_ratio,
+                                               ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
+                                               ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+                                               main_rssi_avg, alt_rssi_avg,
+                                               antcomb->total_pkt_count))
+                               antcomb->first_ratio = true;
+                       else
+                               antcomb->first_ratio = false;
+               } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
+                       if (ath_is_alt_ant_ratio_better(alt_ratio,
+                                               ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
+                                               ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+                                               main_rssi_avg, alt_rssi_avg,
+                                               antcomb->total_pkt_count))
+                               antcomb->first_ratio = true;
+                       else
+                               antcomb->first_ratio = false;
+               } else {
+                       if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
+                             (alt_rssi_avg > main_rssi_avg +
+                              ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
+                            (alt_rssi_avg > main_rssi_avg)) &&
+                           (antcomb->total_pkt_count > 50))
+                               antcomb->first_ratio = true;
+                       else
+                               antcomb->first_ratio = false;
+               }
+               break;
+       case 2:
+               antcomb->alt_good = false;
+               antcomb->scan_not_start = false;
+               antcomb->scan = false;
+               antcomb->rssi_first = main_rssi_avg;
+               antcomb->rssi_third = alt_rssi_avg;
+
+               if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1)
+                       antcomb->rssi_lna1 = alt_rssi_avg;
+               else if (antcomb->second_quick_scan_conf ==
+                        ATH_ANT_DIV_COMB_LNA2)
+                       antcomb->rssi_lna2 = alt_rssi_avg;
+               else if (antcomb->second_quick_scan_conf ==
+                        ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) {
+                       if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)
+                               antcomb->rssi_lna2 = main_rssi_avg;
+                       else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1)
+                               antcomb->rssi_lna1 = main_rssi_avg;
+               }
+
+               if (antcomb->rssi_lna2 > antcomb->rssi_lna1 +
+                   ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)
+                       div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+               else
+                       div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+
+               if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
+                       if (ath_is_alt_ant_ratio_better(alt_ratio,
+                                               ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
+                                               ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+                                               main_rssi_avg, alt_rssi_avg,
+                                               antcomb->total_pkt_count))
+                               antcomb->second_ratio = true;
+                       else
+                               antcomb->second_ratio = false;
+               } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
+                       if (ath_is_alt_ant_ratio_better(alt_ratio,
+                                               ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
+                                               ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+                                               main_rssi_avg, alt_rssi_avg,
+                                               antcomb->total_pkt_count))
+                               antcomb->second_ratio = true;
+                       else
+                               antcomb->second_ratio = false;
+               } else {
+                       if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
+                             (alt_rssi_avg > main_rssi_avg +
+                              ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
+                            (alt_rssi_avg > main_rssi_avg)) &&
+                           (antcomb->total_pkt_count > 50))
+                               antcomb->second_ratio = true;
+                       else
+                               antcomb->second_ratio = false;
+               }
+
+               /* set alt to the conf with maximun ratio */
+               if (antcomb->first_ratio && antcomb->second_ratio) {
+                       if (antcomb->rssi_second > antcomb->rssi_third) {
+                               /* first alt*/
+                               if ((antcomb->first_quick_scan_conf ==
+                                   ATH_ANT_DIV_COMB_LNA1) ||
+                                   (antcomb->first_quick_scan_conf ==
+                                   ATH_ANT_DIV_COMB_LNA2))
+                                       /* Set alt LNA1 or LNA2*/
+                                       if (div_ant_conf->main_lna_conf ==
+                                           ATH_ANT_DIV_COMB_LNA2)
+                                               div_ant_conf->alt_lna_conf =
+                                                       ATH_ANT_DIV_COMB_LNA1;
+                                       else
+                                               div_ant_conf->alt_lna_conf =
+                                                       ATH_ANT_DIV_COMB_LNA2;
+                               else
+                                       /* Set alt to A+B or A-B */
+                                       div_ant_conf->alt_lna_conf =
+                                               antcomb->first_quick_scan_conf;
+                       } else if ((antcomb->second_quick_scan_conf ==
+                                  ATH_ANT_DIV_COMB_LNA1) ||
+                                  (antcomb->second_quick_scan_conf ==
+                                  ATH_ANT_DIV_COMB_LNA2)) {
+                               /* Set alt LNA1 or LNA2 */
+                               if (div_ant_conf->main_lna_conf ==
+                                   ATH_ANT_DIV_COMB_LNA2)
+                                       div_ant_conf->alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                               else
+                                       div_ant_conf->alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA2;
+                       } else {
+                               /* Set alt to A+B or A-B */
+                               div_ant_conf->alt_lna_conf =
+                                       antcomb->second_quick_scan_conf;
+                       }
+               } else if (antcomb->first_ratio) {
+                       /* first alt */
+                       if ((antcomb->first_quick_scan_conf ==
+                           ATH_ANT_DIV_COMB_LNA1) ||
+                           (antcomb->first_quick_scan_conf ==
+                           ATH_ANT_DIV_COMB_LNA2))
+                                       /* Set alt LNA1 or LNA2 */
+                               if (div_ant_conf->main_lna_conf ==
+                                   ATH_ANT_DIV_COMB_LNA2)
+                                       div_ant_conf->alt_lna_conf =
+                                                       ATH_ANT_DIV_COMB_LNA1;
+                               else
+                                       div_ant_conf->alt_lna_conf =
+                                                       ATH_ANT_DIV_COMB_LNA2;
+                       else
+                               /* Set alt to A+B or A-B */
+                               div_ant_conf->alt_lna_conf =
+                                               antcomb->first_quick_scan_conf;
+               } else if (antcomb->second_ratio) {
+                               /* second alt */
+                       if ((antcomb->second_quick_scan_conf ==
+                           ATH_ANT_DIV_COMB_LNA1) ||
+                           (antcomb->second_quick_scan_conf ==
+                           ATH_ANT_DIV_COMB_LNA2))
+                               /* Set alt LNA1 or LNA2 */
+                               if (div_ant_conf->main_lna_conf ==
+                                   ATH_ANT_DIV_COMB_LNA2)
+                                       div_ant_conf->alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                               else
+                                       div_ant_conf->alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA2;
+                       else
+                               /* Set alt to A+B or A-B */
+                               div_ant_conf->alt_lna_conf =
+                                               antcomb->second_quick_scan_conf;
+               } else {
+                       /* main is largest */
+                       if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) ||
+                           (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2))
+                               /* Set alt LNA1 or LNA2 */
+                               if (div_ant_conf->main_lna_conf ==
+                                   ATH_ANT_DIV_COMB_LNA2)
+                                       div_ant_conf->alt_lna_conf =
+                                                       ATH_ANT_DIV_COMB_LNA1;
+                               else
+                                       div_ant_conf->alt_lna_conf =
+                                                       ATH_ANT_DIV_COMB_LNA2;
+                       else
+                               /* Set alt to A+B or A-B */
+                               div_ant_conf->alt_lna_conf = antcomb->main_conf;
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
+                                         struct ath_ant_comb *antcomb,
+                                         int alt_ratio)
+{
+       if (ant_conf->div_group == 0) {
+               /* Adjust the fast_div_bias based on main and alt lna conf */
+               switch ((ant_conf->main_lna_conf << 4) |
+                               ant_conf->alt_lna_conf) {
+               case 0x01: /* A-B LNA2 */
+                       ant_conf->fast_div_bias = 0x3b;
+                       break;
+               case 0x02: /* A-B LNA1 */
+                       ant_conf->fast_div_bias = 0x3d;
+                       break;
+               case 0x03: /* A-B A+B */
+                       ant_conf->fast_div_bias = 0x1;
+                       break;
+               case 0x10: /* LNA2 A-B */
+                       ant_conf->fast_div_bias = 0x7;
+                       break;
+               case 0x12: /* LNA2 LNA1 */
+                       ant_conf->fast_div_bias = 0x2;
+                       break;
+               case 0x13: /* LNA2 A+B */
+                       ant_conf->fast_div_bias = 0x7;
+                       break;
+               case 0x20: /* LNA1 A-B */
+                       ant_conf->fast_div_bias = 0x6;
+                       break;
+               case 0x21: /* LNA1 LNA2 */
+                       ant_conf->fast_div_bias = 0x0;
+                       break;
+               case 0x23: /* LNA1 A+B */
+                       ant_conf->fast_div_bias = 0x6;
+                       break;
+               case 0x30: /* A+B A-B */
+                       ant_conf->fast_div_bias = 0x1;
+                       break;
+               case 0x31: /* A+B LNA2 */
+                       ant_conf->fast_div_bias = 0x3b;
+                       break;
+               case 0x32: /* A+B LNA1 */
+                       ant_conf->fast_div_bias = 0x3d;
+                       break;
+               default:
+                       break;
+               }
+       } else if (ant_conf->div_group == 1) {
+               /* Adjust the fast_div_bias based on main and alt_lna_conf */
+               switch ((ant_conf->main_lna_conf << 4) |
+                       ant_conf->alt_lna_conf) {
+               case 0x01: /* A-B LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x02: /* A-B LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x03: /* A-B A+B */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x10: /* LNA2 A-B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x12: /* LNA2 LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x13: /* LNA2 A+B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x20: /* LNA1 A-B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x21: /* LNA1 LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x23: /* LNA1 A+B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x30: /* A+B A-B */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x31: /* A+B LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x32: /* A+B LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               default:
+                       break;
+               }
+       } else if (ant_conf->div_group == 2) {
+               /* Adjust the fast_div_bias based on main and alt_lna_conf */
+               switch ((ant_conf->main_lna_conf << 4) |
+                               ant_conf->alt_lna_conf) {
+               case 0x01: /* A-B LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x02: /* A-B LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x03: /* A-B A+B */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x10: /* LNA2 A-B */
+                       if (!(antcomb->scan) &&
+                               (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x1;
+                       else
+                               ant_conf->fast_div_bias = 0x2;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x12: /* LNA2 LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x13: /* LNA2 A+B */
+                       if (!(antcomb->scan) &&
+                               (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x1;
+                       else
+                               ant_conf->fast_div_bias = 0x2;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x20: /* LNA1 A-B */
+                       if (!(antcomb->scan) &&
+                               (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x1;
+                       else
+                               ant_conf->fast_div_bias = 0x2;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x21: /* LNA1 LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x23: /* LNA1 A+B */
+                       if (!(antcomb->scan) &&
+                               (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x1;
+                       else
+                               ant_conf->fast_div_bias = 0x2;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x30: /* A+B A-B */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x31: /* A+B LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x32: /* A+B LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
+{
+       struct ath_hw_antcomb_conf div_ant_conf;
+       struct ath_ant_comb *antcomb = &sc->ant_comb;
+       int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
+       int curr_main_set;
+       int main_rssi = rs->rs_rssi_ctl0;
+       int alt_rssi = rs->rs_rssi_ctl1;
+       int rx_ant_conf,  main_ant_conf;
+       bool short_scan = false;
+
+       rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
+                      ATH_ANT_RX_MASK;
+       main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
+                        ATH_ANT_RX_MASK;
+
+       /* Record packet only when both main_rssi and  alt_rssi is positive */
+       if (main_rssi > 0 && alt_rssi > 0) {
+               antcomb->total_pkt_count++;
+               antcomb->main_total_rssi += main_rssi;
+               antcomb->alt_total_rssi  += alt_rssi;
+               if (main_ant_conf == rx_ant_conf)
+                       antcomb->main_recv_cnt++;
+               else
+                       antcomb->alt_recv_cnt++;
+       }
+
+       /* Short scan check */
+       if (antcomb->scan && antcomb->alt_good) {
+               if (time_after(jiffies, antcomb->scan_start_time +
+                   msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR)))
+                       short_scan = true;
+               else
+                       if (antcomb->total_pkt_count ==
+                           ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) {
+                               alt_ratio = ((antcomb->alt_recv_cnt * 100) /
+                                           antcomb->total_pkt_count);
+                               if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
+                                       short_scan = true;
+                       }
+       }
+
+       if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) ||
+           rs->rs_moreaggr) && !short_scan)
+               return;
+
+       if (antcomb->total_pkt_count) {
+               alt_ratio = ((antcomb->alt_recv_cnt * 100) /
+                            antcomb->total_pkt_count);
+               main_rssi_avg = (antcomb->main_total_rssi /
+                                antcomb->total_pkt_count);
+               alt_rssi_avg = (antcomb->alt_total_rssi /
+                                antcomb->total_pkt_count);
+       }
+
+
+       ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf);
+       curr_alt_set = div_ant_conf.alt_lna_conf;
+       curr_main_set = div_ant_conf.main_lna_conf;
+
+       antcomb->count++;
+
+       if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) {
+               if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
+                       ath_lnaconf_alt_good_scan(antcomb, div_ant_conf,
+                                                 main_rssi_avg);
+                       antcomb->alt_good = true;
+               } else {
+                       antcomb->alt_good = false;
+               }
+
+               antcomb->count = 0;
+               antcomb->scan = true;
+               antcomb->scan_not_start = true;
+       }
+
+       if (!antcomb->scan) {
+               if (ath_ant_div_comb_alt_check(div_ant_conf.div_group,
+                                       alt_ratio, curr_main_set, curr_alt_set,
+                                       alt_rssi_avg, main_rssi_avg)) {
+                       if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) {
+                               /* Switch main and alt LNA */
+                               div_ant_conf.main_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA2;
+                               div_ant_conf.alt_lna_conf  =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                       } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) {
+                               div_ant_conf.main_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                               div_ant_conf.alt_lna_conf  =
+                                               ATH_ANT_DIV_COMB_LNA2;
+                       }
+
+                       goto div_comb_done;
+               } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) &&
+                          (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) {
+                       /* Set alt to another LNA */
+                       if (curr_main_set == ATH_ANT_DIV_COMB_LNA2)
+                               div_ant_conf.alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                       else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1)
+                               div_ant_conf.alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA2;
+
+                       goto div_comb_done;
+               }
+
+               if ((alt_rssi_avg < (main_rssi_avg +
+                                    div_ant_conf.lna1_lna2_delta)))
+                       goto div_comb_done;
+       }
+
+       if (!antcomb->scan_not_start) {
+               switch (curr_alt_set) {
+               case ATH_ANT_DIV_COMB_LNA2:
+                       antcomb->rssi_lna2 = alt_rssi_avg;
+                       antcomb->rssi_lna1 = main_rssi_avg;
+                       antcomb->scan = true;
+                       /* set to A+B */
+                       div_ant_conf.main_lna_conf =
+                               ATH_ANT_DIV_COMB_LNA1;
+                       div_ant_conf.alt_lna_conf  =
+                               ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+                       break;
+               case ATH_ANT_DIV_COMB_LNA1:
+                       antcomb->rssi_lna1 = alt_rssi_avg;
+                       antcomb->rssi_lna2 = main_rssi_avg;
+                       antcomb->scan = true;
+                       /* set to A+B */
+                       div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+                       div_ant_conf.alt_lna_conf  =
+                               ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+                       break;
+               case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2:
+                       antcomb->rssi_add = alt_rssi_avg;
+                       antcomb->scan = true;
+                       /* set to A-B */
+                       div_ant_conf.alt_lna_conf =
+                               ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+                       break;
+               case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2:
+                       antcomb->rssi_sub = alt_rssi_avg;
+                       antcomb->scan = false;
+                       if (antcomb->rssi_lna2 >
+                           (antcomb->rssi_lna1 +
+                           ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) {
+                               /* use LNA2 as main LNA */
+                               if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
+                                   (antcomb->rssi_add > antcomb->rssi_sub)) {
+                                       /* set to A+B */
+                                       div_ant_conf.main_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA2;
+                                       div_ant_conf.alt_lna_conf  =
+                                               ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+                               } else if (antcomb->rssi_sub >
+                                          antcomb->rssi_lna1) {
+                                       /* set to A-B */
+                                       div_ant_conf.main_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA2;
+                                       div_ant_conf.alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+                               } else {
+                                       /* set to LNA1 */
+                                       div_ant_conf.main_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA2;
+                                       div_ant_conf.alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                               }
+                       } else {
+                               /* use LNA1 as main LNA */
+                               if ((antcomb->rssi_add > antcomb->rssi_lna2) &&
+                                   (antcomb->rssi_add > antcomb->rssi_sub)) {
+                                       /* set to A+B */
+                                       div_ant_conf.main_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                                       div_ant_conf.alt_lna_conf  =
+                                               ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+                               } else if (antcomb->rssi_sub >
+                                          antcomb->rssi_lna1) {
+                                       /* set to A-B */
+                                       div_ant_conf.main_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                                       div_ant_conf.alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+                               } else {
+                                       /* set to LNA2 */
+                                       div_ant_conf.main_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                                       div_ant_conf.alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA2;
+                               }
+                       }
+                       break;
+               default:
+                       break;
+               }
+       } else {
+               if (!antcomb->alt_good) {
+                       antcomb->scan_not_start = false;
+                       /* Set alt to another LNA */
+                       if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) {
+                               div_ant_conf.main_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA2;
+                               div_ant_conf.alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                       } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) {
+                               div_ant_conf.main_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA1;
+                               div_ant_conf.alt_lna_conf =
+                                               ATH_ANT_DIV_COMB_LNA2;
+                       }
+                       goto div_comb_done;
+               }
+       }
+
+       ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf,
+                                          main_rssi_avg, alt_rssi_avg,
+                                          alt_ratio);
+
+       antcomb->quick_scan_cnt++;
+
+div_comb_done:
+       ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio);
+       ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf);
+
+       antcomb->scan_start_time = jiffies;
+       antcomb->total_pkt_count = 0;
+       antcomb->main_total_rssi = 0;
+       antcomb->alt_total_rssi = 0;
+       antcomb->main_recv_cnt = 0;
+       antcomb->alt_recv_cnt = 0;
+}
+
+void ath_ant_comb_update(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_hw_antcomb_conf div_ant_conf;
+       u8 lna_conf;
+
+       ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
+
+       if (sc->ant_rx == 1)
+               lna_conf = ATH_ANT_DIV_COMB_LNA1;
+       else
+               lna_conf = ATH_ANT_DIV_COMB_LNA2;
+
+       div_ant_conf.main_lna_conf = lna_conf;
+       div_ant_conf.alt_lna_conf = lna_conf;
+
+       ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar5008_initvals.h b/drivers/net/wireless/ath/ath9k_btcoex/ar5008_initvals.h
new file mode 100644 (file)
index 0000000..f81e7fc
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+static const u32 ar5416Modes[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0},
+       {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de},
+       {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
+       {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
+       {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134},
+       {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
+       {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+       {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+       {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+       {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+       {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120},
+       {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
+       {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+       {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
+       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+       {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+       {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+       {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+       {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+       {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+       {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+       {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+       {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+       {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+       {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+       {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+       {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+       {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+       {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+       {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar5416Common[][2] = {
+       /* Addr      allmodes  */
+       {0x0000000c, 0x00000000},
+       {0x00000030, 0x00020015},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000008},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00000054, 0x0000001f},
+       {0x00000800, 0x00000000},
+       {0x00000804, 0x00000000},
+       {0x00000808, 0x00000000},
+       {0x0000080c, 0x00000000},
+       {0x00000810, 0x00000000},
+       {0x00000814, 0x00000000},
+       {0x00000818, 0x00000000},
+       {0x0000081c, 0x00000000},
+       {0x00000820, 0x00000000},
+       {0x00000824, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x00001230, 0x00000000},
+       {0x00001270, 0x00000000},
+       {0x00001038, 0x00000000},
+       {0x00001078, 0x00000000},
+       {0x000010b8, 0x00000000},
+       {0x000010f8, 0x00000000},
+       {0x00001138, 0x00000000},
+       {0x00001178, 0x00000000},
+       {0x000011b8, 0x00000000},
+       {0x000011f8, 0x00000000},
+       {0x00001238, 0x00000000},
+       {0x00001278, 0x00000000},
+       {0x000012b8, 0x00000000},
+       {0x000012f8, 0x00000000},
+       {0x00001338, 0x00000000},
+       {0x00001378, 0x00000000},
+       {0x000013b8, 0x00000000},
+       {0x000013f8, 0x00000000},
+       {0x00001438, 0x00000000},
+       {0x00001478, 0x00000000},
+       {0x000014b8, 0x00000000},
+       {0x000014f8, 0x00000000},
+       {0x00001538, 0x00000000},
+       {0x00001578, 0x00000000},
+       {0x000015b8, 0x00000000},
+       {0x000015f8, 0x00000000},
+       {0x00001638, 0x00000000},
+       {0x00001678, 0x00000000},
+       {0x000016b8, 0x00000000},
+       {0x000016f8, 0x00000000},
+       {0x00001738, 0x00000000},
+       {0x00001778, 0x00000000},
+       {0x000017b8, 0x00000000},
+       {0x000017f8, 0x00000000},
+       {0x0000103c, 0x00000000},
+       {0x0000107c, 0x00000000},
+       {0x000010bc, 0x00000000},
+       {0x000010fc, 0x00000000},
+       {0x0000113c, 0x00000000},
+       {0x0000117c, 0x00000000},
+       {0x000011bc, 0x00000000},
+       {0x000011fc, 0x00000000},
+       {0x0000123c, 0x00000000},
+       {0x0000127c, 0x00000000},
+       {0x000012bc, 0x00000000},
+       {0x000012fc, 0x00000000},
+       {0x0000133c, 0x00000000},
+       {0x0000137c, 0x00000000},
+       {0x000013bc, 0x00000000},
+       {0x000013fc, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00004030, 0x00000002},
+       {0x0000403c, 0x00000002},
+       {0x00007010, 0x00000000},
+       {0x00007038, 0x000004c2},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000700},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008048, 0x40000000},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x000080c0, 0x2a82301a},
+       {0x000080c4, 0x05dc01e0},
+       {0x000080c8, 0x1f402710},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00001e00},
+       {0x000080d4, 0x00000000},
+       {0x000080d8, 0x00400000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x003f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080f8, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00020000},
+       {0x00008104, 0x00000001},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000168},
+       {0x00008118, 0x000100aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x00000000},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x32143320},
+       {0x00008174, 0xfaa4fa50},
+       {0x00008178, 0x00000100},
+       {0x0000817c, 0x00000000},
+       {0x000081c4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008200, 0x00000000},
+       {0x00008204, 0x00000000},
+       {0x00008208, 0x00000000},
+       {0x0000820c, 0x00000000},
+       {0x00008210, 0x00000000},
+       {0x00008214, 0x00000000},
+       {0x00008218, 0x00000000},
+       {0x0000821c, 0x00000000},
+       {0x00008220, 0x00000000},
+       {0x00008224, 0x00000000},
+       {0x00008228, 0x00000000},
+       {0x0000822c, 0x00000000},
+       {0x00008230, 0x00000000},
+       {0x00008234, 0x00000000},
+       {0x00008238, 0x00000000},
+       {0x0000823c, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000100},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x400000ff},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x88000010},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000000},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x00000000},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x00008300, 0x00000000},
+       {0x00008304, 0x00000000},
+       {0x00008308, 0x00000000},
+       {0x0000830c, 0x00000000},
+       {0x00008310, 0x00000000},
+       {0x00008314, 0x00000000},
+       {0x00008318, 0x00000000},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000e00},
+       {0x00008338, 0x00070000},
+       {0x0000833c, 0x00000000},
+       {0x00008340, 0x000107ff},
+       {0x00009808, 0x00000000},
+       {0x0000980c, 0xad848e19},
+       {0x00009810, 0x7d14e000},
+       {0x00009814, 0x9c0a9f6b},
+       {0x0000981c, 0x00000000},
+       {0x0000982c, 0x0000a000},
+       {0x00009830, 0x00000000},
+       {0x0000983c, 0x00200400},
+       {0x00009840, 0x206a002e},
+       {0x0000984c, 0x1284233c},
+       {0x00009854, 0x00000859},
+       {0x00009900, 0x00000000},
+       {0x00009904, 0x00000000},
+       {0x00009908, 0x00000000},
+       {0x0000990c, 0x00000000},
+       {0x0000991c, 0x10000fff},
+       {0x00009920, 0x05100000},
+       {0x0000a920, 0x05100000},
+       {0x0000b920, 0x05100000},
+       {0x00009928, 0x00000001},
+       {0x0000992c, 0x00000004},
+       {0x00009934, 0x1e1f2022},
+       {0x00009938, 0x0a0b0c0d},
+       {0x0000993c, 0x00000000},
+       {0x00009948, 0x9280b212},
+       {0x0000994c, 0x00020028},
+       {0x00009954, 0x5d50e188},
+       {0x00009958, 0x00081fff},
+       {0x0000c95c, 0x004b6a8e},
+       {0x0000c968, 0x000003ce},
+       {0x00009970, 0x190fb515},
+       {0x00009974, 0x00000000},
+       {0x00009978, 0x00000001},
+       {0x0000997c, 0x00000000},
+       {0x00009980, 0x00000000},
+       {0x00009984, 0x00000000},
+       {0x00009988, 0x00000000},
+       {0x0000998c, 0x00000000},
+       {0x00009990, 0x00000000},
+       {0x00009994, 0x00000000},
+       {0x00009998, 0x00000000},
+       {0x0000999c, 0x00000000},
+       {0x000099a0, 0x00000000},
+       {0x000099a4, 0x00000001},
+       {0x000099a8, 0x001fff00},
+       {0x000099ac, 0x00000000},
+       {0x000099b0, 0x03051000},
+       {0x000099dc, 0x00000000},
+       {0x000099e0, 0x00000200},
+       {0x000099e4, 0xaaaaaaaa},
+       {0x000099e8, 0x3c466478},
+       {0x000099ec, 0x000000aa},
+       {0x000099fc, 0x00001042},
+       {0x00009b00, 0x00000000},
+       {0x00009b04, 0x00000001},
+       {0x00009b08, 0x00000002},
+       {0x00009b0c, 0x00000003},
+       {0x00009b10, 0x00000004},
+       {0x00009b14, 0x00000005},
+       {0x00009b18, 0x00000008},
+       {0x00009b1c, 0x00000009},
+       {0x00009b20, 0x0000000a},
+       {0x00009b24, 0x0000000b},
+       {0x00009b28, 0x0000000c},
+       {0x00009b2c, 0x0000000d},
+       {0x00009b30, 0x00000010},
+       {0x00009b34, 0x00000011},
+       {0x00009b38, 0x00000012},
+       {0x00009b3c, 0x00000013},
+       {0x00009b40, 0x00000014},
+       {0x00009b44, 0x00000015},
+       {0x00009b48, 0x00000018},
+       {0x00009b4c, 0x00000019},
+       {0x00009b50, 0x0000001a},
+       {0x00009b54, 0x0000001b},
+       {0x00009b58, 0x0000001c},
+       {0x00009b5c, 0x0000001d},
+       {0x00009b60, 0x00000020},
+       {0x00009b64, 0x00000021},
+       {0x00009b68, 0x00000022},
+       {0x00009b6c, 0x00000023},
+       {0x00009b70, 0x00000024},
+       {0x00009b74, 0x00000025},
+       {0x00009b78, 0x00000028},
+       {0x00009b7c, 0x00000029},
+       {0x00009b80, 0x0000002a},
+       {0x00009b84, 0x0000002b},
+       {0x00009b88, 0x0000002c},
+       {0x00009b8c, 0x0000002d},
+       {0x00009b90, 0x00000030},
+       {0x00009b94, 0x00000031},
+       {0x00009b98, 0x00000032},
+       {0x00009b9c, 0x00000033},
+       {0x00009ba0, 0x00000034},
+       {0x00009ba4, 0x00000035},
+       {0x00009ba8, 0x00000035},
+       {0x00009bac, 0x00000035},
+       {0x00009bb0, 0x00000035},
+       {0x00009bb4, 0x00000035},
+       {0x00009bb8, 0x00000035},
+       {0x00009bbc, 0x00000035},
+       {0x00009bc0, 0x00000035},
+       {0x00009bc4, 0x00000035},
+       {0x00009bc8, 0x00000035},
+       {0x00009bcc, 0x00000035},
+       {0x00009bd0, 0x00000035},
+       {0x00009bd4, 0x00000035},
+       {0x00009bd8, 0x00000035},
+       {0x00009bdc, 0x00000035},
+       {0x00009be0, 0x00000035},
+       {0x00009be4, 0x00000035},
+       {0x00009be8, 0x00000035},
+       {0x00009bec, 0x00000035},
+       {0x00009bf0, 0x00000035},
+       {0x00009bf4, 0x00000035},
+       {0x00009bf8, 0x00000010},
+       {0x00009bfc, 0x0000001a},
+       {0x0000a210, 0x40806333},
+       {0x0000a214, 0x00106c10},
+       {0x0000a218, 0x009c4060},
+       {0x0000a220, 0x018830c6},
+       {0x0000a224, 0x00000400},
+       {0x0000a228, 0x00000bb5},
+       {0x0000a22c, 0x00000011},
+       {0x0000a234, 0x20202020},
+       {0x0000a238, 0x20202020},
+       {0x0000a23c, 0x13c889af},
+       {0x0000a240, 0x38490a20},
+       {0x0000a244, 0x00007bb6},
+       {0x0000a248, 0x0fff3ffc},
+       {0x0000a24c, 0x00000001},
+       {0x0000a250, 0x0000a000},
+       {0x0000a254, 0x00000000},
+       {0x0000a258, 0x0cc75380},
+       {0x0000a25c, 0x0f0f0f01},
+       {0x0000a260, 0xdfa91f01},
+       {0x0000a268, 0x00000000},
+       {0x0000a26c, 0x0e79e5c6},
+       {0x0000b26c, 0x0e79e5c6},
+       {0x0000c26c, 0x0e79e5c6},
+       {0x0000d270, 0x00820820},
+       {0x0000a278, 0x1ce739ce},
+       {0x0000a27c, 0x051701ce},
+       {0x0000a338, 0x00000000},
+       {0x0000a33c, 0x00000000},
+       {0x0000a340, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a348, 0x3fffffff},
+       {0x0000a34c, 0x3fffffff},
+       {0x0000a350, 0x3fffffff},
+       {0x0000a354, 0x0003ffff},
+       {0x0000a358, 0x79a8aa1f},
+       {0x0000d35c, 0x07ffffef},
+       {0x0000d360, 0x0fffffe7},
+       {0x0000d364, 0x17ffffe5},
+       {0x0000d368, 0x1fffffe4},
+       {0x0000d36c, 0x37ffffe3},
+       {0x0000d370, 0x3fffffe3},
+       {0x0000d374, 0x57ffffe3},
+       {0x0000d378, 0x5fffffe2},
+       {0x0000d37c, 0x7fffffe2},
+       {0x0000d380, 0x7f3c7bba},
+       {0x0000d384, 0xf3307ff0},
+       {0x0000a388, 0x08000000},
+       {0x0000a38c, 0x20202020},
+       {0x0000a390, 0x20202020},
+       {0x0000a394, 0x1ce739ce},
+       {0x0000a398, 0x000001ce},
+       {0x0000a39c, 0x00000001},
+       {0x0000a3a0, 0x00000000},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0x00000000},
+       {0x0000a3ac, 0x00000000},
+       {0x0000a3b0, 0x00000000},
+       {0x0000a3b4, 0x00000000},
+       {0x0000a3b8, 0x00000000},
+       {0x0000a3bc, 0x00000000},
+       {0x0000a3c0, 0x00000000},
+       {0x0000a3c4, 0x00000000},
+       {0x0000a3c8, 0x00000246},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3dc, 0x1ce739ce},
+       {0x0000a3e0, 0x000001ce},
+};
+
+static const u32 ar5416Bank0[][2] = {
+       /* Addr      allmodes  */
+       {0x000098b0, 0x1e5795e5},
+       {0x000098e0, 0x02008020},
+};
+
+static const u32 ar5416BB_RfGain[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x00009a00, 0x00000000, 0x00000000},
+       {0x00009a04, 0x00000040, 0x00000040},
+       {0x00009a08, 0x00000080, 0x00000080},
+       {0x00009a0c, 0x000001a1, 0x00000141},
+       {0x00009a10, 0x000001e1, 0x00000181},
+       {0x00009a14, 0x00000021, 0x000001c1},
+       {0x00009a18, 0x00000061, 0x00000001},
+       {0x00009a1c, 0x00000168, 0x00000041},
+       {0x00009a20, 0x000001a8, 0x000001a8},
+       {0x00009a24, 0x000001e8, 0x000001e8},
+       {0x00009a28, 0x00000028, 0x00000028},
+       {0x00009a2c, 0x00000068, 0x00000068},
+       {0x00009a30, 0x00000189, 0x000000a8},
+       {0x00009a34, 0x000001c9, 0x00000169},
+       {0x00009a38, 0x00000009, 0x000001a9},
+       {0x00009a3c, 0x00000049, 0x000001e9},
+       {0x00009a40, 0x00000089, 0x00000029},
+       {0x00009a44, 0x00000170, 0x00000069},
+       {0x00009a48, 0x000001b0, 0x00000190},
+       {0x00009a4c, 0x000001f0, 0x000001d0},
+       {0x00009a50, 0x00000030, 0x00000010},
+       {0x00009a54, 0x00000070, 0x00000050},
+       {0x00009a58, 0x00000191, 0x00000090},
+       {0x00009a5c, 0x000001d1, 0x00000151},
+       {0x00009a60, 0x00000011, 0x00000191},
+       {0x00009a64, 0x00000051, 0x000001d1},
+       {0x00009a68, 0x00000091, 0x00000011},
+       {0x00009a6c, 0x000001b8, 0x00000051},
+       {0x00009a70, 0x000001f8, 0x00000198},
+       {0x00009a74, 0x00000038, 0x000001d8},
+       {0x00009a78, 0x00000078, 0x00000018},
+       {0x00009a7c, 0x00000199, 0x00000058},
+       {0x00009a80, 0x000001d9, 0x00000098},
+       {0x00009a84, 0x00000019, 0x00000159},
+       {0x00009a88, 0x00000059, 0x00000199},
+       {0x00009a8c, 0x00000099, 0x000001d9},
+       {0x00009a90, 0x000000d9, 0x00000019},
+       {0x00009a94, 0x000000f9, 0x00000059},
+       {0x00009a98, 0x000000f9, 0x00000099},
+       {0x00009a9c, 0x000000f9, 0x000000d9},
+       {0x00009aa0, 0x000000f9, 0x000000f9},
+       {0x00009aa4, 0x000000f9, 0x000000f9},
+       {0x00009aa8, 0x000000f9, 0x000000f9},
+       {0x00009aac, 0x000000f9, 0x000000f9},
+       {0x00009ab0, 0x000000f9, 0x000000f9},
+       {0x00009ab4, 0x000000f9, 0x000000f9},
+       {0x00009ab8, 0x000000f9, 0x000000f9},
+       {0x00009abc, 0x000000f9, 0x000000f9},
+       {0x00009ac0, 0x000000f9, 0x000000f9},
+       {0x00009ac4, 0x000000f9, 0x000000f9},
+       {0x00009ac8, 0x000000f9, 0x000000f9},
+       {0x00009acc, 0x000000f9, 0x000000f9},
+       {0x00009ad0, 0x000000f9, 0x000000f9},
+       {0x00009ad4, 0x000000f9, 0x000000f9},
+       {0x00009ad8, 0x000000f9, 0x000000f9},
+       {0x00009adc, 0x000000f9, 0x000000f9},
+       {0x00009ae0, 0x000000f9, 0x000000f9},
+       {0x00009ae4, 0x000000f9, 0x000000f9},
+       {0x00009ae8, 0x000000f9, 0x000000f9},
+       {0x00009aec, 0x000000f9, 0x000000f9},
+       {0x00009af0, 0x000000f9, 0x000000f9},
+       {0x00009af4, 0x000000f9, 0x000000f9},
+       {0x00009af8, 0x000000f9, 0x000000f9},
+       {0x00009afc, 0x000000f9, 0x000000f9},
+};
+
+static const u32 ar5416Bank1[][2] = {
+       /* Addr      allmodes  */
+       {0x000098b0, 0x02108421},
+       {0x000098ec, 0x00000008},
+};
+
+static const u32 ar5416Bank2[][2] = {
+       /* Addr      allmodes  */
+       {0x000098b0, 0x0e73ff17},
+       {0x000098e0, 0x00000420},
+};
+
+static const u32 ar5416Bank3[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x000098f0, 0x01400018, 0x01c00018},
+};
+
+static const u32 ar5416Bank6[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00e00000, 0x00e00000},
+       {0x0000989c, 0x005e0000, 0x005e0000},
+       {0x0000989c, 0x00120000, 0x00120000},
+       {0x0000989c, 0x00620000, 0x00620000},
+       {0x0000989c, 0x00020000, 0x00020000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x40ff0000, 0x40ff0000},
+       {0x0000989c, 0x005f0000, 0x005f0000},
+       {0x0000989c, 0x00870000, 0x00870000},
+       {0x0000989c, 0x00f90000, 0x00f90000},
+       {0x0000989c, 0x007b0000, 0x007b0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00f50000, 0x00f50000},
+       {0x0000989c, 0x00dc0000, 0x00dc0000},
+       {0x0000989c, 0x00110000, 0x00110000},
+       {0x0000989c, 0x006100a8, 0x006100a8},
+       {0x0000989c, 0x004210a2, 0x004210a2},
+       {0x0000989c, 0x0014008f, 0x0014008f},
+       {0x0000989c, 0x00c40003, 0x00c40003},
+       {0x0000989c, 0x003000f2, 0x003000f2},
+       {0x0000989c, 0x00440016, 0x00440016},
+       {0x0000989c, 0x00410040, 0x00410040},
+       {0x0000989c, 0x0001805e, 0x0001805e},
+       {0x0000989c, 0x0000c0ab, 0x0000c0ab},
+       {0x0000989c, 0x000000f1, 0x000000f1},
+       {0x0000989c, 0x00002081, 0x00002081},
+       {0x0000989c, 0x000000d4, 0x000000d4},
+       {0x000098d0, 0x0000000f, 0x0010000f},
+};
+
+static const u32 ar5416Bank6TPC[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00e00000, 0x00e00000},
+       {0x0000989c, 0x005e0000, 0x005e0000},
+       {0x0000989c, 0x00120000, 0x00120000},
+       {0x0000989c, 0x00620000, 0x00620000},
+       {0x0000989c, 0x00020000, 0x00020000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x40ff0000, 0x40ff0000},
+       {0x0000989c, 0x005f0000, 0x005f0000},
+       {0x0000989c, 0x00870000, 0x00870000},
+       {0x0000989c, 0x00f90000, 0x00f90000},
+       {0x0000989c, 0x007b0000, 0x007b0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00f50000, 0x00f50000},
+       {0x0000989c, 0x00dc0000, 0x00dc0000},
+       {0x0000989c, 0x00110000, 0x00110000},
+       {0x0000989c, 0x006100a8, 0x006100a8},
+       {0x0000989c, 0x00423022, 0x00423022},
+       {0x0000989c, 0x201400df, 0x201400df},
+       {0x0000989c, 0x00c40002, 0x00c40002},
+       {0x0000989c, 0x003000f2, 0x003000f2},
+       {0x0000989c, 0x00440016, 0x00440016},
+       {0x0000989c, 0x00410040, 0x00410040},
+       {0x0000989c, 0x0001805e, 0x0001805e},
+       {0x0000989c, 0x0000c0ab, 0x0000c0ab},
+       {0x0000989c, 0x000000e1, 0x000000e1},
+       {0x0000989c, 0x00007081, 0x00007081},
+       {0x0000989c, 0x000000d4, 0x000000d4},
+       {0x000098d0, 0x0000000f, 0x0010000f},
+};
+
+static const u32 ar5416Bank7[][2] = {
+       /* Addr      allmodes  */
+       {0x0000989c, 0x00000500},
+       {0x0000989c, 0x00000800},
+       {0x000098cc, 0x0000000e},
+};
+
+static const u32 ar5416Addac[][2] = {
+       /* Addr      allmodes  */
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000003},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x0000000c},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000030},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000060},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000058},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x000098c4, 0x00000000},
+};
+
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar5008_phy.c b/drivers/net/wireless/ath/ath9k_btcoex/ar5008_phy.c
new file mode 100644 (file)
index 0000000..24eeb05
--- /dev/null
@@ -0,0 +1,1438 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "../regd.h"
+#include "ar9002_phy.h"
+
+/* All code below is for AR5008, AR9001, AR9002 */
+
+static const int firstep_table[] =
+/* level:  0   1   2   3   4   5   6   7   8  */
+       { -4, -2,  0,  2,  4,  6,  8, 10, 12 }; /* lvl 0-8, default 2 */
+
+static const int cycpwrThr1_table[] =
+/* level:  0   1   2   3   4   5   6   7   8  */
+       { -6, -4, -2,  0,  2,  4,  6,  8 };     /* lvl 0-7, default 3 */
+
+/*
+ * register values to turn OFDM weak signal detection OFF
+ */
+static const int m1ThreshLow_off = 127;
+static const int m2ThreshLow_off = 127;
+static const int m1Thresh_off = 127;
+static const int m2Thresh_off = 127;
+static const int m2CountThr_off =  31;
+static const int m2CountThrLow_off =  63;
+static const int m1ThreshLowExt_off = 127;
+static const int m2ThreshLowExt_off = 127;
+static const int m1ThreshExt_off = 127;
+static const int m2ThreshExt_off = 127;
+
+
+static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array,
+                                int col)
+{
+       int i;
+
+       for (i = 0; i < array->ia_rows; i++)
+               bank[i] = INI_RA(array, i, col);
+}
+
+
+#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \
+       ar5008_write_rf_array(ah, iniarray, regData, &(regWr))
+
+static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array,
+                                 u32 *data, unsigned int *writecnt)
+{
+       int r;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       for (r = 0; r < array->ia_rows; r++) {
+               REG_WRITE(ah, INI_RA(array, r, 0), data[r]);
+               DO_DELAY(*writecnt);
+       }
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+/**
+ * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters
+ * @rfbuf:
+ * @reg32:
+ * @numBits:
+ * @firstBit:
+ * @column:
+ *
+ * Performs analog "swizzling" of parameters into their location.
+ * Used on external AR2133/AR5133 radios.
+ */
+static void ar5008_hw_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32,
+                                          u32 numBits, u32 firstBit,
+                                          u32 column)
+{
+       u32 tmp32, mask, arrayEntry, lastBit;
+       int32_t bitPosition, bitsLeft;
+
+       tmp32 = ath9k_hw_reverse_bits(reg32, numBits);
+       arrayEntry = (firstBit - 1) / 8;
+       bitPosition = (firstBit - 1) % 8;
+       bitsLeft = numBits;
+       while (bitsLeft > 0) {
+               lastBit = (bitPosition + bitsLeft > 8) ?
+                   8 : bitPosition + bitsLeft;
+               mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
+                   (column * 8);
+               rfBuf[arrayEntry] &= ~mask;
+               rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<
+                                     (column * 8)) & mask;
+               bitsLeft -= 8 - bitPosition;
+               tmp32 = tmp32 >> (8 - bitPosition);
+               bitPosition = 0;
+               arrayEntry++;
+       }
+}
+
+/*
+ * Fix on 2.4 GHz band for orientation sensitivity issue by increasing
+ * rf_pwd_icsyndiv.
+ *
+ * Theoretical Rules:
+ *   if 2 GHz band
+ *      if forceBiasAuto
+ *         if synth_freq < 2412
+ *            bias = 0
+ *         else if 2412 <= synth_freq <= 2422
+ *            bias = 1
+ *         else // synth_freq > 2422
+ *            bias = 2
+ *      else if forceBias > 0
+ *         bias = forceBias & 7
+ *      else
+ *         no change, use value from ini file
+ *   else
+ *      no change, invalid band
+ *
+ *  1st Mod:
+ *    2422 also uses value of 2
+ *    <approved>
+ *
+ *  2nd Mod:
+ *    Less than 2412 uses value of 0, 2412 and above uses value of 2
+ */
+static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 tmp_reg;
+       int reg_writes = 0;
+       u32 new_bias = 0;
+
+       if (!AR_SREV_5416(ah) || synth_freq >= 3000)
+               return;
+
+       BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
+
+       if (synth_freq < 2412)
+               new_bias = 0;
+       else if (synth_freq < 2422)
+               new_bias = 1;
+       else
+               new_bias = 2;
+
+       /* pre-reverse this field */
+       tmp_reg = ath9k_hw_reverse_bits(new_bias, 3);
+
+       ath_dbg(common, CONFIG, "Force rf_pwd_icsyndiv to %1d on %4d\n",
+               new_bias, synth_freq);
+
+       /* swizzle rf_pwd_icsyndiv */
+       ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3);
+
+       /* write Bank 6 with new params */
+       REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes);
+}
+
+/**
+ * ar5008_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For the external AR2133/AR5133 radios, takes the MHz channel value and set
+ * the channel value. Assumes writes enabled to analog bus and bank6 register
+ * cache in ah->analogBank6Data.
+ */
+static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 channelSel = 0;
+       u32 bModeSynth = 0;
+       u32 aModeRefSel = 0;
+       u32 reg32 = 0;
+       u16 freq;
+       struct chan_centers centers;
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       freq = centers.synth_center;
+
+       if (freq < 4800) {
+               u32 txctl;
+
+               if (((freq - 2192) % 5) == 0) {
+                       channelSel = ((freq - 672) * 2 - 3040) / 10;
+                       bModeSynth = 0;
+               } else if (((freq - 2224) % 5) == 0) {
+                       channelSel = ((freq - 704) * 2 - 3040) / 10;
+                       bModeSynth = 1;
+               } else {
+                       ath_err(common, "Invalid channel %u MHz\n", freq);
+                       return -EINVAL;
+               }
+
+               channelSel = (channelSel << 2) & 0xff;
+               channelSel = ath9k_hw_reverse_bits(channelSel, 8);
+
+               txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+               if (freq == 2484) {
+
+                       REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                                 txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+               } else {
+                       REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                                 txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
+               }
+
+       } else if ((freq % 20) == 0 && freq >= 5120) {
+               channelSel =
+                   ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);
+               aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+       } else if ((freq % 10) == 0) {
+               channelSel =
+                   ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);
+               if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
+                       aModeRefSel = ath9k_hw_reverse_bits(2, 2);
+               else
+                       aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+       } else if ((freq % 5) == 0) {
+               channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
+               aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+       } else {
+               ath_err(common, "Invalid channel %u MHz\n", freq);
+               return -EINVAL;
+       }
+
+       ar5008_hw_force_bias(ah, freq);
+
+       reg32 =
+           (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
+           (1 << 5) | 0x1;
+
+       REG_WRITE(ah, AR_PHY(0x37), reg32);
+
+       ah->curchan = chan;
+       ah->curchan_rad_index = -1;
+
+       return 0;
+}
+
+/**
+ * ar5008_hw_spur_mitigate - convert baseband spur frequency for external radios
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For non single-chip solutions. Converts to baseband spur frequency given the
+ * input channel frequency and compute register settings below.
+ */
+static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
+                                   struct ath9k_channel *chan)
+{
+       int bb_spur = AR_NO_SPUR;
+       int bin, cur_bin;
+       int spur_freq_sd;
+       int spur_delta_phase;
+       int denominator;
+       int upper, lower, cur_vit_mask;
+       int tmp, new;
+       int i;
+       static int pilot_mask_reg[4] = {
+               AR_PHY_TIMING7, AR_PHY_TIMING8,
+               AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+       };
+       static int chan_mask_reg[4] = {
+               AR_PHY_TIMING9, AR_PHY_TIMING10,
+               AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+       };
+       static int inc[4] = { 0, 100, 0, 0 };
+
+       int8_t mask_m[123];
+       int8_t mask_p[123];
+       int8_t mask_amt;
+       int tmp_mask;
+       int cur_bb_spur;
+       bool is2GHz = IS_CHAN_2GHZ(chan);
+
+       memset(&mask_m, 0, sizeof(int8_t) * 123);
+       memset(&mask_p, 0, sizeof(int8_t) * 123);
+
+       for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+               cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
+               if (AR_NO_SPUR == cur_bb_spur)
+                       break;
+               cur_bb_spur = cur_bb_spur - (chan->channel * 10);
+               if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
+                       bb_spur = cur_bb_spur;
+                       break;
+               }
+       }
+
+       if (AR_NO_SPUR == bb_spur)
+               return;
+
+       bin = bb_spur * 32;
+
+       tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
+       new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+                    AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+                    AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+                    AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+
+       REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
+
+       new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+              AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+              AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+              AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+              SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+       REG_WRITE(ah, AR_PHY_SPUR_REG, new);
+
+       spur_delta_phase = ((bb_spur * 524288) / 100) &
+               AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+       denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
+       spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
+
+       new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+              SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+              SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+       REG_WRITE(ah, AR_PHY_TIMING11, new);
+
+       cur_bin = -6000;
+       upper = bin + 100;
+       lower = bin - 100;
+
+       for (i = 0; i < 4; i++) {
+               int pilot_mask = 0;
+               int chan_mask = 0;
+               int bp = 0;
+               for (bp = 0; bp < 30; bp++) {
+                       if ((cur_bin > lower) && (cur_bin < upper)) {
+                               pilot_mask = pilot_mask | 0x1 << bp;
+                               chan_mask = chan_mask | 0x1 << bp;
+                       }
+                       cur_bin += 100;
+               }
+               cur_bin += inc[i];
+               REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+               REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+       }
+
+       cur_vit_mask = 6100;
+       upper = bin + 120;
+       lower = bin - 120;
+
+       for (i = 0; i < 123; i++) {
+               if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+
+                       /* workaround for gcc bug #37014 */
+                       volatile int tmp_v = abs(cur_vit_mask - bin);
+
+                       if (tmp_v < 75)
+                               mask_amt = 1;
+                       else
+                               mask_amt = 0;
+                       if (cur_vit_mask < 0)
+                               mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+                       else
+                               mask_p[cur_vit_mask / 100] = mask_amt;
+               }
+               cur_vit_mask -= 100;
+       }
+
+       tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+               | (mask_m[48] << 26) | (mask_m[49] << 24)
+               | (mask_m[50] << 22) | (mask_m[51] << 20)
+               | (mask_m[52] << 18) | (mask_m[53] << 16)
+               | (mask_m[54] << 14) | (mask_m[55] << 12)
+               | (mask_m[56] << 10) | (mask_m[57] << 8)
+               | (mask_m[58] << 6) | (mask_m[59] << 4)
+               | (mask_m[60] << 2) | (mask_m[61] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+       REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+       tmp_mask = (mask_m[31] << 28)
+               | (mask_m[32] << 26) | (mask_m[33] << 24)
+               | (mask_m[34] << 22) | (mask_m[35] << 20)
+               | (mask_m[36] << 18) | (mask_m[37] << 16)
+               | (mask_m[48] << 14) | (mask_m[39] << 12)
+               | (mask_m[40] << 10) | (mask_m[41] << 8)
+               | (mask_m[42] << 6) | (mask_m[43] << 4)
+               | (mask_m[44] << 2) | (mask_m[45] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+       tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+               | (mask_m[18] << 26) | (mask_m[18] << 24)
+               | (mask_m[20] << 22) | (mask_m[20] << 20)
+               | (mask_m[22] << 18) | (mask_m[22] << 16)
+               | (mask_m[24] << 14) | (mask_m[24] << 12)
+               | (mask_m[25] << 10) | (mask_m[26] << 8)
+               | (mask_m[27] << 6) | (mask_m[28] << 4)
+               | (mask_m[29] << 2) | (mask_m[30] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+       tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
+               | (mask_m[2] << 26) | (mask_m[3] << 24)
+               | (mask_m[4] << 22) | (mask_m[5] << 20)
+               | (mask_m[6] << 18) | (mask_m[7] << 16)
+               | (mask_m[8] << 14) | (mask_m[9] << 12)
+               | (mask_m[10] << 10) | (mask_m[11] << 8)
+               | (mask_m[12] << 6) | (mask_m[13] << 4)
+               | (mask_m[14] << 2) | (mask_m[15] << 0);
+       REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+       tmp_mask = (mask_p[15] << 28)
+               | (mask_p[14] << 26) | (mask_p[13] << 24)
+               | (mask_p[12] << 22) | (mask_p[11] << 20)
+               | (mask_p[10] << 18) | (mask_p[9] << 16)
+               | (mask_p[8] << 14) | (mask_p[7] << 12)
+               | (mask_p[6] << 10) | (mask_p[5] << 8)
+               | (mask_p[4] << 6) | (mask_p[3] << 4)
+               | (mask_p[2] << 2) | (mask_p[1] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+       tmp_mask = (mask_p[30] << 28)
+               | (mask_p[29] << 26) | (mask_p[28] << 24)
+               | (mask_p[27] << 22) | (mask_p[26] << 20)
+               | (mask_p[25] << 18) | (mask_p[24] << 16)
+               | (mask_p[23] << 14) | (mask_p[22] << 12)
+               | (mask_p[21] << 10) | (mask_p[20] << 8)
+               | (mask_p[19] << 6) | (mask_p[18] << 4)
+               | (mask_p[17] << 2) | (mask_p[16] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+       tmp_mask = (mask_p[45] << 28)
+               | (mask_p[44] << 26) | (mask_p[43] << 24)
+               | (mask_p[42] << 22) | (mask_p[41] << 20)
+               | (mask_p[40] << 18) | (mask_p[39] << 16)
+               | (mask_p[38] << 14) | (mask_p[37] << 12)
+               | (mask_p[36] << 10) | (mask_p[35] << 8)
+               | (mask_p[34] << 6) | (mask_p[33] << 4)
+               | (mask_p[32] << 2) | (mask_p[31] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+       tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+               | (mask_p[59] << 26) | (mask_p[58] << 24)
+               | (mask_p[57] << 22) | (mask_p[56] << 20)
+               | (mask_p[55] << 18) | (mask_p[54] << 16)
+               | (mask_p[53] << 14) | (mask_p[52] << 12)
+               | (mask_p[51] << 10) | (mask_p[50] << 8)
+               | (mask_p[49] << 6) | (mask_p[48] << 4)
+               | (mask_p[47] << 2) | (mask_p[46] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+
+/**
+ * ar5008_hw_rf_alloc_ext_banks - allocates banks for external radio programming
+ * @ah: atheros hardware structure
+ *
+ * Only required for older devices with external AR2133/AR5133 radios.
+ */
+static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
+{
+#define ATH_ALLOC_BANK(bank, size) do { \
+               bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \
+               if (!bank) { \
+                       ath_err(common, "Cannot allocate RF banks\n"); \
+                       return -ENOMEM; \
+               } \
+       } while (0);
+
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
+
+       ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
+       ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
+       ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows);
+       ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows);
+       ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
+       ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
+       ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
+       ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
+
+       return 0;
+#undef ATH_ALLOC_BANK
+}
+
+
+/**
+ * ar5008_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers
+ * @ah: atheros hardware struture
+ * For the external AR2133/AR5133 radios banks.
+ */
+static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah)
+{
+#define ATH_FREE_BANK(bank) do { \
+               kfree(bank); \
+               bank = NULL; \
+       } while (0);
+
+       BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
+
+       ATH_FREE_BANK(ah->analogBank0Data);
+       ATH_FREE_BANK(ah->analogBank1Data);
+       ATH_FREE_BANK(ah->analogBank2Data);
+       ATH_FREE_BANK(ah->analogBank3Data);
+       ATH_FREE_BANK(ah->analogBank6Data);
+       ATH_FREE_BANK(ah->analogBank6TPCData);
+       ATH_FREE_BANK(ah->analogBank7Data);
+       ATH_FREE_BANK(ah->bank6Temp);
+
+#undef ATH_FREE_BANK
+}
+
+/* *
+ * ar5008_hw_set_rf_regs - programs rf registers based on EEPROM
+ * @ah: atheros hardware structure
+ * @chan:
+ * @modesIndex:
+ *
+ * Used for the external AR2133/AR5133 radios.
+ *
+ * Reads the EEPROM header info from the device structure and programs
+ * all rf registers. This routine requires access to the analog
+ * rf device. This is not required for single-chip devices.
+ */
+static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
+                                 struct ath9k_channel *chan,
+                                 u16 modesIndex)
+{
+       u32 eepMinorRev;
+       u32 ob5GHz = 0, db5GHz = 0;
+       u32 ob2GHz = 0, db2GHz = 0;
+       int regWrites = 0;
+
+       /*
+        * Software does not need to program bank data
+        * for single chip devices, that is AR9280 or anything
+        * after that.
+        */
+       if (AR_SREV_9280_20_OR_LATER(ah))
+               return true;
+
+       /* Setup rf parameters */
+       eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
+
+       /* Setup Bank 0 Write */
+       ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1);
+
+       /* Setup Bank 1 Write */
+       ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1);
+
+       /* Setup Bank 2 Write */
+       ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1);
+
+       /* Setup Bank 6 Write */
+       ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3,
+                     modesIndex);
+       {
+               int i;
+               for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) {
+                       ah->analogBank6Data[i] =
+                           INI_RA(&ah->iniBank6TPC, i, modesIndex);
+               }
+       }
+
+       /* Only the 5 or 2 GHz OB/DB need to be set for a mode */
+       if (eepMinorRev >= 2) {
+               if (IS_CHAN_2GHZ(chan)) {
+                       ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2);
+                       db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2);
+                       ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,
+                                                      ob2GHz, 3, 197, 0);
+                       ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,
+                                                      db2GHz, 3, 194, 0);
+               } else {
+                       ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5);
+                       db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5);
+                       ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,
+                                                      ob5GHz, 3, 203, 0);
+                       ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,
+                                                      db5GHz, 3, 200, 0);
+               }
+       }
+
+       /* Setup Bank 7 Setup */
+       ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1);
+
+       /* Write Analog registers */
+       REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
+                          regWrites);
+       REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
+                          regWrites);
+       REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data,
+                          regWrites);
+       REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data,
+                          regWrites);
+       REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data,
+                          regWrites);
+       REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data,
+                          regWrites);
+
+       return true;
+}
+
+static void ar5008_hw_init_bb(struct ath_hw *ah,
+                             struct ath9k_channel *chan)
+{
+       u32 synthDelay;
+
+       synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_B(chan))
+               synthDelay = (4 * synthDelay) / 22;
+       else
+               synthDelay /= 10;
+
+       if (IS_CHAN_HALF_RATE(chan))
+               synthDelay *= 2;
+       else if (IS_CHAN_QUARTER_RATE(chan))
+               synthDelay *= 4;
+
+       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+       udelay(synthDelay + BASE_ACTIVATE_DELAY);
+}
+
+static void ar5008_hw_init_chain_masks(struct ath_hw *ah)
+{
+       int rx_chainmask, tx_chainmask;
+
+       rx_chainmask = ah->rxchainmask;
+       tx_chainmask = ah->txchainmask;
+
+
+       switch (rx_chainmask) {
+       case 0x5:
+               REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+                           AR_PHY_SWAP_ALT_CHAIN);
+       case 0x3:
+               if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) {
+                       REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
+                       REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
+                       break;
+               }
+       case 0x1:
+       case 0x2:
+       case 0x7:
+               ENABLE_REGWRITE_BUFFER(ah);
+               REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
+               REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
+               break;
+       default:
+               ENABLE_REGWRITE_BUFFER(ah);
+               break;
+       }
+
+       REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       if (tx_chainmask == 0x5) {
+               REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+                           AR_PHY_SWAP_ALT_CHAIN);
+       }
+       if (AR_SREV_9100(ah))
+               REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
+                         REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
+}
+
+static void ar5008_hw_override_ini(struct ath_hw *ah,
+                                  struct ath9k_channel *chan)
+{
+       u32 val;
+
+       /*
+        * Set the RX_ABORT and RX_DIS and clear if off only after
+        * RXE is set for MAC. This prevents frames with corrupted
+        * descriptor status.
+        */
+       REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               val = REG_READ(ah, AR_PCU_MISC_MODE2);
+
+               if (!AR_SREV_9271(ah))
+                       val &= ~AR_PCU_MISC_MODE2_HWWAR1;
+
+               if (AR_SREV_9287_11_OR_LATER(ah))
+                       val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
+
+               REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
+       }
+
+       REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
+                   AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+       if (AR_SREV_9280_20_OR_LATER(ah))
+               return;
+       /*
+        * Disable BB clock gating
+        * Necessary to avoid issues on AR5416 2.0
+        */
+       REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
+
+       /*
+        * Disable RIFS search on some chips to avoid baseband
+        * hang issues.
+        */
+       if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {
+               val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
+               val &= ~AR_PHY_RIFS_INIT_DELAY;
+               REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
+       }
+}
+
+static void ar5008_hw_set_channel_regs(struct ath_hw *ah,
+                                      struct ath9k_channel *chan)
+{
+       u32 phymode;
+       u32 enableDacFifo = 0;
+
+       if (AR_SREV_9285_12_OR_LATER(ah))
+               enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
+                                        AR_PHY_FC_ENABLE_DAC_FIFO);
+
+       phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
+               | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;
+
+       if (IS_CHAN_HT40(chan)) {
+               phymode |= AR_PHY_FC_DYN2040_EN;
+
+               if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+                   (chan->chanmode == CHANNEL_G_HT40PLUS))
+                       phymode |= AR_PHY_FC_DYN2040_PRI_CH;
+
+       }
+       REG_WRITE(ah, AR_PHY_TURBO, phymode);
+
+       ath9k_hw_set11nmac2040(ah);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
+       REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+
+static int ar5008_hw_process_ini(struct ath_hw *ah,
+                                struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       int i, regWrites = 0;
+       u32 modesIndex, freqIndex;
+
+       switch (chan->chanmode) {
+       case CHANNEL_A:
+       case CHANNEL_A_HT20:
+               modesIndex = 1;
+               freqIndex = 1;
+               break;
+       case CHANNEL_A_HT40PLUS:
+       case CHANNEL_A_HT40MINUS:
+               modesIndex = 2;
+               freqIndex = 1;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_G_HT20:
+       case CHANNEL_B:
+               modesIndex = 4;
+               freqIndex = 2;
+               break;
+       case CHANNEL_G_HT40PLUS:
+       case CHANNEL_G_HT40MINUS:
+               modesIndex = 3;
+               freqIndex = 2;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       /*
+        * Set correct baseband to analog shift setting to
+        * access analog chips.
+        */
+       REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       /* Write ADDAC shifts */
+       REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
+       if (ah->eep_ops->set_addac)
+               ah->eep_ops->set_addac(ah, chan);
+
+       REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
+       REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       for (i = 0; i < ah->iniModes.ia_rows; i++) {
+               u32 reg = INI_RA(&ah->iniModes, i, 0);
+               u32 val = INI_RA(&ah->iniModes, i, modesIndex);
+
+               if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup)
+                       val &= ~AR_AN_TOP2_PWDCLKIND;
+
+               REG_WRITE(ah, reg, val);
+
+               if (reg >= 0x7800 && reg < 0x78a0
+                   && ah->config.analog_shiftreg
+                   && (common->bus_ops->ath_bus_type != ATH_USB)) {
+                       udelay(100);
+               }
+
+               DO_DELAY(regWrites);
+       }
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah))
+               REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
+
+       if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) ||
+           AR_SREV_9287_11_OR_LATER(ah))
+               REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+
+       if (AR_SREV_9271_10(ah)) {
+               REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENA);
+               REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_ADC_ON, 0xa);
+       }
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       /* Write common array parameters */
+       for (i = 0; i < ah->iniCommon.ia_rows; i++) {
+               u32 reg = INI_RA(&ah->iniCommon, i, 0);
+               u32 val = INI_RA(&ah->iniCommon, i, 1);
+
+               REG_WRITE(ah, reg, val);
+
+               if (reg >= 0x7800 && reg < 0x78a0
+                   && ah->config.analog_shiftreg
+                   && (common->bus_ops->ath_bus_type != ATH_USB)) {
+                       udelay(100);
+               }
+
+               DO_DELAY(regWrites);
+       }
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
+
+       if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+               REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex,
+                               regWrites);
+
+       ar5008_hw_override_ini(ah, chan);
+       ar5008_hw_set_channel_regs(ah, chan);
+       ar5008_hw_init_chain_masks(ah);
+       ath9k_olc_init(ah);
+       ath9k_hw_apply_txpower(ah, chan, false);
+
+       /* Write analog registers */
+       if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
+               ath_err(ath9k_hw_common(ah), "ar5416SetRfRegs failed\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       u32 rfMode = 0;
+
+       if (chan == NULL)
+               return;
+
+       rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
+               ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+
+       if (!AR_SREV_9280_20_OR_LATER(ah))
+               rfMode |= (IS_CHAN_5GHZ(chan)) ?
+                       AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
+
+       if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+               rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
+
+       REG_WRITE(ah, AR_PHY_MODE, rfMode);
+}
+
+static void ar5008_hw_mark_phy_inactive(struct ath_hw *ah)
+{
+       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+}
+
+static void ar5008_hw_set_delta_slope(struct ath_hw *ah,
+                                     struct ath9k_channel *chan)
+{
+       u32 coef_scaled, ds_coef_exp, ds_coef_man;
+       u32 clockMhzScaled = 0x64000000;
+       struct chan_centers centers;
+
+       if (IS_CHAN_HALF_RATE(chan))
+               clockMhzScaled = clockMhzScaled >> 1;
+       else if (IS_CHAN_QUARTER_RATE(chan))
+               clockMhzScaled = clockMhzScaled >> 2;
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       coef_scaled = clockMhzScaled / centers.synth_center;
+
+       ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+                                     &ds_coef_exp);
+
+       REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+                     AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+                     AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
+
+       coef_scaled = (9 * coef_scaled) / 10;
+
+       ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+                                     &ds_coef_exp);
+
+       REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+                     AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
+       REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+                     AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
+}
+
+static bool ar5008_hw_rfbus_req(struct ath_hw *ah)
+{
+       REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
+       return ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
+                          AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT);
+}
+
+static void ar5008_hw_rfbus_done(struct ath_hw *ah)
+{
+       u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_B(ah->curchan))
+               synthDelay = (4 * synthDelay) / 22;
+       else
+               synthDelay /= 10;
+
+       udelay(synthDelay + BASE_ACTIVATE_DELAY);
+
+       REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+}
+
+static void ar5008_restore_chainmask(struct ath_hw *ah)
+{
+       int rx_chainmask = ah->rxchainmask;
+
+       if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
+               REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
+               REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
+       }
+}
+
+static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah,
+                                        struct ath9k_channel *chan)
+{
+       u32 pll;
+
+       pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+
+       if (chan && IS_CHAN_HALF_RATE(chan))
+               pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+       else if (chan && IS_CHAN_QUARTER_RATE(chan))
+               pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
+
+       if (chan && IS_CHAN_5GHZ(chan))
+               pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
+       else
+               pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
+
+       return pll;
+}
+
+static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah,
+                                        struct ath9k_channel *chan)
+{
+       u32 pll;
+
+       pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
+
+       if (chan && IS_CHAN_HALF_RATE(chan))
+               pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
+       else if (chan && IS_CHAN_QUARTER_RATE(chan))
+               pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
+
+       if (chan && IS_CHAN_5GHZ(chan))
+               pll |= SM(0xa, AR_RTC_PLL_DIV);
+       else
+               pll |= SM(0xb, AR_RTC_PLL_DIV);
+
+       return pll;
+}
+
+static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
+                                     enum ath9k_ani_cmd cmd,
+                                     int param)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_channel *chan = ah->curchan;
+       struct ar5416AniState *aniState = &chan->ani;
+       s32 value, value2;
+
+       switch (cmd & ah->ani_function) {
+       case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+               /*
+                * on == 1 means ofdm weak signal detection is ON
+                * on == 1 is the default, for less noise immunity
+                *
+                * on == 0 means ofdm weak signal detection is OFF
+                * on == 0 means more noise imm
+                */
+               u32 on = param ? 1 : 0;
+               /*
+                * make register setting for default
+                * (weak sig detect ON) come from INI file
+                */
+               int m1ThreshLow = on ?
+                       aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
+               int m2ThreshLow = on ?
+                       aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
+               int m1Thresh = on ?
+                       aniState->iniDef.m1Thresh : m1Thresh_off;
+               int m2Thresh = on ?
+                       aniState->iniDef.m2Thresh : m2Thresh_off;
+               int m2CountThr = on ?
+                       aniState->iniDef.m2CountThr : m2CountThr_off;
+               int m2CountThrLow = on ?
+                       aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
+               int m1ThreshLowExt = on ?
+                       aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
+               int m2ThreshLowExt = on ?
+                       aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
+               int m1ThreshExt = on ?
+                       aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
+               int m2ThreshExt = on ?
+                       aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
+
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                             AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+                             m1ThreshLow);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                             AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+                             m2ThreshLow);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                             AR_PHY_SFCORR_M1_THRESH, m1Thresh);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                             AR_PHY_SFCORR_M2_THRESH, m2Thresh);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                             AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                             AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+                             m2CountThrLow);
+
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
+
+               if (on)
+                       REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+                                   AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+               else
+                       REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+                                   AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+               if (on != aniState->ofdmWeakSigDetect) {
+                       ath_dbg(common, ANI,
+                               "** ch %d: ofdm weak signal: %s=>%s\n",
+                               chan->channel,
+                               aniState->ofdmWeakSigDetect ?
+                               "on" : "off",
+                               on ? "on" : "off");
+                       if (on)
+                               ah->stats.ast_ani_ofdmon++;
+                       else
+                               ah->stats.ast_ani_ofdmoff++;
+                       aniState->ofdmWeakSigDetect = on;
+               }
+               break;
+       }
+       case ATH9K_ANI_FIRSTEP_LEVEL:{
+               u32 level = param;
+
+               if (level >= ARRAY_SIZE(firstep_table)) {
+                       ath_dbg(common, ANI,
+                               "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n",
+                               level, ARRAY_SIZE(firstep_table));
+                       return false;
+               }
+
+               /*
+                * make register setting relative to default
+                * from INI file & cap value
+                */
+               value = firstep_table[level] -
+                       firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
+                       aniState->iniDef.firstep;
+               if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+                       value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+               if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+                       value = ATH9K_SIG_FIRSTEP_SETTING_MAX;
+               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                             AR_PHY_FIND_SIG_FIRSTEP,
+                             value);
+               /*
+                * we need to set first step low register too
+                * make register setting relative to default
+                * from INI file & cap value
+                */
+               value2 = firstep_table[level] -
+                        firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
+                        aniState->iniDef.firstepLow;
+               if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+                       value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+               if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+                       value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX;
+
+               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
+                             AR_PHY_FIND_SIG_FIRSTEP_LOW, value2);
+
+               if (level != aniState->firstepLevel) {
+                       ath_dbg(common, ANI,
+                               "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",
+                               chan->channel,
+                               aniState->firstepLevel,
+                               level,
+                               ATH9K_ANI_FIRSTEP_LVL,
+                               value,
+                               aniState->iniDef.firstep);
+                       ath_dbg(common, ANI,
+                               "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n",
+                               chan->channel,
+                               aniState->firstepLevel,
+                               level,
+                               ATH9K_ANI_FIRSTEP_LVL,
+                               value2,
+                               aniState->iniDef.firstepLow);
+                       if (level > aniState->firstepLevel)
+                               ah->stats.ast_ani_stepup++;
+                       else if (level < aniState->firstepLevel)
+                               ah->stats.ast_ani_stepdown++;
+                       aniState->firstepLevel = level;
+               }
+               break;
+       }
+       case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+               u32 level = param;
+
+               if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
+                       ath_dbg(common, ANI,
+                               "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n",
+                               level, ARRAY_SIZE(cycpwrThr1_table));
+                       return false;
+               }
+               /*
+                * make register setting relative to default
+                * from INI file & cap value
+                */
+               value = cycpwrThr1_table[level] -
+                       cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
+                       aniState->iniDef.cycpwrThr1;
+               if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+                       value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+               if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+                       value = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
+               REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+                             AR_PHY_TIMING5_CYCPWR_THR1,
+                             value);
+
+               /*
+                * set AR_PHY_EXT_CCA for extension channel
+                * make register setting relative to default
+                * from INI file & cap value
+                */
+               value2 = cycpwrThr1_table[level] -
+                        cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
+                        aniState->iniDef.cycpwrThr1Ext;
+               if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+                       value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+               if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+                       value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
+               REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+                             AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2);
+
+               if (level != aniState->spurImmunityLevel) {
+                       ath_dbg(common, ANI,
+                               "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n",
+                               chan->channel,
+                               aniState->spurImmunityLevel,
+                               level,
+                               ATH9K_ANI_SPUR_IMMUNE_LVL,
+                               value,
+                               aniState->iniDef.cycpwrThr1);
+                       ath_dbg(common, ANI,
+                               "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n",
+                               chan->channel,
+                               aniState->spurImmunityLevel,
+                               level,
+                               ATH9K_ANI_SPUR_IMMUNE_LVL,
+                               value2,
+                               aniState->iniDef.cycpwrThr1Ext);
+                       if (level > aniState->spurImmunityLevel)
+                               ah->stats.ast_ani_spurup++;
+                       else if (level < aniState->spurImmunityLevel)
+                               ah->stats.ast_ani_spurdown++;
+                       aniState->spurImmunityLevel = level;
+               }
+               break;
+       }
+       case ATH9K_ANI_MRC_CCK:
+               /*
+                * You should not see this as AR5008, AR9001, AR9002
+                * does not have hardware support for MRC CCK.
+                */
+               WARN_ON(1);
+               break;
+       case ATH9K_ANI_PRESENT:
+               break;
+       default:
+               ath_dbg(common, ANI, "invalid cmd %u\n", cmd);
+               return false;
+       }
+
+       ath_dbg(common, ANI,
+               "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
+               aniState->spurImmunityLevel,
+               aniState->ofdmWeakSigDetect ? "on" : "off",
+               aniState->firstepLevel,
+               aniState->mrcCCK ? "on" : "off",
+               aniState->listenTime,
+               aniState->ofdmPhyErrCount,
+               aniState->cckPhyErrCount);
+       return true;
+}
+
+static void ar5008_hw_do_getnf(struct ath_hw *ah,
+                             int16_t nfarray[NUM_NF_READINGS])
+{
+       int16_t nf;
+
+       nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
+       nfarray[0] = sign_extend32(nf, 8);
+
+       nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
+       nfarray[1] = sign_extend32(nf, 8);
+
+       nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
+       nfarray[2] = sign_extend32(nf, 8);
+
+       if (!IS_CHAN_HT40(ah->curchan))
+               return;
+
+       nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
+       nfarray[3] = sign_extend32(nf, 8);
+
+       nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
+       nfarray[4] = sign_extend32(nf, 8);
+
+       nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
+       nfarray[5] = sign_extend32(nf, 8);
+}
+
+/*
+ * Initialize the ANI register values with default (ini) values.
+ * This routine is called during a (full) hardware reset after
+ * all the registers are initialised from the INI.
+ */
+static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_channel *chan = ah->curchan;
+       struct ar5416AniState *aniState = &chan->ani;
+       struct ath9k_ani_default *iniDef;
+       u32 val;
+
+       iniDef = &aniState->iniDef;
+
+       ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
+               ah->hw_version.macVersion,
+               ah->hw_version.macRev,
+               ah->opmode,
+               chan->channel,
+               chan->channelFlags);
+
+       val = REG_READ(ah, AR_PHY_SFCORR);
+       iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
+       iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH);
+       iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR);
+
+       val = REG_READ(ah, AR_PHY_SFCORR_LOW);
+       iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW);
+       iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW);
+       iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW);
+
+       val = REG_READ(ah, AR_PHY_SFCORR_EXT);
+       iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH);
+       iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH);
+       iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW);
+       iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW);
+       iniDef->firstep = REG_READ_FIELD(ah,
+                                        AR_PHY_FIND_SIG,
+                                        AR_PHY_FIND_SIG_FIRSTEP);
+       iniDef->firstepLow = REG_READ_FIELD(ah,
+                                           AR_PHY_FIND_SIG_LOW,
+                                           AR_PHY_FIND_SIG_FIRSTEP_LOW);
+       iniDef->cycpwrThr1 = REG_READ_FIELD(ah,
+                                           AR_PHY_TIMING5,
+                                           AR_PHY_TIMING5_CYCPWR_THR1);
+       iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah,
+                                              AR_PHY_EXT_CCA,
+                                              AR_PHY_EXT_TIMING5_CYCPWR_THR1);
+
+       /* these levels just got reset to defaults by the INI */
+       aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
+       aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
+       aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
+       aniState->mrcCCK = false; /* not available on pre AR9003 */
+}
+
+static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
+{
+       ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ;
+       ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ;
+       ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ;
+       ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ;
+       ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ;
+       ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ;
+}
+
+static void ar5008_hw_set_radar_params(struct ath_hw *ah,
+                                      struct ath_hw_radar_conf *conf)
+{
+       u32 radar_0 = 0, radar_1 = 0;
+
+       if (!conf) {
+               REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
+               return;
+       }
+
+       radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA;
+       radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR);
+       radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI);
+       radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT);
+       radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
+       radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
+
+       radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
+       radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
+       radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
+       radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH);
+       radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH);
+
+       REG_WRITE(ah, AR_PHY_RADAR_0, radar_0);
+       REG_WRITE(ah, AR_PHY_RADAR_1, radar_1);
+       if (conf->ext_channel)
+               REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+       else
+               REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+}
+
+static void ar5008_hw_set_radar_conf(struct ath_hw *ah)
+{
+       struct ath_hw_radar_conf *conf = &ah->radar_conf;
+
+       conf->fir_power = -33;
+       conf->radar_rssi = 20;
+       conf->pulse_height = 10;
+       conf->pulse_rssi = 24;
+       conf->pulse_inband = 15;
+       conf->pulse_maxlen = 255;
+       conf->pulse_inband_step = 12;
+       conf->radar_inband = 8;
+}
+
+void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
+{
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+       static const u32 ar5416_cca_regs[6] = {
+               AR_PHY_CCA,
+               AR_PHY_CH1_CCA,
+               AR_PHY_CH2_CCA,
+               AR_PHY_EXT_CCA,
+               AR_PHY_CH1_EXT_CCA,
+               AR_PHY_CH2_EXT_CCA
+       };
+
+       priv_ops->rf_set_freq = ar5008_hw_set_channel;
+       priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
+
+       priv_ops->rf_alloc_ext_banks = ar5008_hw_rf_alloc_ext_banks;
+       priv_ops->rf_free_ext_banks = ar5008_hw_rf_free_ext_banks;
+       priv_ops->set_rf_regs = ar5008_hw_set_rf_regs;
+       priv_ops->set_channel_regs = ar5008_hw_set_channel_regs;
+       priv_ops->init_bb = ar5008_hw_init_bb;
+       priv_ops->process_ini = ar5008_hw_process_ini;
+       priv_ops->set_rfmode = ar5008_hw_set_rfmode;
+       priv_ops->mark_phy_inactive = ar5008_hw_mark_phy_inactive;
+       priv_ops->set_delta_slope = ar5008_hw_set_delta_slope;
+       priv_ops->rfbus_req = ar5008_hw_rfbus_req;
+       priv_ops->rfbus_done = ar5008_hw_rfbus_done;
+       priv_ops->restore_chainmask = ar5008_restore_chainmask;
+       priv_ops->do_getnf = ar5008_hw_do_getnf;
+       priv_ops->set_radar_params = ar5008_hw_set_radar_params;
+
+       priv_ops->ani_control = ar5008_hw_ani_control_new;
+       priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
+
+       if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
+               priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
+       else
+               priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
+
+       ar5008_hw_set_nf_limits(ah);
+       ar5008_hw_set_radar_conf(ah);
+       memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs));
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9001_initvals.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9001_initvals.h
new file mode 100644 (file)
index 0000000..ea4a230
--- /dev/null
@@ -0,0 +1,1089 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+static const u32 ar5416Modes_9100[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+       {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
+       {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+       {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+       {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
+       {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204},
+       {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
+       {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e},
+       {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff},
+       {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+       {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+       {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+       {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+       {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00},
+       {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+       {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+       {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+       {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+       {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+       {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+       {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+       {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+       {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+       {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+       {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+       {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+       {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+       {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+       {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar5416Common_9100[][2] = {
+       /* Addr      allmodes  */
+       {0x0000000c, 0x00000000},
+       {0x00000030, 0x00020015},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000008},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00000054, 0x0000001f},
+       {0x00000800, 0x00000000},
+       {0x00000804, 0x00000000},
+       {0x00000808, 0x00000000},
+       {0x0000080c, 0x00000000},
+       {0x00000810, 0x00000000},
+       {0x00000814, 0x00000000},
+       {0x00000818, 0x00000000},
+       {0x0000081c, 0x00000000},
+       {0x00000820, 0x00000000},
+       {0x00000824, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x00001230, 0x00000000},
+       {0x00001270, 0x00000000},
+       {0x00001038, 0x00000000},
+       {0x00001078, 0x00000000},
+       {0x000010b8, 0x00000000},
+       {0x000010f8, 0x00000000},
+       {0x00001138, 0x00000000},
+       {0x00001178, 0x00000000},
+       {0x000011b8, 0x00000000},
+       {0x000011f8, 0x00000000},
+       {0x00001238, 0x00000000},
+       {0x00001278, 0x00000000},
+       {0x000012b8, 0x00000000},
+       {0x000012f8, 0x00000000},
+       {0x00001338, 0x00000000},
+       {0x00001378, 0x00000000},
+       {0x000013b8, 0x00000000},
+       {0x000013f8, 0x00000000},
+       {0x00001438, 0x00000000},
+       {0x00001478, 0x00000000},
+       {0x000014b8, 0x00000000},
+       {0x000014f8, 0x00000000},
+       {0x00001538, 0x00000000},
+       {0x00001578, 0x00000000},
+       {0x000015b8, 0x00000000},
+       {0x000015f8, 0x00000000},
+       {0x00001638, 0x00000000},
+       {0x00001678, 0x00000000},
+       {0x000016b8, 0x00000000},
+       {0x000016f8, 0x00000000},
+       {0x00001738, 0x00000000},
+       {0x00001778, 0x00000000},
+       {0x000017b8, 0x00000000},
+       {0x000017f8, 0x00000000},
+       {0x0000103c, 0x00000000},
+       {0x0000107c, 0x00000000},
+       {0x000010bc, 0x00000000},
+       {0x000010fc, 0x00000000},
+       {0x0000113c, 0x00000000},
+       {0x0000117c, 0x00000000},
+       {0x000011bc, 0x00000000},
+       {0x000011fc, 0x00000000},
+       {0x0000123c, 0x00000000},
+       {0x0000127c, 0x00000000},
+       {0x000012bc, 0x00000000},
+       {0x000012fc, 0x00000000},
+       {0x0000133c, 0x00000000},
+       {0x0000137c, 0x00000000},
+       {0x000013bc, 0x00000000},
+       {0x000013fc, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00020010, 0x00000003},
+       {0x00020038, 0x000004c2},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000700},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008048, 0x40000000},
+       {0x00008054, 0x00004000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x000080c0, 0x2a82301a},
+       {0x000080c4, 0x05dc01e0},
+       {0x000080c8, 0x1f402710},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00001e00},
+       {0x000080d4, 0x00000000},
+       {0x000080d8, 0x00400000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x003f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080f8, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00020000},
+       {0x00008104, 0x00000001},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000168},
+       {0x00008118, 0x000100aa},
+       {0x0000811c, 0x00003210},
+       {0x00008120, 0x08f04800},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x00000000},
+       {0x00008144, 0x00000000},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x32143320},
+       {0x00008174, 0xfaa4fa50},
+       {0x00008178, 0x00000100},
+       {0x0000817c, 0x00000000},
+       {0x000081c4, 0x00000000},
+       {0x000081d0, 0x00003210},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008200, 0x00000000},
+       {0x00008204, 0x00000000},
+       {0x00008208, 0x00000000},
+       {0x0000820c, 0x00000000},
+       {0x00008210, 0x00000000},
+       {0x00008214, 0x00000000},
+       {0x00008218, 0x00000000},
+       {0x0000821c, 0x00000000},
+       {0x00008220, 0x00000000},
+       {0x00008224, 0x00000000},
+       {0x00008228, 0x00000000},
+       {0x0000822c, 0x00000000},
+       {0x00008230, 0x00000000},
+       {0x00008234, 0x00000000},
+       {0x00008238, 0x00000000},
+       {0x0000823c, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000100},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x400000ff},
+       {0x00008260, 0x00080922},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000000},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x00000000},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x00008300, 0x00000000},
+       {0x00008304, 0x00000000},
+       {0x00008308, 0x00000000},
+       {0x0000830c, 0x00000000},
+       {0x00008310, 0x00000000},
+       {0x00008314, 0x00000000},
+       {0x00008318, 0x00000000},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000e00},
+       {0x00008338, 0x00000000},
+       {0x0000833c, 0x00000000},
+       {0x00008340, 0x000107ff},
+       {0x00009808, 0x00000000},
+       {0x0000980c, 0xad848e19},
+       {0x00009810, 0x7d14e000},
+       {0x00009814, 0x9c0a9f6b},
+       {0x0000981c, 0x00000000},
+       {0x0000982c, 0x0000a000},
+       {0x00009830, 0x00000000},
+       {0x0000983c, 0x00200400},
+       {0x00009840, 0x206a01ae},
+       {0x0000984c, 0x1284233c},
+       {0x00009854, 0x00000859},
+       {0x00009900, 0x00000000},
+       {0x00009904, 0x00000000},
+       {0x00009908, 0x00000000},
+       {0x0000990c, 0x00000000},
+       {0x0000991c, 0x10000fff},
+       {0x00009920, 0x05100000},
+       {0x0000a920, 0x05100000},
+       {0x0000b920, 0x05100000},
+       {0x00009928, 0x00000001},
+       {0x0000992c, 0x00000004},
+       {0x00009934, 0x1e1f2022},
+       {0x00009938, 0x0a0b0c0d},
+       {0x0000993c, 0x00000000},
+       {0x00009948, 0x9280b212},
+       {0x0000994c, 0x00020028},
+       {0x0000c95c, 0x004b6a8e},
+       {0x0000c968, 0x000003ce},
+       {0x00009970, 0x190fb515},
+       {0x00009974, 0x00000000},
+       {0x00009978, 0x00000001},
+       {0x0000997c, 0x00000000},
+       {0x00009980, 0x00000000},
+       {0x00009984, 0x00000000},
+       {0x00009988, 0x00000000},
+       {0x0000998c, 0x00000000},
+       {0x00009990, 0x00000000},
+       {0x00009994, 0x00000000},
+       {0x00009998, 0x00000000},
+       {0x0000999c, 0x00000000},
+       {0x000099a0, 0x00000000},
+       {0x000099a4, 0x00000001},
+       {0x000099a8, 0x201fff00},
+       {0x000099ac, 0x006f0000},
+       {0x000099b0, 0x03051000},
+       {0x000099dc, 0x00000000},
+       {0x000099e0, 0x00000200},
+       {0x000099e4, 0xaaaaaaaa},
+       {0x000099e8, 0x3c466478},
+       {0x000099ec, 0x0cc80caa},
+       {0x000099fc, 0x00001042},
+       {0x00009b00, 0x00000000},
+       {0x00009b04, 0x00000001},
+       {0x00009b08, 0x00000002},
+       {0x00009b0c, 0x00000003},
+       {0x00009b10, 0x00000004},
+       {0x00009b14, 0x00000005},
+       {0x00009b18, 0x00000008},
+       {0x00009b1c, 0x00000009},
+       {0x00009b20, 0x0000000a},
+       {0x00009b24, 0x0000000b},
+       {0x00009b28, 0x0000000c},
+       {0x00009b2c, 0x0000000d},
+       {0x00009b30, 0x00000010},
+       {0x00009b34, 0x00000011},
+       {0x00009b38, 0x00000012},
+       {0x00009b3c, 0x00000013},
+       {0x00009b40, 0x00000014},
+       {0x00009b44, 0x00000015},
+       {0x00009b48, 0x00000018},
+       {0x00009b4c, 0x00000019},
+       {0x00009b50, 0x0000001a},
+       {0x00009b54, 0x0000001b},
+       {0x00009b58, 0x0000001c},
+       {0x00009b5c, 0x0000001d},
+       {0x00009b60, 0x00000020},
+       {0x00009b64, 0x00000021},
+       {0x00009b68, 0x00000022},
+       {0x00009b6c, 0x00000023},
+       {0x00009b70, 0x00000024},
+       {0x00009b74, 0x00000025},
+       {0x00009b78, 0x00000028},
+       {0x00009b7c, 0x00000029},
+       {0x00009b80, 0x0000002a},
+       {0x00009b84, 0x0000002b},
+       {0x00009b88, 0x0000002c},
+       {0x00009b8c, 0x0000002d},
+       {0x00009b90, 0x00000030},
+       {0x00009b94, 0x00000031},
+       {0x00009b98, 0x00000032},
+       {0x00009b9c, 0x00000033},
+       {0x00009ba0, 0x00000034},
+       {0x00009ba4, 0x00000035},
+       {0x00009ba8, 0x00000035},
+       {0x00009bac, 0x00000035},
+       {0x00009bb0, 0x00000035},
+       {0x00009bb4, 0x00000035},
+       {0x00009bb8, 0x00000035},
+       {0x00009bbc, 0x00000035},
+       {0x00009bc0, 0x00000035},
+       {0x00009bc4, 0x00000035},
+       {0x00009bc8, 0x00000035},
+       {0x00009bcc, 0x00000035},
+       {0x00009bd0, 0x00000035},
+       {0x00009bd4, 0x00000035},
+       {0x00009bd8, 0x00000035},
+       {0x00009bdc, 0x00000035},
+       {0x00009be0, 0x00000035},
+       {0x00009be4, 0x00000035},
+       {0x00009be8, 0x00000035},
+       {0x00009bec, 0x00000035},
+       {0x00009bf0, 0x00000035},
+       {0x00009bf4, 0x00000035},
+       {0x00009bf8, 0x00000010},
+       {0x00009bfc, 0x0000001a},
+       {0x0000a210, 0x40806333},
+       {0x0000a214, 0x00106c10},
+       {0x0000a218, 0x009c4060},
+       {0x0000a220, 0x018830c6},
+       {0x0000a224, 0x00000400},
+       {0x0000a228, 0x001a0bb5},
+       {0x0000a22c, 0x00000000},
+       {0x0000a234, 0x20202020},
+       {0x0000a238, 0x20202020},
+       {0x0000a23c, 0x13c889af},
+       {0x0000a240, 0x38490a20},
+       {0x0000a244, 0x00007bb6},
+       {0x0000a248, 0x0fff3ffc},
+       {0x0000a24c, 0x00000001},
+       {0x0000a250, 0x0000e000},
+       {0x0000a254, 0x00000000},
+       {0x0000a258, 0x0cc75380},
+       {0x0000a25c, 0x0f0f0f01},
+       {0x0000a260, 0xdfa91f01},
+       {0x0000a268, 0x00000001},
+       {0x0000a26c, 0x0ebae9c6},
+       {0x0000b26c, 0x0ebae9c6},
+       {0x0000c26c, 0x0ebae9c6},
+       {0x0000d270, 0x00820820},
+       {0x0000a278, 0x1ce739ce},
+       {0x0000a27c, 0x050701ce},
+       {0x0000a338, 0x00000000},
+       {0x0000a33c, 0x00000000},
+       {0x0000a340, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a348, 0x3fffffff},
+       {0x0000a34c, 0x3fffffff},
+       {0x0000a350, 0x3fffffff},
+       {0x0000a354, 0x0003ffff},
+       {0x0000a358, 0x79a8aa33},
+       {0x0000d35c, 0x07ffffef},
+       {0x0000d360, 0x0fffffe7},
+       {0x0000d364, 0x17ffffe5},
+       {0x0000d368, 0x1fffffe4},
+       {0x0000d36c, 0x37ffffe3},
+       {0x0000d370, 0x3fffffe3},
+       {0x0000d374, 0x57ffffe3},
+       {0x0000d378, 0x5fffffe2},
+       {0x0000d37c, 0x7fffffe2},
+       {0x0000d380, 0x7f3c7bba},
+       {0x0000d384, 0xf3307ff0},
+       {0x0000a388, 0x0c000000},
+       {0x0000a38c, 0x20202020},
+       {0x0000a390, 0x20202020},
+       {0x0000a394, 0x1ce739ce},
+       {0x0000a398, 0x000001ce},
+       {0x0000a39c, 0x00000001},
+       {0x0000a3a0, 0x00000000},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0x00000000},
+       {0x0000a3ac, 0x00000000},
+       {0x0000a3b0, 0x00000000},
+       {0x0000a3b4, 0x00000000},
+       {0x0000a3b8, 0x00000000},
+       {0x0000a3bc, 0x00000000},
+       {0x0000a3c0, 0x00000000},
+       {0x0000a3c4, 0x00000000},
+       {0x0000a3c8, 0x00000246},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3dc, 0x1ce739ce},
+       {0x0000a3e0, 0x000001ce},
+};
+
+static const u32 ar5416Bank6_9100[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00e00000, 0x00e00000},
+       {0x0000989c, 0x005e0000, 0x005e0000},
+       {0x0000989c, 0x00120000, 0x00120000},
+       {0x0000989c, 0x00620000, 0x00620000},
+       {0x0000989c, 0x00020000, 0x00020000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x005f0000, 0x005f0000},
+       {0x0000989c, 0x00870000, 0x00870000},
+       {0x0000989c, 0x00f90000, 0x00f90000},
+       {0x0000989c, 0x007b0000, 0x007b0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00f50000, 0x00f50000},
+       {0x0000989c, 0x00dc0000, 0x00dc0000},
+       {0x0000989c, 0x00110000, 0x00110000},
+       {0x0000989c, 0x006100a8, 0x006100a8},
+       {0x0000989c, 0x004210a2, 0x004210a2},
+       {0x0000989c, 0x0014000f, 0x0014000f},
+       {0x0000989c, 0x00c40002, 0x00c40002},
+       {0x0000989c, 0x003000f2, 0x003000f2},
+       {0x0000989c, 0x00440016, 0x00440016},
+       {0x0000989c, 0x00410040, 0x00410040},
+       {0x0000989c, 0x000180d6, 0x000180d6},
+       {0x0000989c, 0x0000c0aa, 0x0000c0aa},
+       {0x0000989c, 0x000000b1, 0x000000b1},
+       {0x0000989c, 0x00002000, 0x00002000},
+       {0x0000989c, 0x000000d4, 0x000000d4},
+       {0x000098d0, 0x0000000f, 0x0010000f},
+};
+
+static const u32 ar5416Bank6TPC_9100[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00000000, 0x00000000},
+       {0x0000989c, 0x00e00000, 0x00e00000},
+       {0x0000989c, 0x005e0000, 0x005e0000},
+       {0x0000989c, 0x00120000, 0x00120000},
+       {0x0000989c, 0x00620000, 0x00620000},
+       {0x0000989c, 0x00020000, 0x00020000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x40ff0000, 0x40ff0000},
+       {0x0000989c, 0x005f0000, 0x005f0000},
+       {0x0000989c, 0x00870000, 0x00870000},
+       {0x0000989c, 0x00f90000, 0x00f90000},
+       {0x0000989c, 0x007b0000, 0x007b0000},
+       {0x0000989c, 0x00ff0000, 0x00ff0000},
+       {0x0000989c, 0x00f50000, 0x00f50000},
+       {0x0000989c, 0x00dc0000, 0x00dc0000},
+       {0x0000989c, 0x00110000, 0x00110000},
+       {0x0000989c, 0x006100a8, 0x006100a8},
+       {0x0000989c, 0x00423022, 0x00423022},
+       {0x0000989c, 0x2014008f, 0x2014008f},
+       {0x0000989c, 0x00c40002, 0x00c40002},
+       {0x0000989c, 0x003000f2, 0x003000f2},
+       {0x0000989c, 0x00440016, 0x00440016},
+       {0x0000989c, 0x00410040, 0x00410040},
+       {0x0000989c, 0x0001805e, 0x0001805e},
+       {0x0000989c, 0x0000c0ab, 0x0000c0ab},
+       {0x0000989c, 0x000000e1, 0x000000e1},
+       {0x0000989c, 0x00007080, 0x00007080},
+       {0x0000989c, 0x000000d4, 0x000000d4},
+       {0x000098d0, 0x0000000f, 0x0010000f},
+};
+
+static const u32 ar5416Addac_9100[][2] = {
+       /* Addr      allmodes  */
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000010},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x000000c0},
+       {0x0000989c, 0x00000015},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x000098cc, 0x00000000},
+};
+
+static const u32 ar5416Modes_9160[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+       {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
+       {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+       {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+       {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
+       {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+       {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+       {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+       {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+       {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+       {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00},
+       {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+       {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+       {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+       {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+       {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+       {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+       {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+       {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+       {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+       {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+       {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+       {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+       {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+       {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+       {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar5416Common_9160[][2] = {
+       /* Addr      allmodes  */
+       {0x0000000c, 0x00000000},
+       {0x00000030, 0x00020015},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000008},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00000054, 0x0000001f},
+       {0x00000800, 0x00000000},
+       {0x00000804, 0x00000000},
+       {0x00000808, 0x00000000},
+       {0x0000080c, 0x00000000},
+       {0x00000810, 0x00000000},
+       {0x00000814, 0x00000000},
+       {0x00000818, 0x00000000},
+       {0x0000081c, 0x00000000},
+       {0x00000820, 0x00000000},
+       {0x00000824, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x00001230, 0x00000000},
+       {0x00001270, 0x00000000},
+       {0x00001038, 0x00000000},
+       {0x00001078, 0x00000000},
+       {0x000010b8, 0x00000000},
+       {0x000010f8, 0x00000000},
+       {0x00001138, 0x00000000},
+       {0x00001178, 0x00000000},
+       {0x000011b8, 0x00000000},
+       {0x000011f8, 0x00000000},
+       {0x00001238, 0x00000000},
+       {0x00001278, 0x00000000},
+       {0x000012b8, 0x00000000},
+       {0x000012f8, 0x00000000},
+       {0x00001338, 0x00000000},
+       {0x00001378, 0x00000000},
+       {0x000013b8, 0x00000000},
+       {0x000013f8, 0x00000000},
+       {0x00001438, 0x00000000},
+       {0x00001478, 0x00000000},
+       {0x000014b8, 0x00000000},
+       {0x000014f8, 0x00000000},
+       {0x00001538, 0x00000000},
+       {0x00001578, 0x00000000},
+       {0x000015b8, 0x00000000},
+       {0x000015f8, 0x00000000},
+       {0x00001638, 0x00000000},
+       {0x00001678, 0x00000000},
+       {0x000016b8, 0x00000000},
+       {0x000016f8, 0x00000000},
+       {0x00001738, 0x00000000},
+       {0x00001778, 0x00000000},
+       {0x000017b8, 0x00000000},
+       {0x000017f8, 0x00000000},
+       {0x0000103c, 0x00000000},
+       {0x0000107c, 0x00000000},
+       {0x000010bc, 0x00000000},
+       {0x000010fc, 0x00000000},
+       {0x0000113c, 0x00000000},
+       {0x0000117c, 0x00000000},
+       {0x000011bc, 0x00000000},
+       {0x000011fc, 0x00000000},
+       {0x0000123c, 0x00000000},
+       {0x0000127c, 0x00000000},
+       {0x000012bc, 0x00000000},
+       {0x000012fc, 0x00000000},
+       {0x0000133c, 0x00000000},
+       {0x0000137c, 0x00000000},
+       {0x000013bc, 0x00000000},
+       {0x000013fc, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00004030, 0x00000002},
+       {0x0000403c, 0x00000002},
+       {0x00007010, 0x00000020},
+       {0x00007038, 0x000004c2},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000700},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008048, 0x40000000},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x000080c0, 0x2a82301a},
+       {0x000080c4, 0x05dc01e0},
+       {0x000080c8, 0x1f402710},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00001e00},
+       {0x000080d4, 0x00000000},
+       {0x000080d8, 0x00400000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x003f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080f8, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00020000},
+       {0x00008104, 0x00000001},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000168},
+       {0x00008118, 0x000100aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x00000000},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x32143320},
+       {0x00008174, 0xfaa4fa50},
+       {0x00008178, 0x00000100},
+       {0x0000817c, 0x00000000},
+       {0x000081c4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008200, 0x00000000},
+       {0x00008204, 0x00000000},
+       {0x00008208, 0x00000000},
+       {0x0000820c, 0x00000000},
+       {0x00008210, 0x00000000},
+       {0x00008214, 0x00000000},
+       {0x00008218, 0x00000000},
+       {0x0000821c, 0x00000000},
+       {0x00008220, 0x00000000},
+       {0x00008224, 0x00000000},
+       {0x00008228, 0x00000000},
+       {0x0000822c, 0x00000000},
+       {0x00008230, 0x00000000},
+       {0x00008234, 0x00000000},
+       {0x00008238, 0x00000000},
+       {0x0000823c, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000100},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x400000ff},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x88a00010},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000000},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x00000000},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x00008300, 0x00000000},
+       {0x00008304, 0x00000000},
+       {0x00008308, 0x00000000},
+       {0x0000830c, 0x00000000},
+       {0x00008310, 0x00000000},
+       {0x00008314, 0x00000000},
+       {0x00008318, 0x00000000},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000e00},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x00000000},
+       {0x00008340, 0x000107ff},
+       {0x00009808, 0x00000000},
+       {0x0000980c, 0xad848e19},
+       {0x00009810, 0x7d14e000},
+       {0x00009814, 0x9c0a9f6b},
+       {0x0000981c, 0x00000000},
+       {0x0000982c, 0x0000a000},
+       {0x00009830, 0x00000000},
+       {0x0000983c, 0x00200400},
+       {0x00009840, 0x206a01ae},
+       {0x0000984c, 0x1284233c},
+       {0x00009854, 0x00000859},
+       {0x00009900, 0x00000000},
+       {0x00009904, 0x00000000},
+       {0x00009908, 0x00000000},
+       {0x0000990c, 0x00000000},
+       {0x0000991c, 0x10000fff},
+       {0x00009920, 0x05100000},
+       {0x0000a920, 0x05100000},
+       {0x0000b920, 0x05100000},
+       {0x00009928, 0x00000001},
+       {0x0000992c, 0x00000004},
+       {0x00009934, 0x1e1f2022},
+       {0x00009938, 0x0a0b0c0d},
+       {0x0000993c, 0x00000000},
+       {0x00009948, 0x9280b212},
+       {0x0000994c, 0x00020028},
+       {0x00009954, 0x5f3ca3de},
+       {0x00009958, 0x2108ecff},
+       {0x00009940, 0x00750604},
+       {0x0000c95c, 0x004b6a8e},
+       {0x00009970, 0x190fb515},
+       {0x00009974, 0x00000000},
+       {0x00009978, 0x00000001},
+       {0x0000997c, 0x00000000},
+       {0x00009980, 0x00000000},
+       {0x00009984, 0x00000000},
+       {0x00009988, 0x00000000},
+       {0x0000998c, 0x00000000},
+       {0x00009990, 0x00000000},
+       {0x00009994, 0x00000000},
+       {0x00009998, 0x00000000},
+       {0x0000999c, 0x00000000},
+       {0x000099a0, 0x00000000},
+       {0x000099a4, 0x00000001},
+       {0x000099a8, 0x201fff00},
+       {0x000099ac, 0x006f0000},
+       {0x000099b0, 0x03051000},
+       {0x000099dc, 0x00000000},
+       {0x000099e0, 0x00000200},
+       {0x000099e4, 0xaaaaaaaa},
+       {0x000099e8, 0x3c466478},
+       {0x000099ec, 0x0cc80caa},
+       {0x000099fc, 0x00001042},
+       {0x00009b00, 0x00000000},
+       {0x00009b04, 0x00000001},
+       {0x00009b08, 0x00000002},
+       {0x00009b0c, 0x00000003},
+       {0x00009b10, 0x00000004},
+       {0x00009b14, 0x00000005},
+       {0x00009b18, 0x00000008},
+       {0x00009b1c, 0x00000009},
+       {0x00009b20, 0x0000000a},
+       {0x00009b24, 0x0000000b},
+       {0x00009b28, 0x0000000c},
+       {0x00009b2c, 0x0000000d},
+       {0x00009b30, 0x00000010},
+       {0x00009b34, 0x00000011},
+       {0x00009b38, 0x00000012},
+       {0x00009b3c, 0x00000013},
+       {0x00009b40, 0x00000014},
+       {0x00009b44, 0x00000015},
+       {0x00009b48, 0x00000018},
+       {0x00009b4c, 0x00000019},
+       {0x00009b50, 0x0000001a},
+       {0x00009b54, 0x0000001b},
+       {0x00009b58, 0x0000001c},
+       {0x00009b5c, 0x0000001d},
+       {0x00009b60, 0x00000020},
+       {0x00009b64, 0x00000021},
+       {0x00009b68, 0x00000022},
+       {0x00009b6c, 0x00000023},
+       {0x00009b70, 0x00000024},
+       {0x00009b74, 0x00000025},
+       {0x00009b78, 0x00000028},
+       {0x00009b7c, 0x00000029},
+       {0x00009b80, 0x0000002a},
+       {0x00009b84, 0x0000002b},
+       {0x00009b88, 0x0000002c},
+       {0x00009b8c, 0x0000002d},
+       {0x00009b90, 0x00000030},
+       {0x00009b94, 0x00000031},
+       {0x00009b98, 0x00000032},
+       {0x00009b9c, 0x00000033},
+       {0x00009ba0, 0x00000034},
+       {0x00009ba4, 0x00000035},
+       {0x00009ba8, 0x00000035},
+       {0x00009bac, 0x00000035},
+       {0x00009bb0, 0x00000035},
+       {0x00009bb4, 0x00000035},
+       {0x00009bb8, 0x00000035},
+       {0x00009bbc, 0x00000035},
+       {0x00009bc0, 0x00000035},
+       {0x00009bc4, 0x00000035},
+       {0x00009bc8, 0x00000035},
+       {0x00009bcc, 0x00000035},
+       {0x00009bd0, 0x00000035},
+       {0x00009bd4, 0x00000035},
+       {0x00009bd8, 0x00000035},
+       {0x00009bdc, 0x00000035},
+       {0x00009be0, 0x00000035},
+       {0x00009be4, 0x00000035},
+       {0x00009be8, 0x00000035},
+       {0x00009bec, 0x00000035},
+       {0x00009bf0, 0x00000035},
+       {0x00009bf4, 0x00000035},
+       {0x00009bf8, 0x00000010},
+       {0x00009bfc, 0x0000001a},
+       {0x0000a210, 0x40806333},
+       {0x0000a214, 0x00106c10},
+       {0x0000a218, 0x009c4060},
+       {0x0000a220, 0x018830c6},
+       {0x0000a224, 0x00000400},
+       {0x0000a228, 0x001a0bb5},
+       {0x0000a22c, 0x00000000},
+       {0x0000a234, 0x20202020},
+       {0x0000a238, 0x20202020},
+       {0x0000a23c, 0x13c889af},
+       {0x0000a240, 0x38490a20},
+       {0x0000a244, 0x00007bb6},
+       {0x0000a248, 0x0fff3ffc},
+       {0x0000a24c, 0x00000001},
+       {0x0000a250, 0x0000e000},
+       {0x0000a254, 0x00000000},
+       {0x0000a258, 0x0cc75380},
+       {0x0000a25c, 0x0f0f0f01},
+       {0x0000a260, 0xdfa91f01},
+       {0x0000a268, 0x00000001},
+       {0x0000a26c, 0x0e79e5c6},
+       {0x0000b26c, 0x0e79e5c6},
+       {0x0000c26c, 0x0e79e5c6},
+       {0x0000d270, 0x00820820},
+       {0x0000a278, 0x1ce739ce},
+       {0x0000a27c, 0x050701ce},
+       {0x0000a338, 0x00000000},
+       {0x0000a33c, 0x00000000},
+       {0x0000a340, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a348, 0x3fffffff},
+       {0x0000a34c, 0x3fffffff},
+       {0x0000a350, 0x3fffffff},
+       {0x0000a354, 0x0003ffff},
+       {0x0000a358, 0x79bfaa03},
+       {0x0000d35c, 0x07ffffef},
+       {0x0000d360, 0x0fffffe7},
+       {0x0000d364, 0x17ffffe5},
+       {0x0000d368, 0x1fffffe4},
+       {0x0000d36c, 0x37ffffe3},
+       {0x0000d370, 0x3fffffe3},
+       {0x0000d374, 0x57ffffe3},
+       {0x0000d378, 0x5fffffe2},
+       {0x0000d37c, 0x7fffffe2},
+       {0x0000d380, 0x7f3c7bba},
+       {0x0000d384, 0xf3307ff0},
+       {0x0000a388, 0x0c000000},
+       {0x0000a38c, 0x20202020},
+       {0x0000a390, 0x20202020},
+       {0x0000a394, 0x1ce739ce},
+       {0x0000a398, 0x000001ce},
+       {0x0000a39c, 0x00000001},
+       {0x0000a3a0, 0x00000000},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0x00000000},
+       {0x0000a3ac, 0x00000000},
+       {0x0000a3b0, 0x00000000},
+       {0x0000a3b4, 0x00000000},
+       {0x0000a3b8, 0x00000000},
+       {0x0000a3bc, 0x00000000},
+       {0x0000a3c0, 0x00000000},
+       {0x0000a3c4, 0x00000000},
+       {0x0000a3c8, 0x00000246},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3dc, 0x1ce739ce},
+       {0x0000a3e0, 0x000001ce},
+};
+
+static const u32 ar5416Addac_9160[][2] = {
+       /* Addr      allmodes  */
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x000000c0},
+       {0x0000989c, 0x00000018},
+       {0x0000989c, 0x00000004},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x000000c0},
+       {0x0000989c, 0x00000019},
+       {0x0000989c, 0x00000004},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000004},
+       {0x0000989c, 0x00000003},
+       {0x0000989c, 0x00000008},
+       {0x0000989c, 0x00000000},
+       {0x000098cc, 0x00000000},
+};
+
+static const u32 ar5416Addac_9160_1_1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x000000c0},
+       {0x0000989c, 0x00000018},
+       {0x0000989c, 0x00000004},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x000000c0},
+       {0x0000989c, 0x00000019},
+       {0x0000989c, 0x00000004},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x000098cc, 0x00000000},
+};
+
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9002_calib.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9002_calib.c
new file mode 100644 (file)
index 0000000..fec9097
--- /dev/null
@@ -0,0 +1,989 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "ar9002_phy.h"
+
+#define AR9285_CLCAL_REDO_THRESH    1
+
+enum ar9002_cal_types {
+       ADC_GAIN_CAL = BIT(0),
+       ADC_DC_CAL = BIT(1),
+       IQ_MISMATCH_CAL = BIT(2),
+};
+
+static bool ar9002_hw_is_cal_supported(struct ath_hw *ah,
+                               struct ath9k_channel *chan,
+                               enum ar9002_cal_types cal_type)
+{
+       bool supported = false;
+       switch (ah->supp_cals & cal_type) {
+       case IQ_MISMATCH_CAL:
+               /* Run IQ Mismatch for non-CCK only */
+               if (!IS_CHAN_B(chan))
+                       supported = true;
+               break;
+       case ADC_GAIN_CAL:
+       case ADC_DC_CAL:
+               /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
+               if (!IS_CHAN_B(chan) &&
+                   !((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) &&
+                     IS_CHAN_HT20(chan)))
+                       supported = true;
+               break;
+       }
+       return supported;
+}
+
+static void ar9002_hw_setup_calibration(struct ath_hw *ah,
+                                       struct ath9k_cal_list *currCal)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
+                     AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+                     currCal->calData->calCountMax);
+
+       switch (currCal->calData->calType) {
+       case IQ_MISMATCH_CAL:
+               REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
+               ath_dbg(common, CALIBRATE,
+                       "starting IQ Mismatch Calibration\n");
+               break;
+       case ADC_GAIN_CAL:
+               REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
+               ath_dbg(common, CALIBRATE, "starting ADC Gain Calibration\n");
+               break;
+       case ADC_DC_CAL:
+               REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
+               ath_dbg(common, CALIBRATE, "starting ADC DC Calibration\n");
+               break;
+       }
+
+       REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+                   AR_PHY_TIMING_CTRL4_DO_CAL);
+}
+
+static bool ar9002_hw_per_calibration(struct ath_hw *ah,
+                                     struct ath9k_channel *ichan,
+                                     u8 rxchainmask,
+                                     struct ath9k_cal_list *currCal)
+{
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+       bool iscaldone = false;
+
+       if (currCal->calState == CAL_RUNNING) {
+               if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
+                     AR_PHY_TIMING_CTRL4_DO_CAL)) {
+
+                       currCal->calData->calCollect(ah);
+                       ah->cal_samples++;
+
+                       if (ah->cal_samples >=
+                           currCal->calData->calNumSamples) {
+                               int i, numChains = 0;
+                               for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+                                       if (rxchainmask & (1 << i))
+                                               numChains++;
+                               }
+
+                               currCal->calData->calPostProc(ah, numChains);
+                               caldata->CalValid |= currCal->calData->calType;
+                               currCal->calState = CAL_DONE;
+                               iscaldone = true;
+                       } else {
+                               ar9002_hw_setup_calibration(ah, currCal);
+                       }
+               }
+       } else if (!(caldata->CalValid & currCal->calData->calType)) {
+               ath9k_hw_reset_calibration(ah, currCal);
+       }
+
+       return iscaldone;
+}
+
+static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
+{
+       int i;
+
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               ah->totalPowerMeasI[i] +=
+                       REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+               ah->totalPowerMeasQ[i] +=
+                       REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+               ah->totalIqCorrMeas[i] +=
+                       (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+               ath_dbg(ath9k_hw_common(ah), CALIBRATE,
+                       "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+                       ah->cal_samples, i, ah->totalPowerMeasI[i],
+                       ah->totalPowerMeasQ[i],
+                       ah->totalIqCorrMeas[i]);
+       }
+}
+
+static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
+{
+       int i;
+
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               ah->totalAdcIOddPhase[i] +=
+                       REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+               ah->totalAdcIEvenPhase[i] +=
+                       REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+               ah->totalAdcQOddPhase[i] +=
+                       REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+               ah->totalAdcQEvenPhase[i] +=
+                       REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+               ath_dbg(ath9k_hw_common(ah), CALIBRATE,
+                       "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
+                       ah->cal_samples, i,
+                       ah->totalAdcIOddPhase[i],
+                       ah->totalAdcIEvenPhase[i],
+                       ah->totalAdcQOddPhase[i],
+                       ah->totalAdcQEvenPhase[i]);
+       }
+}
+
+static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
+{
+       int i;
+
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               ah->totalAdcDcOffsetIOddPhase[i] +=
+                       (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+               ah->totalAdcDcOffsetIEvenPhase[i] +=
+                       (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+               ah->totalAdcDcOffsetQOddPhase[i] +=
+                       (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+               ah->totalAdcDcOffsetQEvenPhase[i] +=
+                       (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+               ath_dbg(ath9k_hw_common(ah), CALIBRATE,
+                       "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
+                       ah->cal_samples, i,
+                       ah->totalAdcDcOffsetIOddPhase[i],
+                       ah->totalAdcDcOffsetIEvenPhase[i],
+                       ah->totalAdcDcOffsetQOddPhase[i],
+                       ah->totalAdcDcOffsetQEvenPhase[i]);
+       }
+}
+
+static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 powerMeasQ, powerMeasI, iqCorrMeas;
+       u32 qCoffDenom, iCoffDenom;
+       int32_t qCoff, iCoff;
+       int iqCorrNeg, i;
+
+       for (i = 0; i < numChains; i++) {
+               powerMeasI = ah->totalPowerMeasI[i];
+               powerMeasQ = ah->totalPowerMeasQ[i];
+               iqCorrMeas = ah->totalIqCorrMeas[i];
+
+               ath_dbg(common, CALIBRATE,
+                       "Starting IQ Cal and Correction for Chain %d\n",
+                       i);
+
+               ath_dbg(common, CALIBRATE,
+                       "Original: Chn %d iq_corr_meas = 0x%08x\n",
+                       i, ah->totalIqCorrMeas[i]);
+
+               iqCorrNeg = 0;
+
+               if (iqCorrMeas > 0x80000000) {
+                       iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
+                       iqCorrNeg = 1;
+               }
+
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
+                       i, powerMeasI);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
+                       i, powerMeasQ);
+               ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
+
+               iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
+               qCoffDenom = powerMeasQ / 64;
+
+               if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
+                   (qCoffDenom != 0)) {
+                       iCoff = iqCorrMeas / iCoffDenom;
+                       qCoff = powerMeasI / qCoffDenom - 64;
+                       ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
+                               i, iCoff);
+                       ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
+                               i, qCoff);
+
+                       iCoff = iCoff & 0x3f;
+                       ath_dbg(common, CALIBRATE,
+                               "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
+                       if (iqCorrNeg == 0x0)
+                               iCoff = 0x40 - iCoff;
+
+                       if (qCoff > 15)
+                               qCoff = 15;
+                       else if (qCoff <= -16)
+                               qCoff = -16;
+
+                       ath_dbg(common, CALIBRATE,
+                               "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
+                               i, iCoff, qCoff);
+
+                       REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+                                     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
+                                     iCoff);
+                       REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+                                     AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
+                                     qCoff);
+                       ath_dbg(common, CALIBRATE,
+                               "IQ Cal and Correction done for Chain %d\n",
+                               i);
+               }
+       }
+
+       REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+                   AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+}
+
+static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
+       u32 qGainMismatch, iGainMismatch, val, i;
+
+       for (i = 0; i < numChains; i++) {
+               iOddMeasOffset = ah->totalAdcIOddPhase[i];
+               iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
+               qOddMeasOffset = ah->totalAdcQOddPhase[i];
+               qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
+
+               ath_dbg(common, CALIBRATE,
+                       "Starting ADC Gain Cal for Chain %d\n", i);
+
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = 0x%08x\n",
+                       i, iOddMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = 0x%08x\n",
+                       i, iEvenMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = 0x%08x\n",
+                       i, qOddMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = 0x%08x\n",
+                       i, qEvenMeasOffset);
+
+               if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
+                       iGainMismatch =
+                               ((iEvenMeasOffset * 32) /
+                                iOddMeasOffset) & 0x3f;
+                       qGainMismatch =
+                               ((qOddMeasOffset * 32) /
+                                qEvenMeasOffset) & 0x3f;
+
+                       ath_dbg(common, CALIBRATE,
+                               "Chn %d gain_mismatch_i = 0x%08x\n",
+                               i, iGainMismatch);
+                       ath_dbg(common, CALIBRATE,
+                               "Chn %d gain_mismatch_q = 0x%08x\n",
+                               i, qGainMismatch);
+
+                       val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+                       val &= 0xfffff000;
+                       val |= (qGainMismatch) | (iGainMismatch << 6);
+                       REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+                       ath_dbg(common, CALIBRATE,
+                               "ADC Gain Cal done for Chain %d\n", i);
+               }
+       }
+
+       REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+                 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+                 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
+}
+
+static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 iOddMeasOffset, iEvenMeasOffset, val, i;
+       int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
+       const struct ath9k_percal_data *calData =
+               ah->cal_list_curr->calData;
+       u32 numSamples =
+               (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
+
+       for (i = 0; i < numChains; i++) {
+               iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
+               iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
+               qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
+               qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
+
+               ath_dbg(common, CALIBRATE,
+                       "Starting ADC DC Offset Cal for Chain %d\n", i);
+
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = %d\n",
+                       i, iOddMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = %d\n",
+                       i, iEvenMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = %d\n",
+                       i, qOddMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = %d\n",
+                       i, qEvenMeasOffset);
+
+               iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
+                              numSamples) & 0x1ff;
+               qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
+                              numSamples) & 0x1ff;
+
+               ath_dbg(common, CALIBRATE,
+                       "Chn %d dc_offset_mismatch_i = 0x%08x\n",
+                       i, iDcMismatch);
+               ath_dbg(common, CALIBRATE,
+                       "Chn %d dc_offset_mismatch_q = 0x%08x\n",
+                       i, qDcMismatch);
+
+               val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+               val &= 0xc0000fff;
+               val |= (qDcMismatch << 12) | (iDcMismatch << 21);
+               REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+               ath_dbg(common, CALIBRATE,
+                       "ADC DC Offset Cal done for Chain %d\n", i);
+       }
+
+       REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+                 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+                 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
+}
+
+static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
+{
+       u32 rddata;
+       int32_t delta, currPDADC, slope;
+
+       rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
+       currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
+
+       if (ah->initPDADC == 0 || currPDADC == 0) {
+               /*
+                * Zero value indicates that no frames have been transmitted
+                * yet, can't do temperature compensation until frames are
+                * transmitted.
+                */
+               return;
+       } else {
+               slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
+
+               if (slope == 0) { /* to avoid divide by zero case */
+                       delta = 0;
+               } else {
+                       delta = ((currPDADC - ah->initPDADC)*4) / slope;
+               }
+               REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
+                             AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
+               REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
+                             AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
+       }
+}
+
+static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
+{
+       u32 rddata, i;
+       int delta, currPDADC, regval;
+
+       rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
+       currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
+
+       if (ah->initPDADC == 0 || currPDADC == 0)
+               return;
+
+       if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
+               delta = (currPDADC - ah->initPDADC + 4) / 8;
+       else
+               delta = (currPDADC - ah->initPDADC + 5) / 10;
+
+       if (delta != ah->PDADCdelta) {
+               ah->PDADCdelta = delta;
+               for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
+                       regval = ah->originalGain[i] - delta;
+                       if (regval < 0)
+                               regval = 0;
+
+                       REG_RMW_FIELD(ah,
+                                     AR_PHY_TX_GAIN_TBL1 + i * 4,
+                                     AR_PHY_TX_GAIN, regval);
+               }
+       }
+}
+
+static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
+{
+       u32 regVal;
+       unsigned int i;
+       u32 regList[][2] = {
+               { 0x786c, 0 },
+               { 0x7854, 0 },
+               { 0x7820, 0 },
+               { 0x7824, 0 },
+               { 0x7868, 0 },
+               { 0x783c, 0 },
+               { 0x7838, 0 } ,
+               { 0x7828, 0 } ,
+       };
+
+       for (i = 0; i < ARRAY_SIZE(regList); i++)
+               regList[i][1] = REG_READ(ah, regList[i][0]);
+
+       regVal = REG_READ(ah, 0x7834);
+       regVal &= (~(0x1));
+       REG_WRITE(ah, 0x7834, regVal);
+       regVal = REG_READ(ah, 0x9808);
+       regVal |= (0x1 << 27);
+       REG_WRITE(ah, 0x9808, regVal);
+
+       /* 786c,b23,1, pwddac=1 */
+       REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
+       /* 7854, b5,1, pdrxtxbb=1 */
+       REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
+       /* 7854, b7,1, pdv2i=1 */
+       REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
+       /* 7854, b8,1, pddacinterface=1 */
+       REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
+       /* 7824,b12,0, offcal=0 */
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
+       /* 7838, b1,0, pwddb=0 */
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
+       /* 7820,b11,0, enpacal=0 */
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
+       /* 7820,b25,1, pdpadrv1=0 */
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
+       /* 7820,b24,0, pdpadrv2=0 */
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
+       /* 7820,b23,0, pdpaout=0 */
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
+       /* 783c,b14-16,7, padrvgn2tab_0=7 */
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
+       /*
+        * 7838,b29-31,0, padrvgn1tab_0=0
+        * does not matter since we turn it off
+        */
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
+
+       /* Set:
+        * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
+        * txon=1,paon=1,oscon=1,synthon_force=1
+        */
+       REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
+       udelay(30);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
+
+       /* find off_6_1; */
+       for (i = 6; i > 0; i--) {
+               regVal = REG_READ(ah, 0x7834);
+               regVal |= (1 << (20 + i));
+               REG_WRITE(ah, 0x7834, regVal);
+               udelay(1);
+               /* regVal = REG_READ(ah, 0x7834); */
+               regVal &= (~(0x1 << (20 + i)));
+               regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
+                           << (20 + i));
+               REG_WRITE(ah, 0x7834, regVal);
+       }
+
+       regVal = (regVal >> 20) & 0x7f;
+
+       /* Update PA cal info */
+       if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
+               if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
+                       ah->pacal_info.max_skipcount =
+                               2 * ah->pacal_info.max_skipcount;
+               ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
+       } else {
+               ah->pacal_info.max_skipcount = 1;
+               ah->pacal_info.skipcount = 0;
+               ah->pacal_info.prev_offset = regVal;
+       }
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       regVal = REG_READ(ah, 0x7834);
+       regVal |= 0x1;
+       REG_WRITE(ah, 0x7834, regVal);
+       regVal = REG_READ(ah, 0x9808);
+       regVal &= (~(0x1 << 27));
+       REG_WRITE(ah, 0x9808, regVal);
+
+       for (i = 0; i < ARRAY_SIZE(regList); i++)
+               REG_WRITE(ah, regList[i][0], regList[i][1]);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 regVal;
+       int i, offset, offs_6_1, offs_0;
+       u32 ccomp_org, reg_field;
+       u32 regList[][2] = {
+               { 0x786c, 0 },
+               { 0x7854, 0 },
+               { 0x7820, 0 },
+               { 0x7824, 0 },
+               { 0x7868, 0 },
+               { 0x783c, 0 },
+               { 0x7838, 0 },
+       };
+
+       ath_dbg(common, CALIBRATE, "Running PA Calibration\n");
+
+       /* PA CAL is not needed for high power solution */
+       if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
+           AR5416_EEP_TXGAIN_HIGH_POWER)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(regList); i++)
+               regList[i][1] = REG_READ(ah, regList[i][0]);
+
+       regVal = REG_READ(ah, 0x7834);
+       regVal &= (~(0x1));
+       REG_WRITE(ah, 0x7834, regVal);
+       regVal = REG_READ(ah, 0x9808);
+       regVal |= (0x1 << 27);
+       REG_WRITE(ah, 0x9808, regVal);
+
+       REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
+       REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
+       REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
+       REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+       ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
+
+       REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
+       udelay(30);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
+
+       for (i = 6; i > 0; i--) {
+               regVal = REG_READ(ah, 0x7834);
+               regVal |= (1 << (19 + i));
+               REG_WRITE(ah, 0x7834, regVal);
+               udelay(1);
+               regVal = REG_READ(ah, 0x7834);
+               regVal &= (~(0x1 << (19 + i)));
+               reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
+               regVal |= (reg_field << (19 + i));
+               REG_WRITE(ah, 0x7834, regVal);
+       }
+
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
+       udelay(1);
+       reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
+       offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
+       offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
+
+       offset = (offs_6_1<<1) | offs_0;
+       offset = offset - 0;
+       offs_6_1 = offset>>1;
+       offs_0 = offset & 1;
+
+       if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
+               if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
+                       ah->pacal_info.max_skipcount =
+                               2 * ah->pacal_info.max_skipcount;
+               ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
+       } else {
+               ah->pacal_info.max_skipcount = 1;
+               ah->pacal_info.skipcount = 0;
+               ah->pacal_info.prev_offset = offset;
+       }
+
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
+
+       regVal = REG_READ(ah, 0x7834);
+       regVal |= 0x1;
+       REG_WRITE(ah, 0x7834, regVal);
+       regVal = REG_READ(ah, 0x9808);
+       regVal &= (~(0x1 << 27));
+       REG_WRITE(ah, 0x9808, regVal);
+
+       for (i = 0; i < ARRAY_SIZE(regList); i++)
+               REG_WRITE(ah, regList[i][0], regList[i][1]);
+
+       REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
+}
+
+static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
+{
+       if (AR_SREV_9271(ah)) {
+               if (is_reset || !ah->pacal_info.skipcount)
+                       ar9271_hw_pa_cal(ah, is_reset);
+               else
+                       ah->pacal_info.skipcount--;
+       } else if (AR_SREV_9285_12_OR_LATER(ah)) {
+               if (is_reset || !ah->pacal_info.skipcount)
+                       ar9285_hw_pa_cal(ah, is_reset);
+               else
+                       ah->pacal_info.skipcount--;
+       }
+}
+
+static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
+{
+       if (OLC_FOR_AR9287_10_LATER)
+               ar9287_hw_olc_temp_compensation(ah);
+       else if (OLC_FOR_AR9280_20_LATER)
+               ar9280_hw_olc_temp_compensation(ah);
+}
+
+static bool ar9002_hw_calibrate(struct ath_hw *ah,
+                               struct ath9k_channel *chan,
+                               u8 rxchainmask,
+                               bool longcal)
+{
+       bool iscaldone = true;
+       struct ath9k_cal_list *currCal = ah->cal_list_curr;
+       bool nfcal, nfcal_pending = false;
+
+       nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
+       if (ah->caldata)
+               nfcal_pending = ah->caldata->nfcal_pending;
+
+       if (currCal && !nfcal &&
+           (currCal->calState == CAL_RUNNING ||
+            currCal->calState == CAL_WAITING)) {
+               iscaldone = ar9002_hw_per_calibration(ah, chan,
+                                                     rxchainmask, currCal);
+               if (iscaldone) {
+                       ah->cal_list_curr = currCal = currCal->calNext;
+
+                       if (currCal->calState == CAL_WAITING) {
+                               iscaldone = false;
+                               ath9k_hw_reset_calibration(ah, currCal);
+                       }
+               }
+       }
+
+       /* Do NF cal only at longer intervals */
+       if (longcal || nfcal_pending) {
+               /*
+                * Get the value from the previous NF cal and update
+                * history buffer.
+                */
+               if (ath9k_btcoex_ath9k_hw_getnf(ah, chan)) {
+                       /*
+                        * Load the NF from history buffer of the current
+                        * channel.
+                        * NF is slow time-variant, so it is OK to use a
+                        * historical value.
+                        */
+                       ath9k_hw_loadnf(ah, ah->curchan);
+               }
+
+               if (longcal) {
+                       ath9k_hw_start_nfcal(ah, false);
+                       /* Do periodic PAOffset Cal */
+                       ar9002_hw_pa_cal(ah, false);
+                       ar9002_hw_olc_temp_compensation(ah);
+               }
+       }
+
+       return iscaldone;
+}
+
+/* Carrier leakage Calibration fix */
+static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+       if (IS_CHAN_HT20(chan)) {
+               REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
+               REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
+               REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+                           AR_PHY_AGC_CONTROL_FLTR_CAL);
+               REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
+               REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+               if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+                                 AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
+                       ath_dbg(common, CALIBRATE,
+                               "offset calibration failed to complete in 1ms; noisy environment?\n");
+                       return false;
+               }
+               REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
+               REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
+               REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+       }
+       REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+       REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+       REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
+       REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+       if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
+                         0, AH_WAIT_TIMEOUT)) {
+               ath_dbg(common, CALIBRATE,
+                       "offset calibration failed to complete in 1ms; noisy environment?\n");
+               return false;
+       }
+
+       REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+       REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+       REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+
+       return true;
+}
+
+static bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       int i;
+       u_int32_t txgain_max;
+       u_int32_t clc_gain, gain_mask = 0, clc_num = 0;
+       u_int32_t reg_clc_I0, reg_clc_Q0;
+       u_int32_t i0_num = 0;
+       u_int32_t q0_num = 0;
+       u_int32_t total_num = 0;
+       u_int32_t reg_rf2g5_org;
+       bool retv = true;
+
+       if (!(ar9285_hw_cl_cal(ah, chan)))
+               return false;
+
+       txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
+                       AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
+
+       for (i = 0; i < (txgain_max+1); i++) {
+               clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
+                          AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
+               if (!(gain_mask & (1 << clc_gain))) {
+                       gain_mask |= (1 << clc_gain);
+                       clc_num++;
+               }
+       }
+
+       for (i = 0; i < clc_num; i++) {
+               reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
+                             & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
+               reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
+                             & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
+               if (reg_clc_I0 == 0)
+                       i0_num++;
+
+               if (reg_clc_Q0 == 0)
+                       q0_num++;
+       }
+       total_num = i0_num + q0_num;
+       if (total_num > AR9285_CLCAL_REDO_THRESH) {
+               reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
+               if (AR_SREV_9285E_20(ah)) {
+                       REG_WRITE(ah, AR9285_RF2G5,
+                                 (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
+                                 AR9285_RF2G5_IC50TX_XE_SET);
+               } else {
+                       REG_WRITE(ah, AR9285_RF2G5,
+                                 (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
+                                 AR9285_RF2G5_IC50TX_SET);
+               }
+               retv = ar9285_hw_cl_cal(ah, chan);
+               REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
+       }
+       return retv;
+}
+
+static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (AR_SREV_9271(ah)) {
+               if (!ar9285_hw_cl_cal(ah, chan))
+                       return false;
+       } else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
+               if (!ar9285_hw_clc(ah, chan))
+                       return false;
+       } else {
+               if (AR_SREV_9280_20_OR_LATER(ah)) {
+                       if (!AR_SREV_9287_11_OR_LATER(ah))
+                               REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
+                                           AR_PHY_ADC_CTL_OFF_PWDADC);
+                       REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+                                   AR_PHY_AGC_CONTROL_FLTR_CAL);
+               }
+
+               /* Calibrate the AGC */
+               REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+                         REG_READ(ah, AR_PHY_AGC_CONTROL) |
+                         AR_PHY_AGC_CONTROL_CAL);
+
+               /* Poll for offset calibration complete */
+               if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+                                  AR_PHY_AGC_CONTROL_CAL,
+                                  0, AH_WAIT_TIMEOUT)) {
+                       ath_dbg(common, CALIBRATE,
+                               "offset calibration failed to complete in 1ms; noisy environment?\n");
+                       return false;
+               }
+
+               if (AR_SREV_9280_20_OR_LATER(ah)) {
+                       if (!AR_SREV_9287_11_OR_LATER(ah))
+                               REG_SET_BIT(ah, AR_PHY_ADC_CTL,
+                                           AR_PHY_ADC_CTL_OFF_PWDADC);
+                       REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+                                   AR_PHY_AGC_CONTROL_FLTR_CAL);
+               }
+       }
+
+       /* Do PA Calibration */
+       ar9002_hw_pa_cal(ah, true);
+
+       if (ah->caldata)
+               ah->caldata->nfcal_pending = true;
+
+       ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+
+       /* Enable IQ, ADC Gain and ADC DC offset CALs */
+       if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
+               ah->supp_cals = IQ_MISMATCH_CAL;
+
+               if (AR_SREV_9160_10_OR_LATER(ah))
+                       ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
+
+               if (AR_SREV_9287(ah))
+                       ah->supp_cals &= ~ADC_GAIN_CAL;
+
+               if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) {
+                       INIT_CAL(&ah->adcgain_caldata);
+                       INSERT_CAL(ah, &ah->adcgain_caldata);
+                       ath_dbg(common, CALIBRATE,
+                                       "enabling ADC Gain Calibration\n");
+               }
+
+               if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) {
+                       INIT_CAL(&ah->adcdc_caldata);
+                       INSERT_CAL(ah, &ah->adcdc_caldata);
+                       ath_dbg(common, CALIBRATE,
+                                       "enabling ADC DC Calibration\n");
+               }
+
+               if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) {
+                       INIT_CAL(&ah->iq_caldata);
+                       INSERT_CAL(ah, &ah->iq_caldata);
+                       ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
+               }
+
+               ah->cal_list_curr = ah->cal_list;
+
+               if (ah->cal_list_curr)
+                       ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
+       }
+
+       if (ah->caldata)
+               ah->caldata->CalValid = 0;
+
+       return true;
+}
+
+static const struct ath9k_percal_data iq_cal_multi_sample = {
+       IQ_MISMATCH_CAL,
+       MAX_CAL_SAMPLES,
+       PER_MIN_LOG_COUNT,
+       ar9002_hw_iqcal_collect,
+       ar9002_hw_iqcalibrate
+};
+static const struct ath9k_percal_data iq_cal_single_sample = {
+       IQ_MISMATCH_CAL,
+       MIN_CAL_SAMPLES,
+       PER_MAX_LOG_COUNT,
+       ar9002_hw_iqcal_collect,
+       ar9002_hw_iqcalibrate
+};
+static const struct ath9k_percal_data adc_gain_cal_multi_sample = {
+       ADC_GAIN_CAL,
+       MAX_CAL_SAMPLES,
+       PER_MIN_LOG_COUNT,
+       ar9002_hw_adc_gaincal_collect,
+       ar9002_hw_adc_gaincal_calibrate
+};
+static const struct ath9k_percal_data adc_gain_cal_single_sample = {
+       ADC_GAIN_CAL,
+       MIN_CAL_SAMPLES,
+       PER_MAX_LOG_COUNT,
+       ar9002_hw_adc_gaincal_collect,
+       ar9002_hw_adc_gaincal_calibrate
+};
+static const struct ath9k_percal_data adc_dc_cal_multi_sample = {
+       ADC_DC_CAL,
+       MAX_CAL_SAMPLES,
+       PER_MIN_LOG_COUNT,
+       ar9002_hw_adc_dccal_collect,
+       ar9002_hw_adc_dccal_calibrate
+};
+static const struct ath9k_percal_data adc_dc_cal_single_sample = {
+       ADC_DC_CAL,
+       MIN_CAL_SAMPLES,
+       PER_MAX_LOG_COUNT,
+       ar9002_hw_adc_dccal_collect,
+       ar9002_hw_adc_dccal_calibrate
+};
+
+static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
+{
+       if (AR_SREV_9100(ah)) {
+               ah->iq_caldata.calData = &iq_cal_multi_sample;
+               ah->supp_cals = IQ_MISMATCH_CAL;
+               return;
+       }
+
+       if (AR_SREV_9160_10_OR_LATER(ah)) {
+               if (AR_SREV_9280_20_OR_LATER(ah)) {
+                       ah->iq_caldata.calData = &iq_cal_single_sample;
+                       ah->adcgain_caldata.calData =
+                               &adc_gain_cal_single_sample;
+                       ah->adcdc_caldata.calData =
+                               &adc_dc_cal_single_sample;
+               } else {
+                       ah->iq_caldata.calData = &iq_cal_multi_sample;
+                       ah->adcgain_caldata.calData =
+                               &adc_gain_cal_multi_sample;
+                       ah->adcdc_caldata.calData =
+                               &adc_dc_cal_multi_sample;
+               }
+               ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
+
+               if (AR_SREV_9287(ah))
+                       ah->supp_cals &= ~ADC_GAIN_CAL;
+       }
+}
+
+void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
+{
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+       struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+       priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
+       priv_ops->init_cal = ar9002_hw_init_cal;
+       priv_ops->setup_calibration = ar9002_hw_setup_calibration;
+
+       ops->calibrate = ar9002_hw_calibrate;
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9002_hw.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9002_hw.c
new file mode 100644 (file)
index 0000000..edf21ea
--- /dev/null
@@ -0,0 +1,526 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/moduleparam.h>
+#include "hw.h"
+#include "ar5008_initvals.h"
+#include "ar9001_initvals.h"
+#include "ar9002_initvals.h"
+#include "ar9002_phy.h"
+
+/* General hardware code for the A5008/AR9001/AR9002 hadware families */
+
+static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
+{
+       if (AR_SREV_9271(ah)) {
+               INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
+                              ARRAY_SIZE(ar9271Modes_9271), 5);
+               INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
+                              ARRAY_SIZE(ar9271Common_9271), 2);
+               INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
+                              ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5);
+               return;
+       }
+
+       if (ah->config.pcie_clock_req)
+               INIT_INI_ARRAY(&ah->iniPcieSerdes,
+                          ar9280PciePhy_clkreq_off_L1_9280,
+                          ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280), 2);
+       else
+               INIT_INI_ARRAY(&ah->iniPcieSerdes,
+                          ar9280PciePhy_clkreq_always_on_L1_9280,
+                          ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
+
+       if (AR_SREV_9287_11_OR_LATER(ah)) {
+               INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
+                               ARRAY_SIZE(ar9287Modes_9287_1_1), 5);
+               INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
+                               ARRAY_SIZE(ar9287Common_9287_1_1), 2);
+       } else if (AR_SREV_9285_12_OR_LATER(ah)) {
+               INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
+                              ARRAY_SIZE(ar9285Modes_9285_1_2), 5);
+               INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
+                              ARRAY_SIZE(ar9285Common_9285_1_2), 2);
+       } else if (AR_SREV_9280_20_OR_LATER(ah)) {
+               INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
+                              ARRAY_SIZE(ar9280Modes_9280_2), 5);
+               INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
+                              ARRAY_SIZE(ar9280Common_9280_2), 2);
+
+               INIT_INI_ARRAY(&ah->iniModesFastClock,
+                              ar9280Modes_fast_clock_9280_2,
+                              ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
+       } else if (AR_SREV_9160_10_OR_LATER(ah)) {
+               INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
+                              ARRAY_SIZE(ar5416Modes_9160), 5);
+               INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
+                              ARRAY_SIZE(ar5416Common_9160), 2);
+               if (AR_SREV_9160_11(ah)) {
+                       INIT_INI_ARRAY(&ah->iniAddac,
+                                      ar5416Addac_9160_1_1,
+                                      ARRAY_SIZE(ar5416Addac_9160_1_1), 2);
+               } else {
+                       INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
+                                      ARRAY_SIZE(ar5416Addac_9160), 2);
+               }
+       } else if (AR_SREV_9100_OR_LATER(ah)) {
+               INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
+                              ARRAY_SIZE(ar5416Modes_9100), 5);
+               INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
+                              ARRAY_SIZE(ar5416Common_9100), 2);
+               INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
+                              ARRAY_SIZE(ar5416Bank6_9100), 3);
+               INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
+                              ARRAY_SIZE(ar5416Addac_9100), 2);
+       } else {
+               INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
+                              ARRAY_SIZE(ar5416Modes), 5);
+               INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
+                              ARRAY_SIZE(ar5416Common), 2);
+               INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
+                              ARRAY_SIZE(ar5416Bank6TPC), 3);
+               INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
+                              ARRAY_SIZE(ar5416Addac), 2);
+       }
+
+       if (!AR_SREV_9280_20_OR_LATER(ah)) {
+               /* Common for AR5416, AR913x, AR9160 */
+               INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
+                              ARRAY_SIZE(ar5416BB_RfGain), 3);
+
+               INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
+                              ARRAY_SIZE(ar5416Bank0), 2);
+               INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
+                              ARRAY_SIZE(ar5416Bank1), 2);
+               INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
+                              ARRAY_SIZE(ar5416Bank2), 2);
+               INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
+                              ARRAY_SIZE(ar5416Bank3), 3);
+               INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
+                              ARRAY_SIZE(ar5416Bank7), 2);
+
+               /* Common for AR5416, AR9160 */
+               if (!AR_SREV_9100(ah))
+                       INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
+                                      ARRAY_SIZE(ar5416Bank6), 3);
+
+               /* Common for AR913x, AR9160 */
+               if (!AR_SREV_5416(ah))
+                       INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
+                                      ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
+       }
+
+       /* iniAddac needs to be modified for these chips */
+       if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) {
+               struct ar5416IniArray *addac = &ah->iniAddac;
+               u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns;
+               u32 *data;
+
+               data = kmalloc(size, GFP_KERNEL);
+               if (!data)
+                       return;
+
+               memcpy(data, addac->ia_array, size);
+               addac->ia_array = data;
+
+               if (!AR_SREV_5416_22_OR_LATER(ah)) {
+                       /* override CLKDRV value */
+                       INI_RA(addac, 31,1) = 0;
+               }
+       }
+       if (AR_SREV_9287_11_OR_LATER(ah)) {
+               INIT_INI_ARRAY(&ah->iniCckfirNormal,
+                      ar9287Common_normal_cck_fir_coeff_9287_1_1,
+                      ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_9287_1_1),
+                      2);
+               INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+                      ar9287Common_japan_2484_cck_fir_coeff_9287_1_1,
+                      ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_9287_1_1),
+                      2);
+       }
+}
+
+static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
+{
+       u32 rxgain_type;
+
+       if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
+           AR5416_EEP_MINOR_VER_17) {
+               rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
+
+               if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
+                       INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9280Modes_backoff_13db_rxgain_9280_2,
+                       ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 5);
+               else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
+                       INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9280Modes_backoff_23db_rxgain_9280_2,
+                       ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 5);
+               else
+                       INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9280Modes_original_rxgain_9280_2,
+                       ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
+       } else {
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9280Modes_original_rxgain_9280_2,
+                       ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
+       }
+}
+
+static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
+{
+       if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
+           AR5416_EEP_MINOR_VER_19) {
+               if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9280Modes_high_power_tx_gain_9280_2,
+                       ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 5);
+               else
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9280Modes_original_tx_gain_9280_2,
+                       ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
+       } else {
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+               ar9280Modes_original_tx_gain_9280_2,
+               ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
+       }
+}
+
+static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
+{
+       if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                              ar9271Modes_high_power_tx_gain_9271,
+                              ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
+       else
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                              ar9271Modes_normal_power_tx_gain_9271,
+                              ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
+}
+
+static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
+{
+       u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
+
+       if (AR_SREV_9287_11_OR_LATER(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+               ar9287Modes_rx_gain_9287_1_1,
+               ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 5);
+       else if (AR_SREV_9280_20(ah))
+               ar9280_20_hw_init_rxgain_ini(ah);
+
+       if (AR_SREV_9271(ah)) {
+               ar9271_hw_init_txgain_ini(ah, txgain_type);
+       } else if (AR_SREV_9287_11_OR_LATER(ah)) {
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+               ar9287Modes_tx_gain_9287_1_1,
+               ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5);
+       } else if (AR_SREV_9280_20(ah)) {
+               ar9280_20_hw_init_txgain_ini(ah, txgain_type);
+       } else if (AR_SREV_9285_12_OR_LATER(ah)) {
+               /* txgain table */
+               if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
+                       if (AR_SREV_9285E_20(ah)) {
+                               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9285Modes_XE2_0_high_power,
+                               ARRAY_SIZE(
+                                 ar9285Modes_XE2_0_high_power), 5);
+                       } else {
+                               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9285Modes_high_power_tx_gain_9285_1_2,
+                               ARRAY_SIZE(
+                                 ar9285Modes_high_power_tx_gain_9285_1_2), 5);
+                       }
+               } else {
+                       if (AR_SREV_9285E_20(ah)) {
+                               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9285Modes_XE2_0_normal_power,
+                               ARRAY_SIZE(
+                                 ar9285Modes_XE2_0_normal_power), 5);
+                       } else {
+                               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9285Modes_original_tx_gain_9285_1_2,
+                               ARRAY_SIZE(
+                                 ar9285Modes_original_tx_gain_9285_1_2), 5);
+                       }
+               }
+       }
+}
+
+/*
+ * Helper for ASPM support.
+ *
+ * Disable PLL when in L0s as well as receiver clock when in L1.
+ * This power saving option must be enabled through the SerDes.
+ *
+ * Programming the SerDes must go through the same 288 bit serial shift
+ * register as the other analog registers.  Hence the 9 writes.
+ */
+static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
+                                        bool power_off)
+{
+       u8 i;
+       u32 val;
+
+       /* Nothing to do on restore for 11N */
+       if (!power_off /* !restore */) {
+               if (AR_SREV_9280_20_OR_LATER(ah)) {
+                       /*
+                        * AR9280 2.0 or later chips use SerDes values from the
+                        * initvals.h initialized depending on chipset during
+                        * __ath9k_hw_init()
+                        */
+                       for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
+                               REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
+                                         INI_RA(&ah->iniPcieSerdes, i, 1));
+                       }
+               } else {
+                       ENABLE_REGWRITE_BUFFER(ah);
+
+                       REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+                       REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+
+                       /* RX shut off when elecidle is asserted */
+                       REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
+                       REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
+                       REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
+
+                       /*
+                        * Ignore ah->ah_config.pcie_clock_req setting for
+                        * pre-AR9280 11n
+                        */
+                       REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
+
+                       REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+                       REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+                       REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
+
+                       /* Load the new settings */
+                       REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+
+                       REGWRITE_BUFFER_FLUSH(ah);
+               }
+
+               udelay(1000);
+       }
+
+       if (power_off) {
+               /* clear bit 19 to disable L1 */
+               REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+
+               val = REG_READ(ah, AR_WA);
+
+               /*
+                * Set PCIe workaround bits
+                * In AR9280 and AR9285, bit 14 in WA register (disable L1)
+                * should only  be set when device enters D3 and be
+                * cleared when device comes back to D0.
+                */
+               if (ah->config.pcie_waen) {
+                       if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
+                               val |= AR_WA_D3_L1_DISABLE;
+               } else {
+                       if (((AR_SREV_9285(ah) ||
+                             AR_SREV_9271(ah) ||
+                             AR_SREV_9287(ah)) &&
+                            (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
+                           (AR_SREV_9280(ah) &&
+                            (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
+                               val |= AR_WA_D3_L1_DISABLE;
+                       }
+               }
+
+               if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
+                       /*
+                        * Disable bit 6 and 7 before entering D3 to
+                        * prevent system hang.
+                        */
+                       val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
+               }
+
+               if (AR_SREV_9280(ah))
+                       val |= AR_WA_BIT22;
+
+               if (AR_SREV_9285E_20(ah))
+                       val |= AR_WA_BIT23;
+
+               REG_WRITE(ah, AR_WA, val);
+       } else {
+               if (ah->config.pcie_waen) {
+                       val = ah->config.pcie_waen;
+                       if (!power_off)
+                               val &= (~AR_WA_D3_L1_DISABLE);
+               } else {
+                       if (AR_SREV_9285(ah) ||
+                           AR_SREV_9271(ah) ||
+                           AR_SREV_9287(ah)) {
+                               val = AR9285_WA_DEFAULT;
+                               if (!power_off)
+                                       val &= (~AR_WA_D3_L1_DISABLE);
+                       }
+                       else if (AR_SREV_9280(ah)) {
+                               /*
+                                * For AR9280 chips, bit 22 of 0x4004
+                                * needs to be set.
+                                */
+                               val = AR9280_WA_DEFAULT;
+                               if (!power_off)
+                                       val &= (~AR_WA_D3_L1_DISABLE);
+                       } else {
+                               val = AR_WA_DEFAULT;
+                       }
+               }
+
+               /* WAR for ASPM system hang */
+               if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
+                       val |= (AR_WA_BIT6 | AR_WA_BIT7);
+
+               if (AR_SREV_9285E_20(ah))
+                       val |= AR_WA_BIT23;
+
+               REG_WRITE(ah, AR_WA, val);
+
+               /* set bit 19 to allow forcing of pcie core into L1 state */
+               REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+       }
+}
+
+static int ar9002_hw_get_radiorev(struct ath_hw *ah)
+{
+       u32 val;
+       int i;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
+       for (i = 0; i < 8; i++)
+               REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
+       val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
+
+       return ath9k_hw_reverse_bits(val, 8);
+}
+
+int ar9002_hw_rf_claim(struct ath_hw *ah)
+{
+       u32 val;
+
+       REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       val = ar9002_hw_get_radiorev(ah);
+       switch (val & AR_RADIO_SREV_MAJOR) {
+       case 0:
+               val = AR_RAD5133_SREV_MAJOR;
+               break;
+       case AR_RAD5133_SREV_MAJOR:
+       case AR_RAD5122_SREV_MAJOR:
+       case AR_RAD2133_SREV_MAJOR:
+       case AR_RAD2122_SREV_MAJOR:
+               break;
+       default:
+               ath_err(ath9k_hw_common(ah),
+                       "Radio Chip Rev 0x%02X not supported\n",
+                       val & AR_RADIO_SREV_MAJOR);
+               return -EOPNOTSUPP;
+       }
+
+       ah->hw_version.analog5GhzRev = val;
+
+       return 0;
+}
+
+void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
+{
+       if (AR_SREV_9287_13_OR_LATER(ah)) {
+               REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+                               AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
+               REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
+               REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+                               AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
+               REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+                               AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
+       }
+}
+
+/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
+void ar9002_hw_attach_ops(struct ath_hw *ah)
+{
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+       struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+       priv_ops->init_mode_regs = ar9002_hw_init_mode_regs;
+       priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
+
+       ops->config_pci_powersave = ar9002_hw_configpcipowersave;
+
+       ar5008_hw_attach_phy_ops(ah);
+       if (AR_SREV_9280_20_OR_LATER(ah))
+               ar9002_hw_attach_phy_ops(ah);
+
+       ar9002_hw_attach_calib_ops(ah);
+       ar9002_hw_attach_mac_ops(ah);
+}
+
+void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       u32 modesIndex;
+       int i;
+
+       switch (chan->chanmode) {
+       case CHANNEL_A:
+       case CHANNEL_A_HT20:
+               modesIndex = 1;
+               break;
+       case CHANNEL_A_HT40PLUS:
+       case CHANNEL_A_HT40MINUS:
+               modesIndex = 2;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_G_HT20:
+       case CHANNEL_B:
+               modesIndex = 4;
+               break;
+       case CHANNEL_G_HT40PLUS:
+       case CHANNEL_G_HT40MINUS:
+               modesIndex = 3;
+               break;
+
+       default:
+               return;
+       }
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
+               u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
+               u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
+               u32 val_orig;
+
+               if (reg == AR_PHY_CCK_DETECT) {
+                       val_orig = REG_READ(ah, reg);
+                       val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
+                       val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
+
+                       REG_WRITE(ah, reg, val|val_orig);
+               } else
+                       REG_WRITE(ah, reg, val);
+       }
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9002_initvals.h
new file mode 100644 (file)
index 0000000..4d18c66
--- /dev/null
@@ -0,0 +1,3180 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+static const u32 ar9280Modes_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+       {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+       {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+       {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b},
+       {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d},
+       {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010},
+       {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+       {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+       {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210},
+       {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c},
+       {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00},
+       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444},
+       {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019},
+       {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000},
+       {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000},
+       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
+       {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000},
+       {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000},
+};
+
+static const u32 ar9280Common_9280_2[][2] = {
+       /* Addr      allmodes  */
+       {0x0000000c, 0x00000000},
+       {0x00000030, 0x00020015},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000008},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00000054, 0x0000001f},
+       {0x00000800, 0x00000000},
+       {0x00000804, 0x00000000},
+       {0x00000808, 0x00000000},
+       {0x0000080c, 0x00000000},
+       {0x00000810, 0x00000000},
+       {0x00000814, 0x00000000},
+       {0x00000818, 0x00000000},
+       {0x0000081c, 0x00000000},
+       {0x00000820, 0x00000000},
+       {0x00000824, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x00001230, 0x00000000},
+       {0x00001270, 0x00000000},
+       {0x00001038, 0x00000000},
+       {0x00001078, 0x00000000},
+       {0x000010b8, 0x00000000},
+       {0x000010f8, 0x00000000},
+       {0x00001138, 0x00000000},
+       {0x00001178, 0x00000000},
+       {0x000011b8, 0x00000000},
+       {0x000011f8, 0x00000000},
+       {0x00001238, 0x00000000},
+       {0x00001278, 0x00000000},
+       {0x000012b8, 0x00000000},
+       {0x000012f8, 0x00000000},
+       {0x00001338, 0x00000000},
+       {0x00001378, 0x00000000},
+       {0x000013b8, 0x00000000},
+       {0x000013f8, 0x00000000},
+       {0x00001438, 0x00000000},
+       {0x00001478, 0x00000000},
+       {0x000014b8, 0x00000000},
+       {0x000014f8, 0x00000000},
+       {0x00001538, 0x00000000},
+       {0x00001578, 0x00000000},
+       {0x000015b8, 0x00000000},
+       {0x000015f8, 0x00000000},
+       {0x00001638, 0x00000000},
+       {0x00001678, 0x00000000},
+       {0x000016b8, 0x00000000},
+       {0x000016f8, 0x00000000},
+       {0x00001738, 0x00000000},
+       {0x00001778, 0x00000000},
+       {0x000017b8, 0x00000000},
+       {0x000017f8, 0x00000000},
+       {0x0000103c, 0x00000000},
+       {0x0000107c, 0x00000000},
+       {0x000010bc, 0x00000000},
+       {0x000010fc, 0x00000000},
+       {0x0000113c, 0x00000000},
+       {0x0000117c, 0x00000000},
+       {0x000011bc, 0x00000000},
+       {0x000011fc, 0x00000000},
+       {0x0000123c, 0x00000000},
+       {0x0000127c, 0x00000000},
+       {0x000012bc, 0x00000000},
+       {0x000012fc, 0x00000000},
+       {0x0000133c, 0x00000000},
+       {0x0000137c, 0x00000000},
+       {0x000013bc, 0x00000000},
+       {0x000013fc, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00004030, 0x00000002},
+       {0x0000403c, 0x00000002},
+       {0x00004024, 0x0000001f},
+       {0x00004060, 0x00000000},
+       {0x00004064, 0x00000000},
+       {0x00007010, 0x00000033},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000700},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008048, 0x40000000},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000000},
+       {0x000080c0, 0x2a80001a},
+       {0x000080c4, 0x05dc01e0},
+       {0x000080c8, 0x1f402710},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00001e00},
+       {0x000080d4, 0x00000000},
+       {0x000080d8, 0x00400000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x003f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080f8, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00020000},
+       {0x00008104, 0x00000001},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000168},
+       {0x00008118, 0x000100aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x00000000},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x32143320},
+       {0x00008174, 0xfaa4fa50},
+       {0x00008178, 0x00000100},
+       {0x0000817c, 0x00000000},
+       {0x000081c0, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008200, 0x00000000},
+       {0x00008204, 0x00000000},
+       {0x00008208, 0x00000000},
+       {0x0000820c, 0x00000000},
+       {0x00008210, 0x00000000},
+       {0x00008214, 0x00000000},
+       {0x00008218, 0x00000000},
+       {0x0000821c, 0x00000000},
+       {0x00008220, 0x00000000},
+       {0x00008224, 0x00000000},
+       {0x00008228, 0x00000000},
+       {0x0000822c, 0x00000000},
+       {0x00008230, 0x00000000},
+       {0x00008234, 0x00000000},
+       {0x00008238, 0x00000000},
+       {0x0000823c, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000100},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x400000ff},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x88a00010},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000000},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x00000000},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000040},
+       {0x00008314, 0x00000000},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000e00},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x00000000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0x00481043},
+       {0x00009808, 0x00000000},
+       {0x0000980c, 0xafa68e30},
+       {0x00009810, 0xfd14e000},
+       {0x00009814, 0x9c0a9f6b},
+       {0x0000981c, 0x00000000},
+       {0x0000982c, 0x0000a000},
+       {0x00009830, 0x00000000},
+       {0x0000983c, 0x00200400},
+       {0x0000984c, 0x0040233c},
+       {0x0000a84c, 0x0040233c},
+       {0x00009854, 0x00000044},
+       {0x00009900, 0x00000000},
+       {0x00009904, 0x00000000},
+       {0x00009908, 0x00000000},
+       {0x0000990c, 0x00000000},
+       {0x00009910, 0x01002310},
+       {0x0000991c, 0x10000fff},
+       {0x00009920, 0x04900000},
+       {0x0000a920, 0x04900000},
+       {0x00009928, 0x00000001},
+       {0x0000992c, 0x00000004},
+       {0x00009934, 0x1e1f2022},
+       {0x00009938, 0x0a0b0c0d},
+       {0x0000993c, 0x00000000},
+       {0x00009948, 0x9280c00a},
+       {0x0000994c, 0x00020028},
+       {0x00009954, 0x5f3ca3de},
+       {0x00009958, 0x2108ecff},
+       {0x00009940, 0x14750604},
+       {0x0000c95c, 0x004b6a8e},
+       {0x00009970, 0x190fb514},
+       {0x00009974, 0x00000000},
+       {0x00009978, 0x00000001},
+       {0x0000997c, 0x00000000},
+       {0x00009980, 0x00000000},
+       {0x00009984, 0x00000000},
+       {0x00009988, 0x00000000},
+       {0x0000998c, 0x00000000},
+       {0x00009990, 0x00000000},
+       {0x00009994, 0x00000000},
+       {0x00009998, 0x00000000},
+       {0x0000999c, 0x00000000},
+       {0x000099a0, 0x00000000},
+       {0x000099a4, 0x00000001},
+       {0x000099a8, 0x201fff00},
+       {0x000099ac, 0x006f0000},
+       {0x000099b0, 0x03051000},
+       {0x000099b4, 0x00000820},
+       {0x000099c4, 0x06336f77},
+       {0x000099c8, 0x6af6532f},
+       {0x000099cc, 0x08f186c8},
+       {0x000099d0, 0x00046384},
+       {0x000099d4, 0x00000000},
+       {0x000099d8, 0x00000000},
+       {0x000099dc, 0x00000000},
+       {0x000099e0, 0x00000000},
+       {0x000099e4, 0xaaaaaaaa},
+       {0x000099e8, 0x3c466478},
+       {0x000099ec, 0x0cc80caa},
+       {0x000099f0, 0x00000000},
+       {0x000099fc, 0x00001042},
+       {0x0000a208, 0x803e4788},
+       {0x0000a210, 0x4080a333},
+       {0x0000a214, 0x40206c10},
+       {0x0000a218, 0x009c4060},
+       {0x0000a220, 0x01834061},
+       {0x0000a224, 0x00000400},
+       {0x0000a228, 0x000003b5},
+       {0x0000a22c, 0x233f7180},
+       {0x0000a234, 0x20202020},
+       {0x0000a238, 0x20202020},
+       {0x0000a240, 0x38490a20},
+       {0x0000a244, 0x00007bb6},
+       {0x0000a248, 0x0fff3ffc},
+       {0x0000a24c, 0x00000000},
+       {0x0000a254, 0x00000000},
+       {0x0000a258, 0x0cdbd380},
+       {0x0000a25c, 0x0f0f0f01},
+       {0x0000a260, 0xdfa91f01},
+       {0x0000a268, 0x00000000},
+       {0x0000a26c, 0x0e79e5c6},
+       {0x0000b26c, 0x0e79e5c6},
+       {0x0000d270, 0x00820820},
+       {0x0000a278, 0x1ce739ce},
+       {0x0000d35c, 0x07ffffef},
+       {0x0000d360, 0x0fffffe7},
+       {0x0000d364, 0x17ffffe5},
+       {0x0000d368, 0x1fffffe4},
+       {0x0000d36c, 0x37ffffe3},
+       {0x0000d370, 0x3fffffe3},
+       {0x0000d374, 0x57ffffe3},
+       {0x0000d378, 0x5fffffe2},
+       {0x0000d37c, 0x7fffffe2},
+       {0x0000d380, 0x7f3c7bba},
+       {0x0000d384, 0xf3307ff0},
+       {0x0000a38c, 0x20202020},
+       {0x0000a390, 0x20202020},
+       {0x0000a394, 0x1ce739ce},
+       {0x0000a398, 0x000001ce},
+       {0x0000a39c, 0x00000001},
+       {0x0000a3a0, 0x00000000},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0x00000000},
+       {0x0000a3ac, 0x00000000},
+       {0x0000a3b0, 0x00000000},
+       {0x0000a3b4, 0x00000000},
+       {0x0000a3b8, 0x00000000},
+       {0x0000a3bc, 0x00000000},
+       {0x0000a3c0, 0x00000000},
+       {0x0000a3c4, 0x00000000},
+       {0x0000a3c8, 0x00000246},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3dc, 0x1ce739ce},
+       {0x0000a3e0, 0x000001ce},
+       {0x0000a3e4, 0x00000000},
+       {0x0000a3e8, 0x18c43433},
+       {0x00007800, 0x00040000},
+       {0x00007804, 0xdb005012},
+       {0x00007808, 0x04924914},
+       {0x0000780c, 0x21084210},
+       {0x00007810, 0x6d801300},
+       {0x00007818, 0x07e41000},
+       {0x00007824, 0x00040000},
+       {0x00007828, 0xdb005012},
+       {0x0000782c, 0x04924914},
+       {0x00007830, 0x21084210},
+       {0x00007834, 0x6d801300},
+       {0x0000783c, 0x07e40000},
+       {0x00007848, 0x00100000},
+       {0x0000784c, 0x773f0567},
+       {0x00007850, 0x54214514},
+       {0x00007854, 0x12035828},
+       {0x00007858, 0x9259269a},
+       {0x00007860, 0x52802000},
+       {0x00007864, 0x0a8e370e},
+       {0x00007868, 0xc0102850},
+       {0x0000786c, 0x812d4000},
+       {0x00007870, 0x807ec400},
+       {0x00007874, 0x001b6db0},
+       {0x00007878, 0x00376b63},
+       {0x0000787c, 0x06db6db6},
+       {0x00007880, 0x006d8000},
+       {0x00007884, 0xffeffffe},
+       {0x00007888, 0xffeffffe},
+       {0x0000788c, 0x00010000},
+       {0x00007890, 0x02060aeb},
+       {0x00007898, 0x2a850160},
+};
+
+static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x00001030, 0x00000268, 0x000004d0},
+       {0x00001070, 0x0000018c, 0x00000318},
+       {0x000010b0, 0x00000fd0, 0x00001fa0},
+       {0x00008014, 0x044c044c, 0x08980898},
+       {0x0000801c, 0x148ec02b, 0x148ec057},
+       {0x00008318, 0x000044c0, 0x00008980},
+       {0x00009820, 0x02020200, 0x02020200},
+       {0x00009824, 0x01000f0f, 0x01000f0f},
+       {0x00009828, 0x0b020001, 0x0b020001},
+       {0x00009834, 0x00000f0f, 0x00000f0f},
+       {0x00009844, 0x03721821, 0x03721821},
+       {0x00009914, 0x00000898, 0x00001130},
+       {0x00009918, 0x0000000b, 0x00000016},
+};
+
+static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290},
+       {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300},
+       {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304},
+       {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308},
+       {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c},
+       {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+       {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+       {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+       {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+       {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+       {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+       {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+       {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+       {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+       {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+       {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+       {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+       {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+       {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+       {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+       {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+       {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+       {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+       {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+       {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+       {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+       {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+       {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+       {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+       {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+       {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+       {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+       {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+       {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+       {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+       {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+       {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+       {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+       {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+       {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+       {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+       {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+       {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+       {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+       {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+       {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+       {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+       {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+       {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10},
+       {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80},
+       {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84},
+       {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88},
+       {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c},
+       {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90},
+       {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94},
+       {0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98},
+       {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4},
+       {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8},
+       {0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac},
+       {0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0},
+       {0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4},
+       {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1},
+       {0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5},
+       {0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9},
+       {0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad},
+       {0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1},
+       {0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5},
+       {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2},
+       {0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6},
+       {0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa},
+       {0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae},
+       {0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2},
+       {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6},
+       {0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3},
+       {0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7},
+       {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab},
+       {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf},
+       {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3},
+       {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7},
+       {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3},
+       {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7},
+       {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb},
+       {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf},
+       {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3},
+       {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7},
+       {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb},
+       {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb},
+       {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb},
+       {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb},
+       {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb},
+       {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb},
+       {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb},
+       {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb},
+       {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb},
+       {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb},
+       {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb},
+       {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb},
+       {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb},
+       {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb},
+       {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb},
+       {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb},
+       {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb},
+       {0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055},
+       {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055},
+};
+
+static const u32 ar9280Modes_original_rxgain_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000},
+       {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000},
+       {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000},
+       {0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000},
+       {0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000},
+       {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+       {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+       {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+       {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+       {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+       {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+       {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+       {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+       {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+       {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+       {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+       {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+       {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+       {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+       {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+       {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+       {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+       {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+       {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+       {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+       {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+       {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+       {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+       {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+       {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+       {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+       {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+       {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+       {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+       {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+       {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+       {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+       {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+       {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+       {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+       {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+       {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+       {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+       {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+       {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+       {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+       {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+       {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+       {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80},
+       {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84},
+       {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88},
+       {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c},
+       {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90},
+       {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80},
+       {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84},
+       {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88},
+       {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c},
+       {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90},
+       {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c},
+       {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310},
+       {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384},
+       {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388},
+       {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324},
+       {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704},
+       {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4},
+       {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8},
+       {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710},
+       {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714},
+       {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720},
+       {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724},
+       {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728},
+       {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c},
+       {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0},
+       {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4},
+       {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8},
+       {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0},
+       {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4},
+       {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8},
+       {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5},
+       {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9},
+       {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad},
+       {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1},
+       {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5},
+       {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9},
+       {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5},
+       {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9},
+       {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1},
+       {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5},
+       {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9},
+       {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6},
+       {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca},
+       {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce},
+       {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2},
+       {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6},
+       {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3},
+       {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7},
+       {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb},
+       {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf},
+       {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7},
+       {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db},
+       {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db},
+       {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db},
+       {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063},
+       {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063},
+};
+
+static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290},
+       {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300},
+       {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304},
+       {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308},
+       {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c},
+       {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+       {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+       {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+       {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+       {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+       {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+       {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+       {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+       {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+       {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+       {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+       {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+       {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+       {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+       {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+       {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+       {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+       {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+       {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+       {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+       {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+       {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+       {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+       {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+       {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+       {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+       {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+       {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+       {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+       {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+       {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+       {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+       {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+       {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+       {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+       {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+       {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+       {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+       {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+       {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+       {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+       {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+       {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+       {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80},
+       {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84},
+       {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88},
+       {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c},
+       {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90},
+       {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80},
+       {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84},
+       {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88},
+       {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c},
+       {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90},
+       {0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310},
+       {0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314},
+       {0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320},
+       {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324},
+       {0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328},
+       {0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c},
+       {0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330},
+       {0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334},
+       {0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321},
+       {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325},
+       {0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329},
+       {0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d},
+       {0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331},
+       {0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335},
+       {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322},
+       {0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326},
+       {0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a},
+       {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e},
+       {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332},
+       {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336},
+       {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323},
+       {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327},
+       {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b},
+       {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f},
+       {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333},
+       {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337},
+       {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343},
+       {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347},
+       {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b},
+       {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f},
+       {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353},
+       {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357},
+       {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b},
+       {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b},
+       {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b},
+       {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b},
+       {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b},
+       {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b},
+       {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b},
+       {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b},
+       {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b},
+       {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b},
+       {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b},
+       {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b},
+       {0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a},
+       {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a},
+};
+
+static const u32 ar9280Modes_high_power_tx_gain_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652},
+       {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce},
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002},
+       {0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008},
+       {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010},
+       {0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012},
+       {0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014},
+       {0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a},
+       {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211},
+       {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213},
+       {0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411},
+       {0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413},
+       {0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811},
+       {0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813},
+       {0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14},
+       {0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50},
+       {0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c},
+       {0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a},
+       {0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92},
+       {0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2},
+       {0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5},
+       {0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54},
+       {0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5},
+       {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
+       {0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
+       {0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
+       {0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
+       {0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
+       {0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
+       {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
+};
+
+static const u32 ar9280Modes_original_tx_gain_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652},
+       {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce},
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002},
+       {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009},
+       {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b},
+       {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012},
+       {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048},
+       {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a},
+       {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211},
+       {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213},
+       {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b},
+       {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412},
+       {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414},
+       {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a},
+       {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649},
+       {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b},
+       {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49},
+       {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48},
+       {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a},
+       {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88},
+       {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a},
+       {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9},
+       {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42},
+       {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
+       {0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
+       {0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
+       {0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
+       {0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
+       {0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
+       {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
+};
+
+static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
+       /* Addr      allmodes  */
+       {0x00004040, 0x9248fd00},
+       {0x00004040, 0x24924924},
+       {0x00004040, 0xa8000019},
+       {0x00004040, 0x13160820},
+       {0x00004040, 0xe5980560},
+       {0x00004040, 0xc01dcffc},
+       {0x00004040, 0x1aaabe41},
+       {0x00004040, 0xbe105554},
+       {0x00004040, 0x00043007},
+       {0x00004044, 0x00000000},
+};
+
+static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
+       /* Addr      allmodes  */
+       {0x00004040, 0x9248fd00},
+       {0x00004040, 0x24924924},
+       {0x00004040, 0xa8000019},
+       {0x00004040, 0x13160820},
+       {0x00004040, 0xe5980560},
+       {0x00004040, 0xc01dcffd},
+       {0x00004040, 0x1aaabe41},
+       {0x00004040, 0xbe105554},
+       {0x00004040, 0x00043007},
+       {0x00004044, 0x00000000},
+};
+
+static const u32 ar9285Modes_9285_1_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
+       {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620},
+       {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+       {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+       {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+       {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+       {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20},
+       {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+       {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020},
+       {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
+       {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00},
+       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+       {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
+       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+       {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+       {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+       {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+       {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+       {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+       {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+       {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+       {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+       {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+       {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+       {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+       {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+       {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+       {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+       {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+       {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+       {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+       {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+       {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+       {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+       {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+       {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+       {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+       {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+       {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+       {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+       {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+       {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+       {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+       {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+       {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+       {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+       {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+       {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+       {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+       {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+       {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+       {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+       {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+       {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+       {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+       {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+       {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+       {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+       {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+       {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+       {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+       {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+       {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+       {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+       {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+       {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+       {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+       {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+       {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+       {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+       {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+       {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+       {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+       {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+       {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+       {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+       {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+       {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+       {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+       {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+       {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+       {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+       {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+       {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+       {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+       {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+       {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+       {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+       {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+       {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+       {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+       {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+       {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+       {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+       {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+       {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+       {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+       {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+       {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+       {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+       {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+       {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+       {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+       {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+       {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+       {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+       {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+       {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+       {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+       {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+       {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+       {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+       {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+       {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+       {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+       {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+       {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+       {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+       {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+       {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+       {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+       {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+       {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+       {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+       {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+       {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+       {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+       {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+       {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+       {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+       {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+       {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+       {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+       {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+       {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+       {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+       {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+       {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+       {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+       {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+       {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+       {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+       {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+       {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+       {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+       {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+       {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+       {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+       {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+       {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+       {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+       {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+       {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+       {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+       {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+       {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+       {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+       {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+       {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+       {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+       {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+       {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+       {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+       {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+       {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+       {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+       {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+       {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+       {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+       {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+       {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+       {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+       {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+       {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+       {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+       {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+       {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+       {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+       {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+       {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+       {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+       {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+       {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+       {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+       {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+       {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+       {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+       {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+       {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+       {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+       {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+       {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
+       {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+       {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000},
+       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
+};
+
+static const u32 ar9285Common_9285_1_2[][2] = {
+       /* Addr      allmodes  */
+       {0x0000000c, 0x00000000},
+       {0x00000030, 0x00020045},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000008},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00000054, 0x0000001f},
+       {0x00000800, 0x00000000},
+       {0x00000804, 0x00000000},
+       {0x00000808, 0x00000000},
+       {0x0000080c, 0x00000000},
+       {0x00000810, 0x00000000},
+       {0x00000814, 0x00000000},
+       {0x00000818, 0x00000000},
+       {0x0000081c, 0x00000000},
+       {0x00000820, 0x00000000},
+       {0x00000824, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x00001230, 0x00000000},
+       {0x00001270, 0x00000000},
+       {0x00001038, 0x00000000},
+       {0x00001078, 0x00000000},
+       {0x000010b8, 0x00000000},
+       {0x000010f8, 0x00000000},
+       {0x00001138, 0x00000000},
+       {0x00001178, 0x00000000},
+       {0x000011b8, 0x00000000},
+       {0x000011f8, 0x00000000},
+       {0x00001238, 0x00000000},
+       {0x00001278, 0x00000000},
+       {0x000012b8, 0x00000000},
+       {0x000012f8, 0x00000000},
+       {0x00001338, 0x00000000},
+       {0x00001378, 0x00000000},
+       {0x000013b8, 0x00000000},
+       {0x000013f8, 0x00000000},
+       {0x00001438, 0x00000000},
+       {0x00001478, 0x00000000},
+       {0x000014b8, 0x00000000},
+       {0x000014f8, 0x00000000},
+       {0x00001538, 0x00000000},
+       {0x00001578, 0x00000000},
+       {0x000015b8, 0x00000000},
+       {0x000015f8, 0x00000000},
+       {0x00001638, 0x00000000},
+       {0x00001678, 0x00000000},
+       {0x000016b8, 0x00000000},
+       {0x000016f8, 0x00000000},
+       {0x00001738, 0x00000000},
+       {0x00001778, 0x00000000},
+       {0x000017b8, 0x00000000},
+       {0x000017f8, 0x00000000},
+       {0x0000103c, 0x00000000},
+       {0x0000107c, 0x00000000},
+       {0x000010bc, 0x00000000},
+       {0x000010fc, 0x00000000},
+       {0x0000113c, 0x00000000},
+       {0x0000117c, 0x00000000},
+       {0x000011bc, 0x00000000},
+       {0x000011fc, 0x00000000},
+       {0x0000123c, 0x00000000},
+       {0x0000127c, 0x00000000},
+       {0x000012bc, 0x00000000},
+       {0x000012fc, 0x00000000},
+       {0x0000133c, 0x00000000},
+       {0x0000137c, 0x00000000},
+       {0x000013bc, 0x00000000},
+       {0x000013fc, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00004030, 0x00000002},
+       {0x0000403c, 0x00000002},
+       {0x00004024, 0x0000001f},
+       {0x00004060, 0x00000000},
+       {0x00004064, 0x00000000},
+       {0x00007010, 0x00000031},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000700},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000000},
+       {0x000080c0, 0x2a80001a},
+       {0x000080c4, 0x05dc01e0},
+       {0x000080c8, 0x1f402710},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00001e00},
+       {0x000080d4, 0x00000000},
+       {0x000080d8, 0x00400000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x003f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080f8, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00020000},
+       {0x00008104, 0x00000001},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000168},
+       {0x00008118, 0x000100aa},
+       {0x0000811c, 0x00003210},
+       {0x00008120, 0x08f04810},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x00000000},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x32143320},
+       {0x00008174, 0xfaa4fa50},
+       {0x00008178, 0x00000100},
+       {0x0000817c, 0x00000000},
+       {0x000081c0, 0x00000000},
+       {0x000081d0, 0x0000320a},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008200, 0x00000000},
+       {0x00008204, 0x00000000},
+       {0x00008208, 0x00000000},
+       {0x0000820c, 0x00000000},
+       {0x00008210, 0x00000000},
+       {0x00008214, 0x00000000},
+       {0x00008218, 0x00000000},
+       {0x0000821c, 0x00000000},
+       {0x00008220, 0x00000000},
+       {0x00008224, 0x00000000},
+       {0x00008228, 0x00000000},
+       {0x0000822c, 0x00000000},
+       {0x00008230, 0x00000000},
+       {0x00008234, 0x00000000},
+       {0x00008238, 0x00000000},
+       {0x0000823c, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000100},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x400000ff},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x88a00010},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000000},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x00000000},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000040},
+       {0x00008314, 0x00000000},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000001},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000e00},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x00000000},
+       {0x00008340, 0x00010380},
+       {0x00008344, 0x00481043},
+       {0x00009808, 0x00000000},
+       {0x0000980c, 0xafe68e30},
+       {0x00009810, 0xfd14e000},
+       {0x00009814, 0x9c0a9f6b},
+       {0x0000981c, 0x00000000},
+       {0x0000982c, 0x0000a000},
+       {0x00009830, 0x00000000},
+       {0x0000983c, 0x00200400},
+       {0x0000984c, 0x0040233c},
+       {0x00009854, 0x00000044},
+       {0x00009900, 0x00000000},
+       {0x00009904, 0x00000000},
+       {0x00009908, 0x00000000},
+       {0x0000990c, 0x00000000},
+       {0x00009910, 0x01002310},
+       {0x0000991c, 0x10000fff},
+       {0x00009920, 0x04900000},
+       {0x00009928, 0x00000001},
+       {0x0000992c, 0x00000004},
+       {0x00009934, 0x1e1f2022},
+       {0x00009938, 0x0a0b0c0d},
+       {0x0000993c, 0x00000000},
+       {0x00009940, 0x14750604},
+       {0x00009948, 0x9280c00a},
+       {0x0000994c, 0x00020028},
+       {0x00009954, 0x5f3ca3de},
+       {0x00009958, 0x2108ecff},
+       {0x00009968, 0x000003ce},
+       {0x00009970, 0x192bb514},
+       {0x00009974, 0x00000000},
+       {0x00009978, 0x00000001},
+       {0x0000997c, 0x00000000},
+       {0x00009980, 0x00000000},
+       {0x00009984, 0x00000000},
+       {0x00009988, 0x00000000},
+       {0x0000998c, 0x00000000},
+       {0x00009990, 0x00000000},
+       {0x00009994, 0x00000000},
+       {0x00009998, 0x00000000},
+       {0x0000999c, 0x00000000},
+       {0x000099a0, 0x00000000},
+       {0x000099a4, 0x00000001},
+       {0x000099a8, 0x201fff00},
+       {0x000099ac, 0x2def0400},
+       {0x000099b0, 0x03051000},
+       {0x000099b4, 0x00000820},
+       {0x000099dc, 0x00000000},
+       {0x000099e0, 0x00000000},
+       {0x000099e4, 0xaaaaaaaa},
+       {0x000099e8, 0x3c466478},
+       {0x000099ec, 0x0cc80caa},
+       {0x000099f0, 0x00000000},
+       {0x0000a208, 0x803e68c8},
+       {0x0000a210, 0x4080a333},
+       {0x0000a214, 0x00206c10},
+       {0x0000a218, 0x009c4060},
+       {0x0000a220, 0x01834061},
+       {0x0000a224, 0x00000400},
+       {0x0000a228, 0x000003b5},
+       {0x0000a22c, 0x00000000},
+       {0x0000a234, 0x20202020},
+       {0x0000a238, 0x20202020},
+       {0x0000a244, 0x00000000},
+       {0x0000a248, 0xfffffffc},
+       {0x0000a24c, 0x00000000},
+       {0x0000a254, 0x00000000},
+       {0x0000a258, 0x0ccb5380},
+       {0x0000a25c, 0x15151501},
+       {0x0000a260, 0xdfa90f01},
+       {0x0000a268, 0x00000000},
+       {0x0000a26c, 0x0ebae9e6},
+       {0x0000d270, 0x0d820820},
+       {0x0000d35c, 0x07ffffef},
+       {0x0000d360, 0x0fffffe7},
+       {0x0000d364, 0x17ffffe5},
+       {0x0000d368, 0x1fffffe4},
+       {0x0000d36c, 0x37ffffe3},
+       {0x0000d370, 0x3fffffe3},
+       {0x0000d374, 0x57ffffe3},
+       {0x0000d378, 0x5fffffe2},
+       {0x0000d37c, 0x7fffffe2},
+       {0x0000d380, 0x7f3c7bba},
+       {0x0000d384, 0xf3307ff0},
+       {0x0000a388, 0x0c000000},
+       {0x0000a38c, 0x20202020},
+       {0x0000a390, 0x20202020},
+       {0x0000a39c, 0x00000001},
+       {0x0000a3a0, 0x00000000},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0x00000000},
+       {0x0000a3ac, 0x00000000},
+       {0x0000a3b0, 0x00000000},
+       {0x0000a3b4, 0x00000000},
+       {0x0000a3b8, 0x00000000},
+       {0x0000a3bc, 0x00000000},
+       {0x0000a3c0, 0x00000000},
+       {0x0000a3c4, 0x00000000},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3e4, 0x00000000},
+       {0x0000a3e8, 0x18c43433},
+       {0x0000a3ec, 0x00f70081},
+       {0x00007800, 0x00140000},
+       {0x00007804, 0x0e4548d8},
+       {0x00007808, 0x54214514},
+       {0x0000780c, 0x02025830},
+       {0x00007810, 0x71c0d388},
+       {0x0000781c, 0x00000000},
+       {0x00007824, 0x00d86fff},
+       {0x0000782c, 0x6e36d97b},
+       {0x00007834, 0x71400087},
+       {0x00007844, 0x000c0db6},
+       {0x00007848, 0x6db6246f},
+       {0x0000784c, 0x6d9b66db},
+       {0x00007850, 0x6d8c6dba},
+       {0x00007854, 0x00040000},
+       {0x00007858, 0xdb003012},
+       {0x0000785c, 0x04924914},
+       {0x00007860, 0x21084210},
+       {0x00007864, 0xf7d7ffde},
+       {0x00007868, 0xc2034080},
+       {0x00007870, 0x10142c00},
+};
+
+static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240},
+       {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600},
+       {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802},
+       {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805},
+       {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80},
+       {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
+       {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
+       {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
+       {0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803},
+       {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
+       {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
+       {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
+       {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+       {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652},
+       {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
+       {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+       {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+};
+
+static const u32 ar9285Modes_original_tx_gain_9285_1_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+       {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9},
+       {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718},
+       {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758},
+       {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a},
+       {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f},
+       {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
+       {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
+       {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
+       {0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801},
+       {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
+       {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
+       {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+       {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+       {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652},
+       {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
+       {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+       {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+};
+
+static const u32 ar9285Modes_XE2_0_normal_power[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+       {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9},
+       {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718},
+       {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758},
+       {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a},
+       {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f},
+       {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
+       {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b},
+       {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
+       {0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441},
+       {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
+       {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
+       {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+       {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+       {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652},
+       {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
+       {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+       {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+};
+
+static const u32 ar9285Modes_XE2_0_high_power[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240},
+       {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600},
+       {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802},
+       {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805},
+       {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80},
+       {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
+       {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b},
+       {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
+       {0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443},
+       {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
+       {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
+       {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
+       {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+       {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652},
+       {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
+       {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+       {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+};
+
+static const u32 ar9287Modes_9287_1_1[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a},
+       {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440},
+       {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300},
+       {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200},
+       {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e},
+       {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001},
+       {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007},
+       {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e},
+       {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0},
+       {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2},
+       {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e},
+       {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e},
+       {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20},
+       {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0},
+       {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881},
+       {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898},
+       {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b},
+       {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d},
+       {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010},
+       {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+       {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+       {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210},
+       {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce},
+       {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c},
+       {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00},
+       {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4},
+       {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444},
+       {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000},
+       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
+       {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9287Common_9287_1_1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000000c, 0x00000000},
+       {0x00000030, 0x00020015},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000008},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00000054, 0x0000001f},
+       {0x00000800, 0x00000000},
+       {0x00000804, 0x00000000},
+       {0x00000808, 0x00000000},
+       {0x0000080c, 0x00000000},
+       {0x00000810, 0x00000000},
+       {0x00000814, 0x00000000},
+       {0x00000818, 0x00000000},
+       {0x0000081c, 0x00000000},
+       {0x00000820, 0x00000000},
+       {0x00000824, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x00001230, 0x00000000},
+       {0x00001270, 0x00000000},
+       {0x00001038, 0x00000000},
+       {0x00001078, 0x00000000},
+       {0x000010b8, 0x00000000},
+       {0x000010f8, 0x00000000},
+       {0x00001138, 0x00000000},
+       {0x00001178, 0x00000000},
+       {0x000011b8, 0x00000000},
+       {0x000011f8, 0x00000000},
+       {0x00001238, 0x00000000},
+       {0x00001278, 0x00000000},
+       {0x000012b8, 0x00000000},
+       {0x000012f8, 0x00000000},
+       {0x00001338, 0x00000000},
+       {0x00001378, 0x00000000},
+       {0x000013b8, 0x00000000},
+       {0x000013f8, 0x00000000},
+       {0x00001438, 0x00000000},
+       {0x00001478, 0x00000000},
+       {0x000014b8, 0x00000000},
+       {0x000014f8, 0x00000000},
+       {0x00001538, 0x00000000},
+       {0x00001578, 0x00000000},
+       {0x000015b8, 0x00000000},
+       {0x000015f8, 0x00000000},
+       {0x00001638, 0x00000000},
+       {0x00001678, 0x00000000},
+       {0x000016b8, 0x00000000},
+       {0x000016f8, 0x00000000},
+       {0x00001738, 0x00000000},
+       {0x00001778, 0x00000000},
+       {0x000017b8, 0x00000000},
+       {0x000017f8, 0x00000000},
+       {0x0000103c, 0x00000000},
+       {0x0000107c, 0x00000000},
+       {0x000010bc, 0x00000000},
+       {0x000010fc, 0x00000000},
+       {0x0000113c, 0x00000000},
+       {0x0000117c, 0x00000000},
+       {0x000011bc, 0x00000000},
+       {0x000011fc, 0x00000000},
+       {0x0000123c, 0x00000000},
+       {0x0000127c, 0x00000000},
+       {0x000012bc, 0x00000000},
+       {0x000012fc, 0x00000000},
+       {0x0000133c, 0x00000000},
+       {0x0000137c, 0x00000000},
+       {0x000013bc, 0x00000000},
+       {0x000013fc, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00004030, 0x00000002},
+       {0x0000403c, 0x00000002},
+       {0x00004024, 0x0000001f},
+       {0x00004060, 0x00000000},
+       {0x00004064, 0x00000000},
+       {0x00007010, 0x00000033},
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000700},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008048, 0x40000000},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000000},
+       {0x000080c0, 0x2a80001a},
+       {0x000080c4, 0x05dc01e0},
+       {0x000080c8, 0x1f402710},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00001e00},
+       {0x000080d4, 0x00000000},
+       {0x000080d8, 0x00400000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x003f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080f8, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00020000},
+       {0x00008104, 0x00000001},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000168},
+       {0x00008118, 0x000100aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x00000000},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x18487320},
+       {0x00008174, 0xfaa4fa50},
+       {0x00008178, 0x00000100},
+       {0x0000817c, 0x00000000},
+       {0x000081c0, 0x00000000},
+       {0x000081c4, 0x00000000},
+       {0x000081d4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008200, 0x00000000},
+       {0x00008204, 0x00000000},
+       {0x00008208, 0x00000000},
+       {0x0000820c, 0x00000000},
+       {0x00008210, 0x00000000},
+       {0x00008214, 0x00000000},
+       {0x00008218, 0x00000000},
+       {0x0000821c, 0x00000000},
+       {0x00008220, 0x00000000},
+       {0x00008224, 0x00000000},
+       {0x00008228, 0x00000000},
+       {0x0000822c, 0x00000000},
+       {0x00008230, 0x00000000},
+       {0x00008234, 0x00000000},
+       {0x00008238, 0x00000000},
+       {0x0000823c, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000100},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x400000ff},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x88a00010},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000000},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000040},
+       {0x00008314, 0x00000000},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000e00},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x00000000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0x01c81043},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0x0fffffff},
+       {0x00008394, 0x0fffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a0, 0x00000000},
+       {0x00009808, 0x00000000},
+       {0x0000980c, 0xafe68e30},
+       {0x00009810, 0xfd14e000},
+       {0x00009814, 0x9c0a9f6b},
+       {0x0000981c, 0x00000000},
+       {0x0000982c, 0x0000a000},
+       {0x00009830, 0x00000000},
+       {0x0000983c, 0x00200400},
+       {0x0000984c, 0x0040233c},
+       {0x0000a84c, 0x0040233c},
+       {0x00009854, 0x00000044},
+       {0x00009900, 0x00000000},
+       {0x00009904, 0x00000000},
+       {0x00009908, 0x00000000},
+       {0x0000990c, 0x00000000},
+       {0x00009910, 0x10002310},
+       {0x0000991c, 0x10000fff},
+       {0x00009920, 0x04900000},
+       {0x0000a920, 0x04900000},
+       {0x00009928, 0x00000001},
+       {0x0000992c, 0x00000004},
+       {0x00009930, 0x00000000},
+       {0x0000a930, 0x00000000},
+       {0x00009934, 0x1e1f2022},
+       {0x00009938, 0x0a0b0c0d},
+       {0x0000993c, 0x00000000},
+       {0x00009948, 0x9280c00a},
+       {0x0000994c, 0x00020028},
+       {0x00009954, 0x5f3ca3de},
+       {0x00009958, 0x0108ecff},
+       {0x00009940, 0x14750604},
+       {0x0000c95c, 0x004b6a8e},
+       {0x00009970, 0x990bb514},
+       {0x00009974, 0x00000000},
+       {0x00009978, 0x00000001},
+       {0x0000997c, 0x00000000},
+       {0x000099a0, 0x00000000},
+       {0x000099a4, 0x00000001},
+       {0x000099a8, 0x201fff00},
+       {0x000099ac, 0x0c6f0000},
+       {0x000099b0, 0x03051000},
+       {0x000099b4, 0x00000820},
+       {0x000099c4, 0x06336f77},
+       {0x000099c8, 0x6af6532f},
+       {0x000099cc, 0x08f186c8},
+       {0x000099d0, 0x00046384},
+       {0x000099dc, 0x00000000},
+       {0x000099e0, 0x00000000},
+       {0x000099e4, 0xaaaaaaaa},
+       {0x000099e8, 0x3c466478},
+       {0x000099ec, 0x0cc80caa},
+       {0x000099f0, 0x00000000},
+       {0x000099fc, 0x00001042},
+       {0x0000a208, 0x803e4788},
+       {0x0000a210, 0x4080a333},
+       {0x0000a214, 0x40206c10},
+       {0x0000a218, 0x009c4060},
+       {0x0000a220, 0x01834061},
+       {0x0000a224, 0x00000400},
+       {0x0000a228, 0x000003b5},
+       {0x0000a22c, 0x233f7180},
+       {0x0000a234, 0x20202020},
+       {0x0000a238, 0x20202020},
+       {0x0000a23c, 0x13c889af},
+       {0x0000a240, 0x38490a20},
+       {0x0000a244, 0x00000000},
+       {0x0000a248, 0xfffffffc},
+       {0x0000a24c, 0x00000000},
+       {0x0000a254, 0x00000000},
+       {0x0000a258, 0x0cdbd380},
+       {0x0000a25c, 0x0f0f0f01},
+       {0x0000a260, 0xdfa91f01},
+       {0x0000a264, 0x00418a11},
+       {0x0000b264, 0x00418a11},
+       {0x0000a268, 0x00000000},
+       {0x0000a26c, 0x0e79e5c6},
+       {0x0000b26c, 0x0e79e5c6},
+       {0x0000d270, 0x00820820},
+       {0x0000a278, 0x1ce739ce},
+       {0x0000a27c, 0x050701ce},
+       {0x0000d35c, 0x07ffffef},
+       {0x0000d360, 0x0fffffe7},
+       {0x0000d364, 0x17ffffe5},
+       {0x0000d368, 0x1fffffe4},
+       {0x0000d36c, 0x37ffffe3},
+       {0x0000d370, 0x3fffffe3},
+       {0x0000d374, 0x57ffffe3},
+       {0x0000d378, 0x5fffffe2},
+       {0x0000d37c, 0x7fffffe2},
+       {0x0000d380, 0x7f3c7bba},
+       {0x0000d384, 0xf3307ff0},
+       {0x0000a388, 0x0c000000},
+       {0x0000a38c, 0x20202020},
+       {0x0000a390, 0x20202020},
+       {0x0000a394, 0x1ce739ce},
+       {0x0000a398, 0x000001ce},
+       {0x0000b398, 0x000001ce},
+       {0x0000a39c, 0x00000001},
+       {0x0000a3c8, 0x00000246},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3dc, 0x1ce739ce},
+       {0x0000a3e0, 0x000001ce},
+       {0x0000a3e4, 0x00000000},
+       {0x0000a3e8, 0x18c43433},
+       {0x0000a3ec, 0x00f70081},
+       {0x0000a3f0, 0x01036a1e},
+       {0x0000a3f4, 0x00000000},
+       {0x0000b3f4, 0x00000000},
+       {0x0000a7d8, 0x000003f1},
+       {0x00007800, 0x00000800},
+       {0x00007804, 0x6c35ffd2},
+       {0x00007808, 0x6db6c000},
+       {0x0000780c, 0x6db6cb30},
+       {0x00007810, 0x6db6cb6c},
+       {0x00007814, 0x0501e200},
+       {0x00007818, 0x0094128d},
+       {0x0000781c, 0x976ee392},
+       {0x00007820, 0xf75ff6fc},
+       {0x00007824, 0x00040000},
+       {0x00007828, 0xdb003012},
+       {0x0000782c, 0x04924914},
+       {0x00007830, 0x21084210},
+       {0x00007834, 0x00140000},
+       {0x00007838, 0x0e4548d8},
+       {0x0000783c, 0x54214514},
+       {0x00007840, 0x02025830},
+       {0x00007844, 0x71c0d388},
+       {0x00007848, 0x934934a8},
+       {0x00007850, 0x00000000},
+       {0x00007854, 0x00000800},
+       {0x00007858, 0x6c35ffd2},
+       {0x0000785c, 0x6db6c000},
+       {0x00007860, 0x6db6cb30},
+       {0x00007864, 0x6db6cb6c},
+       {0x00007868, 0x0501e200},
+       {0x0000786c, 0x0094128d},
+       {0x00007870, 0x976ee392},
+       {0x00007874, 0xf75ff6fc},
+       {0x00007878, 0x00040000},
+       {0x0000787c, 0xdb003012},
+       {0x00007880, 0x04924914},
+       {0x00007884, 0x21084210},
+       {0x00007888, 0x001b6db0},
+       {0x0000788c, 0x00376b63},
+       {0x00007890, 0x06db6db6},
+       {0x00007894, 0x006d8000},
+       {0x00007898, 0x48100000},
+       {0x0000789c, 0x00000000},
+       {0x000078a0, 0x08000000},
+       {0x000078a4, 0x0007ffd8},
+       {0x000078a8, 0x0007ffd8},
+       {0x000078ac, 0x001c0020},
+       {0x000078b0, 0x00060aeb},
+       {0x000078b4, 0x40008080},
+       {0x000078b8, 0x2a850160},
+};
+
+static const u32 ar9287Common_normal_cck_fir_coeff_9287_1_1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a1f4, 0x00fffeff},
+       {0x0000a1f8, 0x00f5f9ff},
+       {0x0000a1fc, 0xb79f6427},
+};
+
+static const u32 ar9287Common_japan_2484_cck_fir_coeff_9287_1_1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a1f4, 0x00000000},
+       {0x0000a1f8, 0xefff0301},
+       {0x0000a1fc, 0xca9228ee},
+};
+
+static const u32 ar9287Modes_tx_gain_9287_1_1[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a},
+       {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b},
+       {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a},
+       {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a},
+       {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a},
+       {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a},
+       {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a},
+       {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c},
+       {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc},
+       {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4},
+       {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc},
+       {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede},
+       {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e},
+       {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e},
+       {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e},
+       {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062},
+       {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064},
+       {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4},
+       {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa},
+       {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac},
+       {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4},
+       {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4},
+       {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134},
+       {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174},
+       {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c},
+       {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e},
+       {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be},
+       {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000},
+};
+
+static const u32 ar9287Modes_rx_gain_9287_1_1[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120},
+       {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124},
+       {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128},
+       {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c},
+       {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130},
+       {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194},
+       {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198},
+       {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c},
+       {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210},
+       {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284},
+       {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288},
+       {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c},
+       {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290},
+       {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294},
+       {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0},
+       {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4},
+       {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8},
+       {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac},
+       {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0},
+       {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4},
+       {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8},
+       {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4},
+       {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708},
+       {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c},
+       {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710},
+       {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04},
+       {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08},
+       {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c},
+       {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10},
+       {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14},
+       {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18},
+       {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c},
+       {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90},
+       {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94},
+       {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98},
+       {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4},
+       {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8},
+       {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04},
+       {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08},
+       {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c},
+       {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10},
+       {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14},
+       {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18},
+       {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c},
+       {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90},
+       {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18},
+       {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24},
+       {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28},
+       {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314},
+       {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318},
+       {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c},
+       {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390},
+       {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394},
+       {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398},
+       {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4},
+       {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8},
+       {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac},
+       {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0},
+       {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380},
+       {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384},
+       {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388},
+       {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710},
+       {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714},
+       {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718},
+       {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10},
+       {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14},
+       {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18},
+       {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c},
+       {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90},
+       {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94},
+       {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c},
+       {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90},
+       {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94},
+       {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0},
+       {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4},
+       {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8},
+       {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac},
+       {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0},
+       {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4},
+       {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1},
+       {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5},
+       {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9},
+       {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad},
+       {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1},
+       {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5},
+       {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9},
+       {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5},
+       {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9},
+       {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd},
+       {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1},
+       {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5},
+       {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2},
+       {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6},
+       {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca},
+       {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce},
+       {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2},
+       {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6},
+       {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda},
+       {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7},
+       {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb},
+       {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf},
+       {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3},
+       {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7},
+       {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120},
+       {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124},
+       {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128},
+       {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c},
+       {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130},
+       {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194},
+       {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198},
+       {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c},
+       {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210},
+       {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284},
+       {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288},
+       {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c},
+       {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290},
+       {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294},
+       {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0},
+       {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4},
+       {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8},
+       {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac},
+       {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0},
+       {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4},
+       {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8},
+       {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4},
+       {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708},
+       {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c},
+       {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710},
+       {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04},
+       {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08},
+       {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c},
+       {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10},
+       {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14},
+       {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18},
+       {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c},
+       {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90},
+       {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94},
+       {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98},
+       {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4},
+       {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8},
+       {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04},
+       {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08},
+       {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c},
+       {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10},
+       {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14},
+       {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18},
+       {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c},
+       {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90},
+       {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18},
+       {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24},
+       {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28},
+       {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314},
+       {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318},
+       {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c},
+       {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390},
+       {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394},
+       {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398},
+       {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4},
+       {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8},
+       {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac},
+       {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0},
+       {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380},
+       {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384},
+       {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388},
+       {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710},
+       {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714},
+       {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718},
+       {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10},
+       {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14},
+       {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18},
+       {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c},
+       {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90},
+       {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94},
+       {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c},
+       {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90},
+       {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94},
+       {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0},
+       {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4},
+       {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8},
+       {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac},
+       {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0},
+       {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4},
+       {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1},
+       {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5},
+       {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9},
+       {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad},
+       {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1},
+       {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5},
+       {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9},
+       {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5},
+       {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9},
+       {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd},
+       {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1},
+       {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5},
+       {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2},
+       {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6},
+       {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca},
+       {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce},
+       {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2},
+       {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6},
+       {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda},
+       {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7},
+       {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb},
+       {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf},
+       {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3},
+       {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7},
+       {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067},
+       {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067},
+};
+
+static const u32 ar9271Modes_9271[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
+       {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620},
+       {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+       {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+       {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+       {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+       {0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
+       {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+       {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020},
+       {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
+       {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00},
+       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+       {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
+       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+       {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+       {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+       {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+       {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+       {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+       {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+       {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+       {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+       {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+       {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+       {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+       {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+       {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+       {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+       {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+       {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+       {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+       {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+       {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+       {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+       {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+       {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+       {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+       {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+       {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+       {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+       {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+       {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+       {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+       {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+       {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+       {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+       {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+       {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+       {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+       {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+       {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+       {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+       {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+       {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+       {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+       {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+       {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+       {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+       {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+       {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+       {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+       {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+       {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+       {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+       {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+       {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+       {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+       {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+       {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+       {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+       {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+       {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+       {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+       {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+       {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+       {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+       {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+       {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+       {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+       {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+       {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+       {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+       {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+       {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+       {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+       {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+       {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+       {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+       {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+       {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+       {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+       {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+       {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+       {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+       {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+       {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+       {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+       {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+       {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+       {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+       {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+       {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+       {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+       {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+       {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+       {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+       {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+       {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+       {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+       {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+       {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+       {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+       {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+       {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+       {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+       {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+       {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+       {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+       {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+       {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+       {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+       {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+       {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+       {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+       {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+       {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+       {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+       {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+       {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+       {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+       {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+       {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+       {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+       {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+       {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+       {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+       {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+       {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+       {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+       {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+       {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+       {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+       {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+       {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+       {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+       {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+       {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+       {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+       {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+       {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+       {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+       {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+       {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+       {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+       {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+       {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+       {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+       {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+       {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+       {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+       {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+       {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+       {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+       {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+       {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+       {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+       {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+       {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+       {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+       {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+       {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+       {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+       {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+       {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+       {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+       {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+       {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+       {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+       {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+       {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+       {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+       {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+       {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+       {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+       {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+       {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+       {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+       {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+       {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+       {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+       {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+       {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
+       {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+       {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000},
+       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
+};
+
+static const u32 ar9271Common_9271[][2] = {
+       /* Addr      allmodes  */
+       {0x0000000c, 0x00000000},
+       {0x00000030, 0x00020045},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000008},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00000054, 0x0000001f},
+       {0x00000800, 0x00000000},
+       {0x00000804, 0x00000000},
+       {0x00000808, 0x00000000},
+       {0x0000080c, 0x00000000},
+       {0x00000810, 0x00000000},
+       {0x00000814, 0x00000000},
+       {0x00000818, 0x00000000},
+       {0x0000081c, 0x00000000},
+       {0x00000820, 0x00000000},
+       {0x00000824, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x00001230, 0x00000000},
+       {0x00001270, 0x00000000},
+       {0x00001038, 0x00000000},
+       {0x00001078, 0x00000000},
+       {0x000010b8, 0x00000000},
+       {0x000010f8, 0x00000000},
+       {0x00001138, 0x00000000},
+       {0x00001178, 0x00000000},
+       {0x000011b8, 0x00000000},
+       {0x000011f8, 0x00000000},
+       {0x00001238, 0x00000000},
+       {0x00001278, 0x00000000},
+       {0x000012b8, 0x00000000},
+       {0x000012f8, 0x00000000},
+       {0x00001338, 0x00000000},
+       {0x00001378, 0x00000000},
+       {0x000013b8, 0x00000000},
+       {0x000013f8, 0x00000000},
+       {0x00001438, 0x00000000},
+       {0x00001478, 0x00000000},
+       {0x000014b8, 0x00000000},
+       {0x000014f8, 0x00000000},
+       {0x00001538, 0x00000000},
+       {0x00001578, 0x00000000},
+       {0x000015b8, 0x00000000},
+       {0x000015f8, 0x00000000},
+       {0x00001638, 0x00000000},
+       {0x00001678, 0x00000000},
+       {0x000016b8, 0x00000000},
+       {0x000016f8, 0x00000000},
+       {0x00001738, 0x00000000},
+       {0x00001778, 0x00000000},
+       {0x000017b8, 0x00000000},
+       {0x000017f8, 0x00000000},
+       {0x0000103c, 0x00000000},
+       {0x0000107c, 0x00000000},
+       {0x000010bc, 0x00000000},
+       {0x000010fc, 0x00000000},
+       {0x0000113c, 0x00000000},
+       {0x0000117c, 0x00000000},
+       {0x000011bc, 0x00000000},
+       {0x000011fc, 0x00000000},
+       {0x0000123c, 0x00000000},
+       {0x0000127c, 0x00000000},
+       {0x000012bc, 0x00000000},
+       {0x000012fc, 0x00000000},
+       {0x0000133c, 0x00000000},
+       {0x0000137c, 0x00000000},
+       {0x000013bc, 0x00000000},
+       {0x000013fc, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00004030, 0x00000002},
+       {0x0000403c, 0x00000002},
+       {0x00004024, 0x0000001f},
+       {0x00004060, 0x00000000},
+       {0x00004064, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000700},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000000},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a80001a},
+       {0x000080c4, 0x05dc01e0},
+       {0x000080c8, 0x1f402710},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00001e00},
+       {0x000080d4, 0x00000000},
+       {0x000080d8, 0x00400000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x003f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080f8, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00020000},
+       {0x00008104, 0x00000001},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000168},
+       {0x00008118, 0x000100aa},
+       {0x0000811c, 0x00003210},
+       {0x00008120, 0x08f04810},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x00000000},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x32143320},
+       {0x00008174, 0xfaa4fa50},
+       {0x00008178, 0x00000100},
+       {0x0000817c, 0x00000000},
+       {0x000081c0, 0x00000000},
+       {0x000081d0, 0x0000320a},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008200, 0x00000000},
+       {0x00008204, 0x00000000},
+       {0x00008208, 0x00000000},
+       {0x0000820c, 0x00000000},
+       {0x00008210, 0x00000000},
+       {0x00008214, 0x00000000},
+       {0x00008218, 0x00000000},
+       {0x0000821c, 0x00000000},
+       {0x00008220, 0x00000000},
+       {0x00008224, 0x00000000},
+       {0x00008228, 0x00000000},
+       {0x0000822c, 0x00000000},
+       {0x00008230, 0x00000000},
+       {0x00008234, 0x00000000},
+       {0x00008238, 0x00000000},
+       {0x0000823c, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000100},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x400000ff},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x88a00010},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000000},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x00000000},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000040},
+       {0x00008314, 0x00000000},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000001},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000e00},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x00000000},
+       {0x00008340, 0x00010380},
+       {0x00008344, 0x00581043},
+       {0x00007010, 0x00000030},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+       {0x00007800, 0x00140000},
+       {0x00007804, 0x0e4548d8},
+       {0x00007808, 0x54214514},
+       {0x0000780c, 0x02025820},
+       {0x00007810, 0x71c0d388},
+       {0x00007814, 0x924934a8},
+       {0x0000781c, 0x00000000},
+       {0x00007828, 0x66964300},
+       {0x0000782c, 0x8db6d961},
+       {0x00007830, 0x8db6d96c},
+       {0x00007834, 0x6140008b},
+       {0x0000783c, 0x72ee0a72},
+       {0x00007840, 0xbbfffffc},
+       {0x00007844, 0x000c0db6},
+       {0x00007848, 0x6db6246f},
+       {0x0000784c, 0x6d9b66db},
+       {0x00007850, 0x6d8c6dba},
+       {0x00007854, 0x00040000},
+       {0x00007858, 0xdb003012},
+       {0x0000785c, 0x04924914},
+       {0x00007860, 0x21084210},
+       {0x00007864, 0xf7d7ffde},
+       {0x00007868, 0xc2034080},
+       {0x00007870, 0x10142c00},
+       {0x00009808, 0x00000000},
+       {0x0000980c, 0xafe68e30},
+       {0x00009810, 0xfd14e000},
+       {0x00009814, 0x9c0a9f6b},
+       {0x0000981c, 0x00000000},
+       {0x0000982c, 0x0000a000},
+       {0x00009830, 0x00000000},
+       {0x0000983c, 0x00200400},
+       {0x0000984c, 0x0040233c},
+       {0x00009854, 0x00000044},
+       {0x00009900, 0x00000000},
+       {0x00009904, 0x00000000},
+       {0x00009908, 0x00000000},
+       {0x0000990c, 0x00000000},
+       {0x0000991c, 0x10000fff},
+       {0x00009920, 0x04900000},
+       {0x00009928, 0x00000001},
+       {0x0000992c, 0x00000004},
+       {0x00009934, 0x1e1f2022},
+       {0x00009938, 0x0a0b0c0d},
+       {0x0000993c, 0x00000000},
+       {0x00009940, 0x14750604},
+       {0x00009948, 0x9280c00a},
+       {0x0000994c, 0x00020028},
+       {0x00009954, 0x5f3ca3de},
+       {0x00009958, 0x0108ecff},
+       {0x00009968, 0x000003ce},
+       {0x00009970, 0x192bb514},
+       {0x00009974, 0x00000000},
+       {0x00009978, 0x00000001},
+       {0x0000997c, 0x00000000},
+       {0x00009980, 0x00000000},
+       {0x00009984, 0x00000000},
+       {0x00009988, 0x00000000},
+       {0x0000998c, 0x00000000},
+       {0x00009990, 0x00000000},
+       {0x00009994, 0x00000000},
+       {0x00009998, 0x00000000},
+       {0x0000999c, 0x00000000},
+       {0x000099a0, 0x00000000},
+       {0x000099a4, 0x00000001},
+       {0x000099a8, 0x201fff00},
+       {0x000099ac, 0x2def0400},
+       {0x000099b0, 0x03051000},
+       {0x000099b4, 0x00000820},
+       {0x000099dc, 0x00000000},
+       {0x000099e0, 0x00000000},
+       {0x000099e4, 0xaaaaaaaa},
+       {0x000099e8, 0x3c466478},
+       {0x000099ec, 0x0cc80caa},
+       {0x000099f0, 0x00000000},
+       {0x0000a208, 0x803e68c8},
+       {0x0000a210, 0x4080a333},
+       {0x0000a214, 0x00206c10},
+       {0x0000a218, 0x009c4060},
+       {0x0000a220, 0x01834061},
+       {0x0000a224, 0x00000400},
+       {0x0000a228, 0x000003b5},
+       {0x0000a22c, 0x00000000},
+       {0x0000a234, 0x20202020},
+       {0x0000a238, 0x20202020},
+       {0x0000a244, 0x00000000},
+       {0x0000a248, 0xfffffffc},
+       {0x0000a24c, 0x00000000},
+       {0x0000a254, 0x00000000},
+       {0x0000a258, 0x0ccb5380},
+       {0x0000a25c, 0x15151501},
+       {0x0000a260, 0xdfa90f01},
+       {0x0000a268, 0x00000000},
+       {0x0000a26c, 0x0ebae9e6},
+       {0x0000a388, 0x0c000000},
+       {0x0000a38c, 0x20202020},
+       {0x0000a390, 0x20202020},
+       {0x0000a39c, 0x00000001},
+       {0x0000a3a0, 0x00000000},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0x00000000},
+       {0x0000a3ac, 0x00000000},
+       {0x0000a3b0, 0x00000000},
+       {0x0000a3b4, 0x00000000},
+       {0x0000a3b8, 0x00000000},
+       {0x0000a3bc, 0x00000000},
+       {0x0000a3c0, 0x00000000},
+       {0x0000a3c4, 0x00000000},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3e4, 0x00000000},
+       {0x0000a3e8, 0x18c43433},
+       {0x0000a3ec, 0x00f70081},
+       {0x0000a3f0, 0x01036a2f},
+       {0x0000a3f4, 0x00000000},
+       {0x0000d270, 0x0d820820},
+       {0x0000d35c, 0x07ffffef},
+       {0x0000d360, 0x0fffffe7},
+       {0x0000d364, 0x17ffffe5},
+       {0x0000d368, 0x1fffffe4},
+       {0x0000d36c, 0x37ffffe3},
+       {0x0000d370, 0x3fffffe3},
+       {0x0000d374, 0x57ffffe3},
+       {0x0000d378, 0x5fffffe2},
+       {0x0000d37c, 0x7fffffe2},
+       {0x0000d380, 0x7f3c7bba},
+       {0x0000d384, 0xf3307ff0},
+};
+
+static const u32 ar9271Modes_9271_ANI_reg[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+       {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+       {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881},
+       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8},
+       {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+};
+
+static const u32 ar9271Modes_normal_power_tx_gain_9271[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+       {0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610},
+       {0x0000a314, 0x00000000, 0x00000000, 0x00024650, 0x00024650},
+       {0x0000a318, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x000316d2, 0x000316d2},
+       {0x0000a320, 0x00000000, 0x00000000, 0x00039758, 0x00039758},
+       {0x0000a324, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759},
+       {0x0000a328, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e},
+       {0x0000a334, 0x000368de, 0x000368de, 0x0004979f, 0x0004979f},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0004d7df, 0x0004d7df},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029},
+       {0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff},
+       {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+       {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+       {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21c652, 0x0a21c652},
+       {0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+       {0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd},
+       {0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+       {0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
+       {0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+       {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
+};
+
+static const u32 ar9271Modes_high_power_tx_gain_9271[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240},
+       {0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600},
+       {0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802},
+       {0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805},
+       {0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41},
+       {0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80},
+       {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b},
+       {0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff},
+       {0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba},
+       {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+       {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652},
+       {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063},
+       {0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
+       {0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
+       {0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
+       {0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
+};
+
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9002_mac.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9002_mac.c
new file mode 100644 (file)
index 0000000..bb2bfac
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include <linux/export.h>
+
+#define AR_BufLen           0x00000fff
+
+static void ar9002_hw_rx_enable(struct ath_hw *ah)
+{
+       REG_WRITE(ah, AR_CR, AR_CR_RXE);
+}
+
+static void ar9002_hw_set_desc_link(void *ds, u32 ds_link)
+{
+       ((struct ath_desc*) ds)->ds_link = ds_link;
+}
+
+static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
+{
+       u32 isr = 0;
+       u32 mask2 = 0;
+       struct ath9k_hw_capabilities *pCap = &ah->caps;
+       u32 sync_cause = 0;
+       bool fatal_int = false;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (!AR_SREV_9100(ah)) {
+               if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
+                       if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
+                           == AR_RTC_STATUS_ON) {
+                               isr = REG_READ(ah, AR_ISR);
+                       }
+               }
+
+               sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
+                       AR_INTR_SYNC_DEFAULT;
+
+               *masked = 0;
+
+               if (!isr && !sync_cause)
+                       return false;
+       } else {
+               *masked = 0;
+               isr = REG_READ(ah, AR_ISR);
+       }
+
+       if (isr) {
+               if (isr & AR_ISR_BCNMISC) {
+                       u32 isr2;
+                       isr2 = REG_READ(ah, AR_ISR_S2);
+                       if (isr2 & AR_ISR_S2_TIM)
+                               mask2 |= ATH9K_INT_TIM;
+                       if (isr2 & AR_ISR_S2_DTIM)
+                               mask2 |= ATH9K_INT_DTIM;
+                       if (isr2 & AR_ISR_S2_DTIMSYNC)
+                               mask2 |= ATH9K_INT_DTIMSYNC;
+                       if (isr2 & (AR_ISR_S2_CABEND))
+                               mask2 |= ATH9K_INT_CABEND;
+                       if (isr2 & AR_ISR_S2_GTT)
+                               mask2 |= ATH9K_INT_GTT;
+                       if (isr2 & AR_ISR_S2_CST)
+                               mask2 |= ATH9K_INT_CST;
+                       if (isr2 & AR_ISR_S2_TSFOOR)
+                               mask2 |= ATH9K_INT_TSFOOR;
+               }
+
+               isr = REG_READ(ah, AR_ISR_RAC);
+               if (isr == 0xffffffff) {
+                       *masked = 0;
+                       return false;
+               }
+
+               *masked = isr & ATH9K_INT_COMMON;
+
+               if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM |
+                          AR_ISR_RXOK | AR_ISR_RXERR))
+                       *masked |= ATH9K_INT_RX;
+
+               if (isr &
+                   (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
+                    AR_ISR_TXEOL)) {
+                       u32 s0_s, s1_s;
+
+                       *masked |= ATH9K_INT_TX;
+
+                       s0_s = REG_READ(ah, AR_ISR_S0_S);
+                       ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
+                       ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
+
+                       s1_s = REG_READ(ah, AR_ISR_S1_S);
+                       ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
+                       ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
+               }
+
+               if (isr & AR_ISR_RXORN) {
+                       ath_dbg(common, INTERRUPT,
+                               "receive FIFO overrun interrupt\n");
+               }
+
+               *masked |= mask2;
+       }
+
+       if (AR_SREV_9100(ah))
+               return true;
+
+       if (isr & AR_ISR_GENTMR) {
+               u32 s5_s;
+
+               s5_s = REG_READ(ah, AR_ISR_S5_S);
+               ah->intr_gen_timer_trigger =
+                               MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
+
+               ah->intr_gen_timer_thresh =
+                       MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
+
+               if (ah->intr_gen_timer_trigger)
+                       *masked |= ATH9K_INT_GENTIMER;
+
+               if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
+                   !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+                       *masked |= ATH9K_INT_TIM_TIMER;
+       }
+
+       if (sync_cause) {
+               fatal_int =
+                       (sync_cause &
+                        (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
+                       ? true : false;
+
+               if (fatal_int) {
+                       if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
+                               ath_dbg(common, ANY,
+                                       "received PCI FATAL interrupt\n");
+                       }
+                       if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
+                               ath_dbg(common, ANY,
+                                       "received PCI PERR interrupt\n");
+                       }
+                       *masked |= ATH9K_INT_FATAL;
+               }
+               if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
+                       ath_dbg(common, INTERRUPT,
+                               "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
+                       REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
+                       REG_WRITE(ah, AR_RC, 0);
+                       *masked |= ATH9K_INT_FATAL;
+               }
+               if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
+                       ath_dbg(common, INTERRUPT,
+                               "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
+               }
+
+               REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
+               (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
+       }
+
+       return true;
+}
+
+static void
+ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       u32 ctl1, ctl6;
+
+       ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+       ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+       ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+       ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+       ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+
+       ACCESS_ONCE(ads->ds_link) = i->link;
+       ACCESS_ONCE(ads->ds_data) = i->buf_addr[0];
+
+       ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore);
+       ctl6 = SM(i->keytype, AR_EncrType);
+
+       if (AR_SREV_9285(ah)) {
+               ads->ds_ctl8 = 0;
+               ads->ds_ctl9 = 0;
+               ads->ds_ctl10 = 0;
+               ads->ds_ctl11 = 0;
+       }
+
+       if ((i->is_first || i->is_last) &&
+           i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) {
+               ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0)
+                       | set11nTries(i->rates, 1)
+                       | set11nTries(i->rates, 2)
+                       | set11nTries(i->rates, 3)
+                       | (i->dur_update ? AR_DurUpdateEna : 0)
+                       | SM(0, AR_BurstDur);
+
+               ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0)
+                       | set11nRate(i->rates, 1)
+                       | set11nRate(i->rates, 2)
+                       | set11nRate(i->rates, 3);
+       } else {
+               ACCESS_ONCE(ads->ds_ctl2) = 0;
+               ACCESS_ONCE(ads->ds_ctl3) = 0;
+       }
+
+       if (!i->is_first) {
+               ACCESS_ONCE(ads->ds_ctl0) = 0;
+               ACCESS_ONCE(ads->ds_ctl1) = ctl1;
+               ACCESS_ONCE(ads->ds_ctl6) = ctl6;
+               return;
+       }
+
+       ctl1 |= (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0)
+               | SM(i->type, AR_FrameType)
+               | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+               | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+               | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+       switch (i->aggr) {
+       case AGGR_BUF_FIRST:
+               ctl6 |= SM(i->aggr_len, AR_AggrLen);
+               /* fall through */
+       case AGGR_BUF_MIDDLE:
+               ctl1 |= AR_IsAggr | AR_MoreAggr;
+               ctl6 |= SM(i->ndelim, AR_PadDelim);
+               break;
+       case AGGR_BUF_LAST:
+               ctl1 |= AR_IsAggr;
+               break;
+       case AGGR_BUF_NONE:
+               break;
+       }
+
+       ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
+               | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+               | SM(i->txpower, AR_XmitPower)
+               | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+               | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+               | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+               | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+               | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
+                  (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
+
+       ACCESS_ONCE(ads->ds_ctl1) = ctl1;
+       ACCESS_ONCE(ads->ds_ctl6) = ctl6;
+
+       if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST)
+               return;
+
+       ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0)
+               | set11nPktDurRTSCTS(i->rates, 1);
+
+       ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2)
+               | set11nPktDurRTSCTS(i->rates, 3);
+
+       ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0)
+               | set11nRateFlags(i->rates, 1)
+               | set11nRateFlags(i->rates, 2)
+               | set11nRateFlags(i->rates, 3)
+               | SM(i->rtscts_rate, AR_RTSCTSRate);
+}
+
+static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
+                                struct ath_tx_status *ts)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       u32 status;
+
+       status = ACCESS_ONCE(ads->ds_txstatus9);
+       if ((status & AR_TxDone) == 0)
+               return -EINPROGRESS;
+
+       ts->ts_tstamp = ads->AR_SendTimestamp;
+       ts->ts_status = 0;
+       ts->ts_flags = 0;
+
+       if (status & AR_TxOpExceeded)
+               ts->ts_status |= ATH9K_TXERR_XTXOP;
+       ts->tid = MS(status, AR_TxTid);
+       ts->ts_rateindex = MS(status, AR_FinalTxIdx);
+       ts->ts_seqnum = MS(status, AR_SeqNum);
+
+       status = ACCESS_ONCE(ads->ds_txstatus0);
+       ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
+       ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
+       ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
+       if (status & AR_TxBaStatus) {
+               ts->ts_flags |= ATH9K_TX_BA;
+               ts->ba_low = ads->AR_BaBitmapLow;
+               ts->ba_high = ads->AR_BaBitmapHigh;
+       }
+
+       status = ACCESS_ONCE(ads->ds_txstatus1);
+       if (status & AR_FrmXmitOK)
+               ts->ts_status |= ATH9K_TX_ACKED;
+       else {
+               if (status & AR_ExcessiveRetries)
+                       ts->ts_status |= ATH9K_TXERR_XRETRY;
+               if (status & AR_Filtered)
+                       ts->ts_status |= ATH9K_TXERR_FILT;
+               if (status & AR_FIFOUnderrun) {
+                       ts->ts_status |= ATH9K_TXERR_FIFO;
+                       ath9k_btcoex_ath9k_hw_updatetxtriglevel(ah, true);
+               }
+       }
+       if (status & AR_TxTimerExpired)
+               ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+       if (status & AR_DescCfgErr)
+               ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+       if (status & AR_TxDataUnderrun) {
+               ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+               ath9k_btcoex_ath9k_hw_updatetxtriglevel(ah, true);
+       }
+       if (status & AR_TxDelimUnderrun) {
+               ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+               ath9k_btcoex_ath9k_hw_updatetxtriglevel(ah, true);
+       }
+       ts->ts_shortretry = MS(status, AR_RTSFailCnt);
+       ts->ts_longretry = MS(status, AR_DataFailCnt);
+       ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
+
+       status = ACCESS_ONCE(ads->ds_txstatus5);
+       ts->ts_rssi = MS(status, AR_TxRSSICombined);
+       ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
+       ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+       ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
+
+       ts->evm0 = ads->AR_TxEVM0;
+       ts->evm1 = ads->AR_TxEVM1;
+       ts->evm2 = ads->AR_TxEVM2;
+
+       return 0;
+}
+
+void ath9k_btcoex_ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
+                         u32 size, u32 flags)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       ads->ds_ctl1 = size & AR_BufLen;
+       if (flags & ATH9K_RXDESC_INTREQ)
+               ads->ds_ctl1 |= AR_RxIntrReq;
+
+       memset(&ads->u.rx, 0, sizeof(ads->u.rx));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_setuprxdesc);
+
+void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
+{
+       struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+       ops->rx_enable = ar9002_hw_rx_enable;
+       ops->set_desc_link = ar9002_hw_set_desc_link;
+       ops->get_isr = ar9002_hw_get_isr;
+       ops->set_txdesc = ar9002_set_txdesc;
+       ops->proc_txdesc = ar9002_hw_proc_txdesc;
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9002_phy.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9002_phy.c
new file mode 100644 (file)
index 0000000..3cbbb03
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Programming Atheros 802.11n analog front end radios
+ *
+ * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express
+ * devices have either an external AR2133 analog front end radio for single
+ * band 2.4 GHz communication or an AR5133 analog front end radio for dual
+ * band 2.4 GHz / 5 GHz communication.
+ *
+ * All devices after the AR5416 and AR5418 family starting with the AR9280
+ * have their analog front radios, MAC/BB and host PCIe/USB interface embedded
+ * into a single-chip and require less programming.
+ *
+ * The following single-chips exist with a respective embedded radio:
+ *
+ * AR9280 - 11n dual-band 2x2 MIMO for PCIe
+ * AR9281 - 11n single-band 1x2 MIMO for PCIe
+ * AR9285 - 11n single-band 1x1 for PCIe
+ * AR9287 - 11n single-band 2x2 MIMO for PCIe
+ *
+ * AR9220 - 11n dual-band 2x2 MIMO for PCI
+ * AR9223 - 11n single-band 2x2 MIMO for PCI
+ *
+ * AR9287 - 11n single-band 1x1 MIMO for USB
+ */
+
+#include "hw.h"
+#include "ar9002_phy.h"
+
+/**
+ * ar9002_hw_set_channel - set channel on single-chip device
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * This is the function to change channel on single-chip devices, that is
+ * all devices after ar9280.
+ *
+ * This function takes the channel value in MHz and sets
+ * hardware channel value. Assumes writes have been enabled to analog bus.
+ *
+ * Actual Expression,
+ *
+ * For 2GHz channel,
+ * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
+ * (freq_ref = 40MHz)
+ *
+ * For 5GHz channel,
+ * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
+ * (freq_ref = 40MHz/(24>>amodeRefSel))
+ */
+static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       u16 bMode, fracMode, aModeRefSel = 0;
+       u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
+       struct chan_centers centers;
+       u32 refDivA = 24;
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       freq = centers.synth_center;
+
+       reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
+       reg32 &= 0xc0000000;
+
+       if (freq < 4800) { /* 2 GHz, fractional mode */
+               u32 txctl;
+               int regWrites = 0;
+
+               bMode = 1;
+               fracMode = 1;
+               aModeRefSel = 0;
+               channelSel = CHANSEL_2G(freq);
+
+               if (AR_SREV_9287_11_OR_LATER(ah)) {
+                       if (freq == 2484) {
+                               /* Enable channel spreading for channel 14 */
+                               REG_WRITE_ARRAY(&ah->iniCckfirJapan2484,
+                                               1, regWrites);
+                       } else {
+                               REG_WRITE_ARRAY(&ah->iniCckfirNormal,
+                                               1, regWrites);
+                       }
+               } else {
+                       txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+                       if (freq == 2484) {
+                               /* Enable channel spreading for channel 14 */
+                               REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                                         txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+                       } else {
+                               REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                                         txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
+                       }
+               }
+       } else {
+               bMode = 0;
+               fracMode = 0;
+
+               switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
+               case 0:
+                       if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
+                               aModeRefSel = 0;
+                       else if ((freq % 20) == 0)
+                               aModeRefSel = 3;
+                       else if ((freq % 10) == 0)
+                               aModeRefSel = 2;
+                       if (aModeRefSel)
+                               break;
+               case 1:
+               default:
+                       aModeRefSel = 0;
+                       /*
+                        * Enable 2G (fractional) mode for channels
+                        * which are 5MHz spaced.
+                        */
+                       fracMode = 1;
+                       refDivA = 1;
+                       channelSel = CHANSEL_5G(freq);
+
+                       /* RefDivA setting */
+                       ath9k_hw_analog_shift_rmw(ah, AR_AN_SYNTH9,
+                                     AR_AN_SYNTH9_REFDIVA,
+                                     AR_AN_SYNTH9_REFDIVA_S, refDivA);
+
+               }
+
+               if (!fracMode) {
+                       ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
+                       channelSel = ndiv & 0x1ff;
+                       channelFrac = (ndiv & 0xfffffe00) * 2;
+                       channelSel = (channelSel << 17) | channelFrac;
+               }
+       }
+
+       reg32 = reg32 |
+           (bMode << 29) |
+           (fracMode << 28) | (aModeRefSel << 26) | (channelSel);
+
+       REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
+
+       ah->curchan = chan;
+       ah->curchan_rad_index = -1;
+
+       return 0;
+}
+
+/**
+ * ar9002_hw_spur_mitigate - convert baseband spur frequency
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For single-chip solutions. Converts to baseband spur frequency given the
+ * input channel frequency and compute register settings below.
+ */
+static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
+                                   struct ath9k_channel *chan)
+{
+       int bb_spur = AR_NO_SPUR;
+       int freq;
+       int bin, cur_bin;
+       int bb_spur_off, spur_subchannel_sd;
+       int spur_freq_sd;
+       int spur_delta_phase;
+       int denominator;
+       int upper, lower, cur_vit_mask;
+       int tmp, newVal;
+       int i;
+       static const int pilot_mask_reg[4] = {
+               AR_PHY_TIMING7, AR_PHY_TIMING8,
+               AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+       };
+       static const int chan_mask_reg[4] = {
+               AR_PHY_TIMING9, AR_PHY_TIMING10,
+               AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+       };
+       static const int inc[4] = { 0, 100, 0, 0 };
+       struct chan_centers centers;
+
+       int8_t mask_m[123];
+       int8_t mask_p[123];
+       int8_t mask_amt;
+       int tmp_mask;
+       int cur_bb_spur;
+       bool is2GHz = IS_CHAN_2GHZ(chan);
+
+       memset(&mask_m, 0, sizeof(int8_t) * 123);
+       memset(&mask_p, 0, sizeof(int8_t) * 123);
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       freq = centers.synth_center;
+
+       ah->config.spurmode = SPUR_ENABLE_EEPROM;
+       for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+               cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
+
+               if (AR_NO_SPUR == cur_bb_spur)
+                       break;
+
+               if (is2GHz)
+                       cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
+               else
+                       cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
+
+               cur_bb_spur = cur_bb_spur - freq;
+
+               if (IS_CHAN_HT40(chan)) {
+                       if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
+                           (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
+                               bb_spur = cur_bb_spur;
+                               break;
+                       }
+               } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
+                          (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
+                       bb_spur = cur_bb_spur;
+                       break;
+               }
+       }
+
+       if (AR_NO_SPUR == bb_spur) {
+               REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
+                           AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+               return;
+       } else {
+               REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
+                           AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+       }
+
+       bin = bb_spur * 320;
+
+       tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+                       AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+                       AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+                       AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+       REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
+
+       newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+                 AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+                 AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+                 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+                 SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+       REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
+
+       if (IS_CHAN_HT40(chan)) {
+               if (bb_spur < 0) {
+                       spur_subchannel_sd = 1;
+                       bb_spur_off = bb_spur + 10;
+               } else {
+                       spur_subchannel_sd = 0;
+                       bb_spur_off = bb_spur - 10;
+               }
+       } else {
+               spur_subchannel_sd = 0;
+               bb_spur_off = bb_spur;
+       }
+
+       if (IS_CHAN_HT40(chan))
+               spur_delta_phase =
+                       ((bb_spur * 262144) /
+                        10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+       else
+               spur_delta_phase =
+                       ((bb_spur * 524288) /
+                        10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+       denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
+       spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
+
+       newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+                 SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+                 SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+       REG_WRITE(ah, AR_PHY_TIMING11, newVal);
+
+       newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
+       REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
+
+       cur_bin = -6000;
+       upper = bin + 100;
+       lower = bin - 100;
+
+       for (i = 0; i < 4; i++) {
+               int pilot_mask = 0;
+               int chan_mask = 0;
+               int bp = 0;
+               for (bp = 0; bp < 30; bp++) {
+                       if ((cur_bin > lower) && (cur_bin < upper)) {
+                               pilot_mask = pilot_mask | 0x1 << bp;
+                               chan_mask = chan_mask | 0x1 << bp;
+                       }
+                       cur_bin += 100;
+               }
+               cur_bin += inc[i];
+               REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+               REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+       }
+
+       cur_vit_mask = 6100;
+       upper = bin + 120;
+       lower = bin - 120;
+
+       for (i = 0; i < 123; i++) {
+               if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+
+                       /* workaround for gcc bug #37014 */
+                       volatile int tmp_v = abs(cur_vit_mask - bin);
+
+                       if (tmp_v < 75)
+                               mask_amt = 1;
+                       else
+                               mask_amt = 0;
+                       if (cur_vit_mask < 0)
+                               mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+                       else
+                               mask_p[cur_vit_mask / 100] = mask_amt;
+               }
+               cur_vit_mask -= 100;
+       }
+
+       tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+               | (mask_m[48] << 26) | (mask_m[49] << 24)
+               | (mask_m[50] << 22) | (mask_m[51] << 20)
+               | (mask_m[52] << 18) | (mask_m[53] << 16)
+               | (mask_m[54] << 14) | (mask_m[55] << 12)
+               | (mask_m[56] << 10) | (mask_m[57] << 8)
+               | (mask_m[58] << 6) | (mask_m[59] << 4)
+               | (mask_m[60] << 2) | (mask_m[61] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+       REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+       tmp_mask = (mask_m[31] << 28)
+               | (mask_m[32] << 26) | (mask_m[33] << 24)
+               | (mask_m[34] << 22) | (mask_m[35] << 20)
+               | (mask_m[36] << 18) | (mask_m[37] << 16)
+               | (mask_m[48] << 14) | (mask_m[39] << 12)
+               | (mask_m[40] << 10) | (mask_m[41] << 8)
+               | (mask_m[42] << 6) | (mask_m[43] << 4)
+               | (mask_m[44] << 2) | (mask_m[45] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+       tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+               | (mask_m[18] << 26) | (mask_m[18] << 24)
+               | (mask_m[20] << 22) | (mask_m[20] << 20)
+               | (mask_m[22] << 18) | (mask_m[22] << 16)
+               | (mask_m[24] << 14) | (mask_m[24] << 12)
+               | (mask_m[25] << 10) | (mask_m[26] << 8)
+               | (mask_m[27] << 6) | (mask_m[28] << 4)
+               | (mask_m[29] << 2) | (mask_m[30] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+       tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
+               | (mask_m[2] << 26) | (mask_m[3] << 24)
+               | (mask_m[4] << 22) | (mask_m[5] << 20)
+               | (mask_m[6] << 18) | (mask_m[7] << 16)
+               | (mask_m[8] << 14) | (mask_m[9] << 12)
+               | (mask_m[10] << 10) | (mask_m[11] << 8)
+               | (mask_m[12] << 6) | (mask_m[13] << 4)
+               | (mask_m[14] << 2) | (mask_m[15] << 0);
+       REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+       tmp_mask = (mask_p[15] << 28)
+               | (mask_p[14] << 26) | (mask_p[13] << 24)
+               | (mask_p[12] << 22) | (mask_p[11] << 20)
+               | (mask_p[10] << 18) | (mask_p[9] << 16)
+               | (mask_p[8] << 14) | (mask_p[7] << 12)
+               | (mask_p[6] << 10) | (mask_p[5] << 8)
+               | (mask_p[4] << 6) | (mask_p[3] << 4)
+               | (mask_p[2] << 2) | (mask_p[1] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+       tmp_mask = (mask_p[30] << 28)
+               | (mask_p[29] << 26) | (mask_p[28] << 24)
+               | (mask_p[27] << 22) | (mask_p[26] << 20)
+               | (mask_p[25] << 18) | (mask_p[24] << 16)
+               | (mask_p[23] << 14) | (mask_p[22] << 12)
+               | (mask_p[21] << 10) | (mask_p[20] << 8)
+               | (mask_p[19] << 6) | (mask_p[18] << 4)
+               | (mask_p[17] << 2) | (mask_p[16] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+       tmp_mask = (mask_p[45] << 28)
+               | (mask_p[44] << 26) | (mask_p[43] << 24)
+               | (mask_p[42] << 22) | (mask_p[41] << 20)
+               | (mask_p[40] << 18) | (mask_p[39] << 16)
+               | (mask_p[38] << 14) | (mask_p[37] << 12)
+               | (mask_p[36] << 10) | (mask_p[35] << 8)
+               | (mask_p[34] << 6) | (mask_p[33] << 4)
+               | (mask_p[32] << 2) | (mask_p[31] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+       tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+               | (mask_p[59] << 26) | (mask_p[58] << 24)
+               | (mask_p[57] << 22) | (mask_p[56] << 20)
+               | (mask_p[55] << 18) | (mask_p[54] << 16)
+               | (mask_p[53] << 14) | (mask_p[52] << 12)
+               | (mask_p[51] << 10) | (mask_p[50] << 8)
+               | (mask_p[49] << 6) | (mask_p[48] << 4)
+               | (mask_p[47] << 2) | (mask_p[46] << 0);
+       REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+       REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static void ar9002_olc_init(struct ath_hw *ah)
+{
+       u32 i;
+
+       if (!OLC_FOR_AR9280_20_LATER)
+               return;
+
+       if (OLC_FOR_AR9287_10_LATER) {
+               REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9,
+                               AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
+               ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0,
+                               AR9287_AN_TXPC0_TXPCMODE,
+                               AR9287_AN_TXPC0_TXPCMODE_S,
+                               AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE);
+               udelay(100);
+       } else {
+               for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
+                       ah->originalGain[i] =
+                               MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
+                                               AR_PHY_TX_GAIN);
+               ah->PDADCdelta = 0;
+       }
+}
+
+static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
+                                        struct ath9k_channel *chan)
+{
+       int ref_div = 5;
+       int pll_div = 0x2c;
+       u32 pll;
+
+       if (chan && IS_CHAN_5GHZ(chan) && !IS_CHAN_A_FAST_CLOCK(ah, chan)) {
+               if (AR_SREV_9280_20(ah)) {
+                       ref_div = 10;
+                       pll_div = 0x50;
+               } else {
+                       pll_div = 0x28;
+               }
+       }
+
+       pll = SM(ref_div, AR_RTC_9160_PLL_REFDIV);
+       pll |= SM(pll_div, AR_RTC_9160_PLL_DIV);
+
+       if (chan && IS_CHAN_HALF_RATE(chan))
+               pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+       else if (chan && IS_CHAN_QUARTER_RATE(chan))
+               pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
+
+       return pll;
+}
+
+static void ar9002_hw_do_getnf(struct ath_hw *ah,
+                             int16_t nfarray[NUM_NF_READINGS])
+{
+       int16_t nf;
+
+       nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
+       nfarray[0] = sign_extend32(nf, 8);
+
+       nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
+       if (IS_CHAN_HT40(ah->curchan))
+               nfarray[3] = sign_extend32(nf, 8);
+
+       if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+               return;
+
+       nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
+       nfarray[1] = sign_extend32(nf, 8);
+
+       nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
+       if (IS_CHAN_HT40(ah->curchan))
+               nfarray[4] = sign_extend32(nf, 8);
+}
+
+static void ar9002_hw_set_nf_limits(struct ath_hw *ah)
+{
+       if (AR_SREV_9285(ah)) {
+               ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ;
+               ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ;
+               ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ;
+       } else if (AR_SREV_9287(ah)) {
+               ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ;
+               ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ;
+               ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9287_2GHZ;
+       } else if (AR_SREV_9271(ah)) {
+               ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ;
+               ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ;
+               ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9271_2GHZ;
+       } else {
+               ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ;
+               ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ;
+               ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ;
+               ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ;
+               ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ;
+               ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ;
+       }
+}
+
+static void ar9002_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+                                  struct ath_hw_antcomb_conf *antconf)
+{
+       u32 regval;
+
+       regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+       antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >>
+                                 AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S;
+       antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >>
+                                AR_PHY_9285_ANT_DIV_ALT_LNACONF_S;
+       antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >>
+                                 AR_PHY_9285_FAST_DIV_BIAS_S;
+       antconf->lna1_lna2_delta = -3;
+       antconf->div_group = 0;
+}
+
+static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah,
+                                  struct ath_hw_antcomb_conf *antconf)
+{
+       u32 regval;
+
+       regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+       regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF |
+                   AR_PHY_9285_ANT_DIV_ALT_LNACONF |
+                   AR_PHY_9285_FAST_DIV_BIAS);
+       regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S)
+                  & AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
+       regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S)
+                  & AR_PHY_9285_ANT_DIV_ALT_LNACONF);
+       regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S)
+                  & AR_PHY_9285_FAST_DIV_BIAS);
+
+       REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
+}
+
+void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
+{
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+       struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+       priv_ops->set_rf_regs = NULL;
+       priv_ops->rf_alloc_ext_banks = NULL;
+       priv_ops->rf_free_ext_banks = NULL;
+       priv_ops->rf_set_freq = ar9002_hw_set_channel;
+       priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate;
+       priv_ops->olc_init = ar9002_olc_init;
+       priv_ops->compute_pll_control = ar9002_hw_compute_pll_control;
+       priv_ops->do_getnf = ar9002_hw_do_getnf;
+
+       ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get;
+       ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set;
+
+       ar9002_hw_set_nf_limits(ah);
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9002_phy.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9002_phy.h
new file mode 100644 (file)
index 0000000..f9eb2c3
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef AR9002_PHY_H
+#define AR9002_PHY_H
+
+#define AR_PHY_TEST             0x9800
+#define PHY_AGC_CLR             0x10000000
+#define RFSILENT_BB             0x00002000
+
+#define AR_PHY_TURBO                0x9804
+#define AR_PHY_FC_TURBO_MODE        0x00000001
+#define AR_PHY_FC_TURBO_SHORT       0x00000002
+#define AR_PHY_FC_DYN2040_EN        0x00000004
+#define AR_PHY_FC_DYN2040_PRI_ONLY  0x00000008
+#define AR_PHY_FC_DYN2040_PRI_CH    0x00000010
+/* For 25 MHz channel spacing -- not used but supported by hw */
+#define AR_PHY_FC_DYN2040_EXT_CH    0x00000020
+#define AR_PHY_FC_HT_EN             0x00000040
+#define AR_PHY_FC_SHORT_GI_40       0x00000080
+#define AR_PHY_FC_WALSH             0x00000100
+#define AR_PHY_FC_SINGLE_HT_LTF1    0x00000200
+#define AR_PHY_FC_ENABLE_DAC_FIFO   0x00000800
+
+#define AR_PHY_TEST2                   0x9808
+
+#define AR_PHY_TIMING2           0x9810
+#define AR_PHY_TIMING3           0x9814
+#define AR_PHY_TIMING3_DSC_MAN   0xFFFE0000
+#define AR_PHY_TIMING3_DSC_MAN_S 17
+#define AR_PHY_TIMING3_DSC_EXP   0x0001E000
+#define AR_PHY_TIMING3_DSC_EXP_S 13
+
+#define AR_PHY_CHIP_ID_REV_0      0x80
+#define AR_PHY_CHIP_ID_REV_1      0x81
+#define AR_PHY_CHIP_ID_9160_REV_0 0xb0
+
+#define AR_PHY_ACTIVE       0x981C
+#define AR_PHY_ACTIVE_EN    0x00000001
+#define AR_PHY_ACTIVE_DIS   0x00000000
+
+#define AR_PHY_RF_CTL2             0x9824
+#define AR_PHY_TX_END_DATA_START   0x000000FF
+#define AR_PHY_TX_END_DATA_START_S 0
+#define AR_PHY_TX_END_PA_ON        0x0000FF00
+#define AR_PHY_TX_END_PA_ON_S      8
+
+#define AR_PHY_RF_CTL3                  0x9828
+#define AR_PHY_TX_END_TO_A2_RX_ON       0x00FF0000
+#define AR_PHY_TX_END_TO_A2_RX_ON_S     16
+#define AR_PHY_TX_END_TO_ADC_ON         0xFF000000
+#define AR_PHY_TX_END_TO_ADC_ON_S       24
+
+#define AR_PHY_ADC_CTL                  0x982C
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN    0x00000003
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S  0
+#define AR_PHY_ADC_CTL_OFF_PWDDAC       0x00002000
+#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP   0x00004000
+#define AR_PHY_ADC_CTL_OFF_PWDADC       0x00008000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN     0x00030000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S   16
+
+#define AR_PHY_ADC_SERIAL_CTL       0x9830
+#define AR_PHY_SEL_INTERNAL_ADDAC   0x00000000
+#define AR_PHY_SEL_EXTERNAL_RADIO   0x00000001
+
+#define AR_PHY_RF_CTL4                    0x9834
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF    0xFF000000
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S  24
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF    0x00FF0000
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S  16
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON      0x0000FF00
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S    8
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON      0x000000FF
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S    0
+
+#define AR_PHY_TSTDAC_CONST               0x983c
+
+#define AR_PHY_SETTLING          0x9844
+#define AR_PHY_SETTLING_SWITCH   0x00003F80
+#define AR_PHY_SETTLING_SWITCH_S 7
+
+#define AR_PHY_RXGAIN                   0x9848
+#define AR_PHY_RXGAIN_TXRX_ATTEN        0x0003F000
+#define AR_PHY_RXGAIN_TXRX_ATTEN_S      12
+#define AR_PHY_RXGAIN_TXRX_RF_MAX       0x007C0000
+#define AR_PHY_RXGAIN_TXRX_RF_MAX_S     18
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN    0x00003F80
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S  7
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN   0x001FC000
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
+
+#define AR_PHY_DESIRED_SZ           0x9850
+#define AR_PHY_DESIRED_SZ_ADC       0x000000FF
+#define AR_PHY_DESIRED_SZ_ADC_S     0
+#define AR_PHY_DESIRED_SZ_PGA       0x0000FF00
+#define AR_PHY_DESIRED_SZ_PGA_S     8
+#define AR_PHY_DESIRED_SZ_TOT_DES   0x0FF00000
+#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
+
+#define AR_PHY_FIND_SIG           0x9858
+#define AR_PHY_FIND_SIG_FIRSTEP   0x0003F000
+#define AR_PHY_FIND_SIG_FIRSTEP_S 12
+#define AR_PHY_FIND_SIG_FIRPWR    0x03FC0000
+#define AR_PHY_FIND_SIG_FIRPWR_S  18
+
+#define AR_PHY_FIND_SIG_LOW           0x9840
+#define AR_PHY_FIND_SIG_FIRSTEP_LOW   0x00000FC0L
+#define AR_PHY_FIND_SIG_FIRSTEP_LOW_S 6
+
+#define AR_PHY_AGC_CTL1                  0x985C
+#define AR_PHY_AGC_CTL1_COARSE_LOW       0x00007F80
+#define AR_PHY_AGC_CTL1_COARSE_LOW_S     7
+#define AR_PHY_AGC_CTL1_COARSE_HIGH      0x003F8000
+#define AR_PHY_AGC_CTL1_COARSE_HIGH_S    15
+
+#define AR_PHY_CCA                  0x9864
+#define AR_PHY_MINCCA_PWR           0x0FF80000
+#define AR_PHY_MINCCA_PWR_S         19
+#define AR_PHY_CCA_THRESH62         0x0007F000
+#define AR_PHY_CCA_THRESH62_S       12
+#define AR9280_PHY_MINCCA_PWR       0x1FF00000
+#define AR9280_PHY_MINCCA_PWR_S     20
+#define AR9280_PHY_CCA_THRESH62     0x000FF000
+#define AR9280_PHY_CCA_THRESH62_S   12
+
+#define AR_PHY_SFCORR_LOW                    0x986C
+#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW  0x00000001
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW    0x00003F00
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S  8
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW      0x001FC000
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S    14
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW      0x0FE00000
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S    21
+
+#define AR_PHY_SFCORR                0x9868
+#define AR_PHY_SFCORR_M2COUNT_THR    0x0000001F
+#define AR_PHY_SFCORR_M2COUNT_THR_S  0
+#define AR_PHY_SFCORR_M1_THRESH      0x00FE0000
+#define AR_PHY_SFCORR_M1_THRESH_S    17
+#define AR_PHY_SFCORR_M2_THRESH      0x7F000000
+#define AR_PHY_SFCORR_M2_THRESH_S    24
+
+#define AR_PHY_SLEEP_CTR_CONTROL    0x9870
+#define AR_PHY_SLEEP_CTR_LIMIT      0x9874
+#define AR_PHY_SYNTH_CONTROL        0x9874
+#define AR_PHY_SLEEP_SCAL           0x9878
+
+#define AR_PHY_PLL_CTL          0x987c
+#define AR_PHY_PLL_CTL_40       0xaa
+#define AR_PHY_PLL_CTL_40_5413  0x04
+#define AR_PHY_PLL_CTL_44       0xab
+#define AR_PHY_PLL_CTL_44_2133  0xeb
+#define AR_PHY_PLL_CTL_40_2133  0xea
+
+#define AR_PHY_SPECTRAL_SCAN                   0x9910  /* AR9280 spectral scan configuration register */
+#define        AR_PHY_SPECTRAL_SCAN_ENABLE             0x1
+#define AR_PHY_SPECTRAL_SCAN_ENA               0x00000001  /* Enable spectral scan, reg 68, bit 0 */
+#define AR_PHY_SPECTRAL_SCAN_ENA_S             0  /* Enable spectral scan, reg 68, bit 0 */
+#define AR_PHY_SPECTRAL_SCAN_ACTIVE            0x00000002  /* Activate spectral scan reg 68, bit 1*/
+#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S          1  /* Activate spectral scan reg 68, bit 1*/
+#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD                0x000000F0  /* Interval for FFT reports, reg 68, bits 4-7*/
+#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S      4
+#define AR_PHY_SPECTRAL_SCAN_PERIOD            0x0000FF00  /* Interval for FFT reports, reg 68, bits 8-15*/
+#define AR_PHY_SPECTRAL_SCAN_PERIOD_S          8
+#define AR_PHY_SPECTRAL_SCAN_COUNT             0x00FF0000  /* Number of reports, reg 68, bits 16-23*/
+#define AR_PHY_SPECTRAL_SCAN_COUNT_S           16
+#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT      0x01000000  /* Short repeat, reg 68, bit 24*/
+#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S    24  /* Short repeat, reg 68, bit 24*/
+
+#define AR_PHY_RX_DELAY           0x9914
+#define AR_PHY_SEARCH_START_DELAY 0x9918
+#define AR_PHY_RX_DELAY_DELAY     0x00003FFF
+
+#define AR_PHY_TIMING_CTRL4(_i)     (0x9920 + ((_i) << 12))
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S   0
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S   5
+#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE   0x800
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S   12
+#define AR_PHY_TIMING_CTRL4_DO_CAL    0x10000
+
+#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI   0x80000000
+#define        AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER  0x40000000
+#define        AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK    0x20000000
+#define        AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK   0x10000000
+
+#define AR_PHY_TIMING5               0x9924
+#define AR_PHY_TIMING5_CYCPWR_THR1   0x000000FE
+#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
+
+#define AR_PHY_POWER_TX_RATE1               0x9934
+#define AR_PHY_POWER_TX_RATE2               0x9938
+#define AR_PHY_POWER_TX_RATE_MAX            0x993c
+#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
+
+#define AR_PHY_FRAME_CTL            0x9944
+#define AR_PHY_FRAME_CTL_TX_CLIP    0x00000038
+#define AR_PHY_FRAME_CTL_TX_CLIP_S  3
+
+#define AR_PHY_TXPWRADJ                   0x994C
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA    0x00000FC0
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S  6
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX   0x00FC0000
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
+
+#define AR_PHY_RADAR_EXT      0x9940
+#define AR_PHY_RADAR_EXT_ENA  0x00004000
+
+#define AR_PHY_RADAR_0          0x9954
+#define AR_PHY_RADAR_0_ENA      0x00000001
+#define AR_PHY_RADAR_0_FFT_ENA  0x80000000
+#define AR_PHY_RADAR_0_INBAND   0x0000003e
+#define AR_PHY_RADAR_0_INBAND_S 1
+#define AR_PHY_RADAR_0_PRSSI    0x00000FC0
+#define AR_PHY_RADAR_0_PRSSI_S  6
+#define AR_PHY_RADAR_0_HEIGHT   0x0003F000
+#define AR_PHY_RADAR_0_HEIGHT_S 12
+#define AR_PHY_RADAR_0_RRSSI    0x00FC0000
+#define AR_PHY_RADAR_0_RRSSI_S  18
+#define AR_PHY_RADAR_0_FIRPWR   0x7F000000
+#define AR_PHY_RADAR_0_FIRPWR_S 24
+
+#define AR_PHY_RADAR_1                  0x9958
+#define AR_PHY_RADAR_1_RELPWR_ENA       0x00800000
+#define AR_PHY_RADAR_1_USE_FIR128       0x00400000
+#define AR_PHY_RADAR_1_RELPWR_THRESH    0x003F0000
+#define AR_PHY_RADAR_1_RELPWR_THRESH_S  16
+#define AR_PHY_RADAR_1_BLOCK_CHECK      0x00008000
+#define AR_PHY_RADAR_1_MAX_RRSSI        0x00004000
+#define AR_PHY_RADAR_1_RELSTEP_CHECK    0x00002000
+#define AR_PHY_RADAR_1_RELSTEP_THRESH   0x00001F00
+#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
+#define AR_PHY_RADAR_1_MAXLEN           0x000000FF
+#define AR_PHY_RADAR_1_MAXLEN_S         0
+
+#define AR_PHY_SWITCH_CHAIN_0     0x9960
+#define AR_PHY_SWITCH_COM         0x9964
+
+#define AR_PHY_SIGMA_DELTA            0x996C
+#define AR_PHY_SIGMA_DELTA_ADC_SEL    0x00000003
+#define AR_PHY_SIGMA_DELTA_ADC_SEL_S  0
+#define AR_PHY_SIGMA_DELTA_FILT2      0x000000F8
+#define AR_PHY_SIGMA_DELTA_FILT2_S    3
+#define AR_PHY_SIGMA_DELTA_FILT1      0x00001F00
+#define AR_PHY_SIGMA_DELTA_FILT1_S    8
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP   0x01FFE000
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
+
+#define AR_PHY_RESTART          0x9970
+#define AR_PHY_RESTART_DIV_GC   0x001C0000
+#define AR_PHY_RESTART_DIV_GC_S 18
+
+#define AR_PHY_RFBUS_REQ        0x997C
+#define AR_PHY_RFBUS_REQ_EN     0x00000001
+
+#define        AR_PHY_TIMING7                  0x9980
+#define        AR_PHY_TIMING8                  0x9984
+#define        AR_PHY_TIMING8_PILOT_MASK_2     0x000FFFFF
+#define        AR_PHY_TIMING8_PILOT_MASK_2_S   0
+
+#define        AR_PHY_BIN_MASK2_1      0x9988
+#define        AR_PHY_BIN_MASK2_2      0x998c
+#define        AR_PHY_BIN_MASK2_3      0x9990
+#define        AR_PHY_BIN_MASK2_4      0x9994
+
+#define        AR_PHY_BIN_MASK_1       0x9900
+#define        AR_PHY_BIN_MASK_2       0x9904
+#define        AR_PHY_BIN_MASK_3       0x9908
+
+#define        AR_PHY_MASK_CTL         0x990c
+
+#define        AR_PHY_BIN_MASK2_4_MASK_4       0x00003FFF
+#define        AR_PHY_BIN_MASK2_4_MASK_4_S     0
+
+#define        AR_PHY_TIMING9                  0x9998
+#define        AR_PHY_TIMING10                 0x999c
+#define        AR_PHY_TIMING10_PILOT_MASK_2    0x000FFFFF
+#define        AR_PHY_TIMING10_PILOT_MASK_2_S  0
+
+#define        AR_PHY_TIMING11                         0x99a0
+#define        AR_PHY_TIMING11_SPUR_DELTA_PHASE        0x000FFFFF
+#define        AR_PHY_TIMING11_SPUR_DELTA_PHASE_S      0
+#define AR_PHY_TIMING11_USE_SPUR_IN_AGC                0x40000000
+#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR    0x80000000
+
+#define AR_PHY_RX_CHAINMASK     0x99a4
+#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
+#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
+#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
+
+#define AR_PHY_MULTICHAIN_GAIN_CTL          0x99ac
+#define AR_PHY_9285_FAST_DIV_BIAS          0x00007E00
+#define AR_PHY_9285_FAST_DIV_BIAS_S        9
+#define AR_PHY_9285_ANT_DIV_CTL_ALL         0x7f000000
+#define AR_PHY_9285_ANT_DIV_CTL             0x01000000
+#define AR_PHY_9285_ANT_DIV_CTL_S           24
+#define AR_PHY_9285_ANT_DIV_ALT_LNACONF     0x06000000
+#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S   25
+#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF    0x18000000
+#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S  27
+#define AR_PHY_9285_ANT_DIV_ALT_GAINTB      0x20000000
+#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S    29
+#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB     0x40000000
+#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S   30
+#define AR_PHY_9285_ANT_DIV_LNA1            2
+#define AR_PHY_9285_ANT_DIV_LNA2            1
+#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2  3
+#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0
+#define AR_PHY_9285_ANT_DIV_GAINTB_0        0
+#define AR_PHY_9285_ANT_DIV_GAINTB_1        1
+
+#define AR_PHY_EXT_CCA0             0x99b8
+#define AR_PHY_EXT_CCA0_THRESH62    0x000000FF
+#define AR_PHY_EXT_CCA0_THRESH62_S  0
+
+#define AR_PHY_EXT_CCA                  0x99bc
+#define AR_PHY_EXT_CCA_CYCPWR_THR1      0x0000FE00
+#define AR_PHY_EXT_CCA_CYCPWR_THR1_S    9
+#define AR_PHY_EXT_CCA_THRESH62         0x007F0000
+#define AR_PHY_EXT_CCA_THRESH62_S       16
+#define AR_PHY_EXT_TIMING5_CYCPWR_THR1   0x0000FE00L
+#define AR_PHY_EXT_TIMING5_CYCPWR_THR1_S 9
+
+#define AR_PHY_EXT_MINCCA_PWR           0xFF800000
+#define AR_PHY_EXT_MINCCA_PWR_S         23
+#define AR9280_PHY_EXT_MINCCA_PWR       0x01FF0000
+#define AR9280_PHY_EXT_MINCCA_PWR_S     16
+
+#define AR_PHY_SFCORR_EXT                 0x99c0
+#define AR_PHY_SFCORR_EXT_M1_THRESH       0x0000007F
+#define AR_PHY_SFCORR_EXT_M1_THRESH_S     0
+#define AR_PHY_SFCORR_EXT_M2_THRESH       0x00003F80
+#define AR_PHY_SFCORR_EXT_M2_THRESH_S     7
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW   0x001FC000
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW   0x0FE00000
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
+#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S   28
+
+#define AR_PHY_HALFGI           0x99D0
+#define AR_PHY_HALFGI_DSC_MAN   0x0007FFF0
+#define AR_PHY_HALFGI_DSC_MAN_S 4
+#define AR_PHY_HALFGI_DSC_EXP   0x0000000F
+#define AR_PHY_HALFGI_DSC_EXP_S 0
+
+#define AR_PHY_CHAN_INFO_MEMORY               0x99DC
+#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK  0x0001
+
+#define AR_PHY_HEAVY_CLIP_ENABLE         0x99E0
+
+#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS    0x99EC
+#define AR_PHY_RIFS_INIT_DELAY         0x03ff0000
+
+#define AR_PHY_M_SLEEP      0x99f0
+#define AR_PHY_REFCLKDLY    0x99f4
+#define AR_PHY_REFCLKPD     0x99f8
+
+#define AR_PHY_CALMODE      0x99f0
+
+#define AR_PHY_CALMODE_IQ           0x00000000
+#define AR_PHY_CALMODE_ADC_GAIN     0x00000001
+#define AR_PHY_CALMODE_ADC_DC_PER   0x00000002
+#define AR_PHY_CALMODE_ADC_DC_INIT  0x00000003
+
+#define AR_PHY_CAL_MEAS_0(_i)     (0x9c10 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_1(_i)     (0x9c14 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_2(_i)     (0x9c18 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_3(_i)     (0x9c1c + ((_i) << 12))
+
+#define AR_PHY_CURRENT_RSSI 0x9c1c
+#define AR9280_PHY_CURRENT_RSSI 0x9c3c
+
+#define AR_PHY_RFBUS_GRANT       0x9C20
+#define AR_PHY_RFBUS_GRANT_EN    0x00000001
+
+#define AR_PHY_CHAN_INFO_GAIN_DIFF             0x9CF4
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
+
+#define AR_PHY_CHAN_INFO_GAIN          0x9CFC
+
+#define AR_PHY_MODE         0xA200
+#define AR_PHY_MODE_ASYNCFIFO 0x80
+#define AR_PHY_MODE_AR2133  0x08
+#define AR_PHY_MODE_AR5111  0x00
+#define AR_PHY_MODE_AR5112  0x08
+#define AR_PHY_MODE_DYNAMIC 0x04
+#define AR_PHY_MODE_RF2GHZ  0x02
+#define AR_PHY_MODE_RF5GHZ  0x00
+#define AR_PHY_MODE_CCK     0x01
+#define AR_PHY_MODE_OFDM    0x00
+#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100
+
+#define AR_PHY_CCK_TX_CTRL       0xA204
+#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
+#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK         0x0000000C
+#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S       2
+
+#define AR_PHY_CCK_DETECT                           0xA208
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK          0x0000003F
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S        0
+/* [12:6] settling time for antenna switch */
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME           0x00001FC0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S         6
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV    0x2000
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S  13
+
+#define AR_PHY_GAIN_2GHZ                0xA20C
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN    0x00FC0000
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S  18
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN     0x00003C00
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S   10
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN      0x0000001F
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S    0
+
+#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN     0x003E0000
+#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S   17
+#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN     0x0001F000
+#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S   12
+#define AR_PHY_GAIN_2GHZ_XATTEN2_DB         0x00000FC0
+#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S       6
+#define AR_PHY_GAIN_2GHZ_XATTEN1_DB         0x0000003F
+#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S       0
+
+#define AR_PHY_CCK_RXCTRL4  0xA21C
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT   0x01F80000
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
+
+#define AR_PHY_DAG_CTRLCCK  0xA228
+#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR  0x00000200
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR     0x0001FC00
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S   10
+
+#define AR_PHY_FORCE_CLKEN_CCK              0xA22C
+#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX      0x00000040
+
+#define AR_PHY_POWER_TX_RATE3   0xA234
+#define AR_PHY_POWER_TX_RATE4   0xA238
+
+#define AR_PHY_SCRM_SEQ_XR       0xA23C
+#define AR_PHY_HEADER_DETECT_XR  0xA240
+#define AR_PHY_CHIRP_DETECTED_XR 0xA244
+#define AR_PHY_BLUETOOTH         0xA254
+
+#define AR_PHY_TPCRG1   0xA258
+#define AR_PHY_TPCRG1_NUM_PD_GAIN   0x0000c000
+#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
+
+#define AR_PHY_TPCRG1_PD_GAIN_1    0x00030000
+#define AR_PHY_TPCRG1_PD_GAIN_1_S  16
+#define AR_PHY_TPCRG1_PD_GAIN_2    0x000C0000
+#define AR_PHY_TPCRG1_PD_GAIN_2_S  18
+#define AR_PHY_TPCRG1_PD_GAIN_3    0x00300000
+#define AR_PHY_TPCRG1_PD_GAIN_3_S  20
+
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE   0x00400000
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
+
+#define AR_PHY_TX_PWRCTRL4       0xa264
+#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID     0x00000001
+#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S   0
+#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT       0x000001FE
+#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S     1
+
+#define AR_PHY_TX_PWRCTRL6_0     0xa270
+#define AR_PHY_TX_PWRCTRL6_1     0xb270
+#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE     0x03000000
+#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S   24
+
+#define AR_PHY_TX_PWRCTRL7       0xa274
+#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN     0x01F80000
+#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S   19
+
+#define AR_PHY_TX_PWRCTRL8       0xa278
+
+#define AR_PHY_TX_PWRCTRL9       0xa27C
+
+#define AR_PHY_TX_PWRCTRL10       0xa394
+#define AR_PHY_TX_DESIRED_SCALE_CCK        0x00007C00
+#define AR_PHY_TX_DESIRED_SCALE_CCK_S      10
+#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL  0x80000000
+#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31
+
+#define AR_PHY_TX_GAIN_TBL1      0xa300
+#define AR_PHY_TX_GAIN                     0x0007F000
+#define AR_PHY_TX_GAIN_S                   12
+
+#define AR_PHY_CH0_TX_PWRCTRL11  0xa398
+#define AR_PHY_CH1_TX_PWRCTRL11  0xb398
+#define AR_PHY_CH0_TX_PWRCTRL12  0xa3dc
+#define AR_PHY_CH0_TX_PWRCTRL13  0xa3e0
+#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP   0x0000FC00
+#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
+
+#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
+#define AR_PHY_MASK2_M_31_45     0xa3a4
+#define AR_PHY_MASK2_M_16_30     0xa3a8
+#define AR_PHY_MASK2_M_00_15     0xa3ac
+#define AR_PHY_MASK2_P_15_01     0xa3b8
+#define AR_PHY_MASK2_P_30_16     0xa3bc
+#define AR_PHY_MASK2_P_45_31     0xa3c0
+#define AR_PHY_MASK2_P_61_45     0xa3c4
+#define AR_PHY_SPUR_REG          0x994c
+
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL       (0xFF << 18)
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S     18
+
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM      0x20000
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT     (0xFF << 9)
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S   9
+#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH     0x7F
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S   0
+
+#define AR_PHY_PILOT_MASK_01_30   0xa3b0
+#define AR_PHY_PILOT_MASK_31_60   0xa3b4
+
+#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
+#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
+
+#define AR_PHY_ANALOG_SWAP      0xa268
+#define AR_PHY_SWAP_ALT_CHAIN   0x00000040
+
+#define AR_PHY_TPCRG5   0xA26C
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP       0x0000000F
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S     0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1    0x000003F0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S  4
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2    0x0000FC00
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S  10
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3    0x003F0000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S  16
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4    0x0FC00000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S  22
+
+/* Carrier leak calibration control, do it after AGC calibration */
+#define AR_PHY_CL_CAL_CTL       0xA358
+#define AR_PHY_CL_CAL_ENABLE    0x00000002
+#define AR_PHY_PARALLEL_CAL_ENABLE    0x00000001
+
+#define AR_PHY_POWER_TX_RATE5   0xA38C
+#define AR_PHY_POWER_TX_RATE6   0xA390
+
+#define AR_PHY_CAL_CHAINMASK    0xA39C
+
+#define AR_PHY_POWER_TX_SUB     0xA3C8
+#define AR_PHY_POWER_TX_RATE7   0xA3CC
+#define AR_PHY_POWER_TX_RATE8   0xA3D0
+#define AR_PHY_POWER_TX_RATE9   0xA3D4
+
+#define AR_PHY_XPA_CFG         0xA3D8
+#define AR_PHY_FORCE_XPA_CFG   0x000000001
+#define AR_PHY_FORCE_XPA_CFG_S 0
+
+#define AR_PHY_CH1_CCA          0xa864
+#define AR_PHY_CH1_MINCCA_PWR   0x0FF80000
+#define AR_PHY_CH1_MINCCA_PWR_S 19
+#define AR9280_PHY_CH1_MINCCA_PWR   0x1FF00000
+#define AR9280_PHY_CH1_MINCCA_PWR_S 20
+
+#define AR_PHY_CH2_CCA          0xb864
+#define AR_PHY_CH2_MINCCA_PWR   0x0FF80000
+#define AR_PHY_CH2_MINCCA_PWR_S 19
+
+#define AR_PHY_CH1_EXT_CCA          0xa9bc
+#define AR_PHY_CH1_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR   0x01FF0000
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
+
+#define AR_PHY_CH2_EXT_CCA          0xb9bc
+#define AR_PHY_CH2_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
+
+#define AR_PHY_CCA_NOM_VAL_5416_2GHZ            -90
+#define AR_PHY_CCA_NOM_VAL_5416_5GHZ            -100
+#define AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ     -100
+#define AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ     -110
+#define AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ     -80
+#define AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ     -90
+
+#define AR_PHY_CCA_NOM_VAL_9280_2GHZ         -112
+#define AR_PHY_CCA_NOM_VAL_9280_5GHZ         -112
+#define AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ  -127
+#define AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ  -122
+#define AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ  -97
+#define AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ  -102
+
+#define AR_PHY_CCA_NOM_VAL_9285_2GHZ           -118
+#define AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ    -127
+#define AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ    -108
+
+#define AR_PHY_CCA_NOM_VAL_9271_2GHZ             -118
+#define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ      -127
+#define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ      -116
+
+#define AR_PHY_CCA_NOM_VAL_9287_2GHZ           -120
+#define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ    -127
+#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ    -110
+
+#endif
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_2p2_initvals.h
new file mode 100644 (file)
index 0000000..d50f47a
--- /dev/null
@@ -0,0 +1,1561 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9003_2P2_H
+#define INITVALS_9003_2P2_H
+
+/* AR9003 2.2 */
+
+static const u32 ar9300_2p2_radio_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31},
+       {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
+       {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
+       {0x0001610c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
+       {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+       {0x0001650c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
+       {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+       {0x0001690c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
+       {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+};
+
+static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+       {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+       {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+       {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+       {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9300Modes_fast_clock_2p2[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x00001030, 0x00000268, 0x000004d0},
+       {0x00001070, 0x0000018c, 0x00000318},
+       {0x000010b0, 0x00000fd0, 0x00001fa0},
+       {0x00008014, 0x044c044c, 0x08980898},
+       {0x0000801c, 0x148ec02b, 0x148ec057},
+       {0x00008318, 0x000044c0, 0x00008980},
+       {0x00009e00, 0x0372131c, 0x0372131c},
+       {0x0000a230, 0x0000000b, 0x00000016},
+       {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9300_2p2_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73f00000},
+       {0x0001600c, 0x00000000},
+       {0x00016040, 0x7f80fff8},
+       {0x0001604c, 0x76d005b5},
+       {0x00016050, 0x556cf031},
+       {0x00016054, 0x13449440},
+       {0x00016058, 0x0c51c92c},
+       {0x0001605c, 0x3db7fffc},
+       {0x00016060, 0xfffffffc},
+       {0x00016064, 0x000f0278},
+       {0x0001606c, 0x6db60000},
+       {0x00016080, 0x00000000},
+       {0x00016084, 0x0e48048c},
+       {0x00016088, 0x54214514},
+       {0x0001608c, 0x119f481e},
+       {0x00016090, 0x24926490},
+       {0x00016098, 0xd2888888},
+       {0x000160a0, 0x0a108ffe},
+       {0x000160a4, 0x812fc370},
+       {0x000160a8, 0x423c8000},
+       {0x000160b4, 0x92480080},
+       {0x000160c0, 0x00adb6d0},
+       {0x000160c4, 0x6db6db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x01e6c000},
+       {0x00016100, 0x3fffbe01},
+       {0x00016104, 0xfff80000},
+       {0x00016108, 0x00080010},
+       {0x00016144, 0x02084080},
+       {0x00016148, 0x00000000},
+       {0x00016280, 0x058a0001},
+       {0x00016284, 0x3d840208},
+       {0x00016288, 0x05a20408},
+       {0x0001628c, 0x00038c07},
+       {0x00016290, 0x00000004},
+       {0x00016294, 0x458a214f},
+       {0x00016380, 0x00000000},
+       {0x00016384, 0x00000000},
+       {0x00016388, 0x00800700},
+       {0x0001638c, 0x00800700},
+       {0x00016390, 0x00800700},
+       {0x00016394, 0x00000000},
+       {0x00016398, 0x00000000},
+       {0x0001639c, 0x00000000},
+       {0x000163a0, 0x00000001},
+       {0x000163a4, 0x00000001},
+       {0x000163a8, 0x00000000},
+       {0x000163ac, 0x00000000},
+       {0x000163b0, 0x00000000},
+       {0x000163b4, 0x00000000},
+       {0x000163b8, 0x00000000},
+       {0x000163bc, 0x00000000},
+       {0x000163c0, 0x000000a0},
+       {0x000163c4, 0x000c0000},
+       {0x000163c8, 0x14021402},
+       {0x000163cc, 0x00001402},
+       {0x000163d0, 0x00000000},
+       {0x000163d4, 0x00000000},
+       {0x00016400, 0x36db6db6},
+       {0x00016404, 0x6db6db40},
+       {0x00016408, 0x73f00000},
+       {0x0001640c, 0x00000000},
+       {0x00016440, 0x7f80fff8},
+       {0x0001644c, 0x76d005b5},
+       {0x00016450, 0x556cf031},
+       {0x00016454, 0x13449440},
+       {0x00016458, 0x0c51c92c},
+       {0x0001645c, 0x3db7fffc},
+       {0x00016460, 0xfffffffc},
+       {0x00016464, 0x000f0278},
+       {0x0001646c, 0x6db60000},
+       {0x00016500, 0x3fffbe01},
+       {0x00016504, 0xfff80000},
+       {0x00016508, 0x00080010},
+       {0x00016544, 0x02084080},
+       {0x00016548, 0x00000000},
+       {0x00016780, 0x00000000},
+       {0x00016784, 0x00000000},
+       {0x00016788, 0x00800700},
+       {0x0001678c, 0x00800700},
+       {0x00016790, 0x00800700},
+       {0x00016794, 0x00000000},
+       {0x00016798, 0x00000000},
+       {0x0001679c, 0x00000000},
+       {0x000167a0, 0x00000001},
+       {0x000167a4, 0x00000001},
+       {0x000167a8, 0x00000000},
+       {0x000167ac, 0x00000000},
+       {0x000167b0, 0x00000000},
+       {0x000167b4, 0x00000000},
+       {0x000167b8, 0x00000000},
+       {0x000167bc, 0x00000000},
+       {0x000167c0, 0x000000a0},
+       {0x000167c4, 0x000c0000},
+       {0x000167c8, 0x14021402},
+       {0x000167cc, 0x00001402},
+       {0x000167d0, 0x00000000},
+       {0x000167d4, 0x00000000},
+       {0x00016800, 0x36db6db6},
+       {0x00016804, 0x6db6db40},
+       {0x00016808, 0x73f00000},
+       {0x0001680c, 0x00000000},
+       {0x00016840, 0x7f80fff8},
+       {0x0001684c, 0x76d005b5},
+       {0x00016850, 0x556cf031},
+       {0x00016854, 0x13449440},
+       {0x00016858, 0x0c51c92c},
+       {0x0001685c, 0x3db7fffc},
+       {0x00016860, 0xfffffffc},
+       {0x00016864, 0x000f0278},
+       {0x0001686c, 0x6db60000},
+       {0x00016900, 0x3fffbe01},
+       {0x00016904, 0xfff80000},
+       {0x00016908, 0x00080010},
+       {0x00016944, 0x02084080},
+       {0x00016948, 0x00000000},
+       {0x00016b80, 0x00000000},
+       {0x00016b84, 0x00000000},
+       {0x00016b88, 0x00800700},
+       {0x00016b8c, 0x00800700},
+       {0x00016b90, 0x00800700},
+       {0x00016b94, 0x00000000},
+       {0x00016b98, 0x00000000},
+       {0x00016b9c, 0x00000000},
+       {0x00016ba0, 0x00000001},
+       {0x00016ba4, 0x00000001},
+       {0x00016ba8, 0x00000000},
+       {0x00016bac, 0x00000000},
+       {0x00016bb0, 0x00000000},
+       {0x00016bb4, 0x00000000},
+       {0x00016bb8, 0x00000000},
+       {0x00016bbc, 0x00000000},
+       {0x00016bc0, 0x000000a0},
+       {0x00016bc4, 0x000c0000},
+       {0x00016bc8, 0x14021402},
+       {0x00016bcc, 0x00001402},
+       {0x00016bd0, 0x00000000},
+       {0x00016bd4, 0x00000000},
+};
+
+static const u32 ar9300_2p2_mac_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9300_2p2_soc_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
+};
+
+static const u32 ar9300_2p2_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+       {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+       {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+       {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+       {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f},
+       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+       {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+       {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00041983, 0x00041983, 0x00041983, 0x00041983},
+       {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+       {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+       {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+       {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+       {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+};
+
+static const u32 ar9300_2p2_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a9f6b},
+       {0x0000980c, 0x04900000},
+       {0x00009814, 0x9280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x6400a190},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x14000600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32840bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0xff55ff55},
+       {0x00009c08, 0x0320ff55},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x9883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c0040b},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038230c},
+       {0x00009e24, 0x990bb515},
+       {0x00009e28, 0x0c6f0000},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009e54, 0x00000000},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x00009fd0, 0x01193b93},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0xaaaaaaaa},
+       {0x0000a3ac, 0x3c466478},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000000},
+       {0x0000a3f8, 0x0c9bd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739ce},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a41c, 0x1ce739ce},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce739ce},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00100000},
+       {0x0000a440, 0x00000000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x05000080},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a458, 0x00000000},
+       {0x0000a640, 0x00000000},
+       {0x0000a644, 0x3fad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00003c37},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000001},
+       {0x0000a8d0, 0x004b6a8e},
+       {0x0000a8d4, 0x00000820},
+       {0x0000a8dc, 0x00000000},
+       {0x0000a8f0, 0x00000000},
+       {0x0000a8f4, 0x00000000},
+       {0x0000b2d0, 0x00000080},
+       {0x0000b2d4, 0x00000000},
+       {0x0000b2ec, 0x00000000},
+       {0x0000b2f0, 0x00000000},
+       {0x0000b2f4, 0x00000000},
+       {0x0000b2f8, 0x00000000},
+       {0x0000b408, 0x0e79e5c0},
+       {0x0000b40c, 0x00820820},
+       {0x0000b420, 0x00000000},
+       {0x0000b8d0, 0x004b6a8e},
+       {0x0000b8d4, 0x00000820},
+       {0x0000b8dc, 0x00000000},
+       {0x0000b8f0, 0x00000000},
+       {0x0000b8f4, 0x00000000},
+       {0x0000c2d0, 0x00000080},
+       {0x0000c2d4, 0x00000000},
+       {0x0000c2ec, 0x00000000},
+       {0x0000c2f0, 0x00000000},
+       {0x0000c2f4, 0x00000000},
+       {0x0000c2f8, 0x00000000},
+       {0x0000c408, 0x0e79e5c0},
+       {0x0000c40c, 0x00820820},
+       {0x0000c420, 0x00000000},
+};
+
+static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
+       {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
+       {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x5e88442e, 0x5e88442e, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x628a4431, 0x628a4431, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
+       {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d4, 0x000050d4, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+       {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+       {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+       {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+       {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+       {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+       {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+       {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+       {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+       {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+       {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+       {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+       {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+       {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+       {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+       {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+       {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+       {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+       {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+       {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+       {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+       {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+       {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+       {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+       {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+       {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+       {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+       {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+       {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+       {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+       {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+       {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+       {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+       {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9300Common_rx_gain_table_2p2[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x01910190},
+       {0x0000a030, 0x01930192},
+       {0x0000a034, 0x01950194},
+       {0x0000a038, 0x038a0196},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x1a1a1a1a},
+       {0x0000a084, 0x1a1a1a1a},
+       {0x0000a088, 0x1a1a1a1a},
+       {0x0000a08c, 0x1a1a1a1a},
+       {0x0000a090, 0x171a1a1a},
+       {0x0000a094, 0x11111717},
+       {0x0000a098, 0x00030311},
+       {0x0000a09c, 0x00000000},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x23232323},
+       {0x0000b084, 0x21232323},
+       {0x0000b088, 0x19191c1e},
+       {0x0000b08c, 0x12141417},
+       {0x0000b090, 0x07070e0e},
+       {0x0000b094, 0x03030305},
+       {0x0000b098, 0x00000003},
+       {0x0000b09c, 0x00000000},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+       {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9300_2p2_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x00020085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c20},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00a00000},
+       {0x000080d8, 0x00400000},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x000081c0, 0x00000000},
+       {0x000081c4, 0x33332210},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000800},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x9d400010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000140},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xaa48105b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a0, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9300Common_wo_xlna_rx_gain_table_2p2[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x03820190},
+       {0x0000a030, 0x03840383},
+       {0x0000a034, 0x03880385},
+       {0x0000a038, 0x038a0389},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x29292929},
+       {0x0000a084, 0x29292929},
+       {0x0000a088, 0x29292929},
+       {0x0000a08c, 0x29292929},
+       {0x0000a090, 0x22292929},
+       {0x0000a094, 0x1d1d2222},
+       {0x0000a098, 0x0c111117},
+       {0x0000a09c, 0x00030303},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x32323232},
+       {0x0000b084, 0x2f2f3232},
+       {0x0000b088, 0x23282a2d},
+       {0x0000b08c, 0x1c1e2123},
+       {0x0000b090, 0x14171919},
+       {0x0000b094, 0x0e0e1214},
+       {0x0000b098, 0x03050707},
+       {0x0000b09c, 0x00030303},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9300_2p2_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x000040a4, 0x00a0c1c9},
+       {0x00007008, 0x00000000},
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+       {0x00007048, 0x00000008},
+};
+
+static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = {
+       /* Addr      allmodes  */
+       {0x00004040, 0x0821265e},
+       {0x00004040, 0x0008003b},
+       {0x00004044, 0x00000000},
+};
+
+static const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = {
+       /* Addr      allmodes  */
+       {0x00004040, 0x08253e5e},
+       {0x00004040, 0x0008003b},
+       {0x00004044, 0x00000000},
+};
+
+static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = {
+       /* Addr      allmodes  */
+       {0x00004040, 0x08213e5e},
+       {0x00004040, 0x0008003b},
+       {0x00004044, 0x00000000},
+};
+
+#endif /* INITVALS_9003_2P2_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_calib.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_calib.c
new file mode 100644 (file)
index 0000000..cab677e
--- /dev/null
@@ -0,0 +1,1089 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "ar9003_phy.h"
+#include "ar9003_rtt.h"
+#include "ar9003_mci.h"
+
+#define MAX_MEASUREMENT        MAX_IQCAL_MEASUREMENT
+#define MAX_MAG_DELTA  11
+#define MAX_PHS_DELTA  10
+
+struct coeff {
+       int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
+       int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
+       int iqc_coeff[2];
+};
+
+enum ar9003_cal_types {
+       IQ_MISMATCH_CAL = BIT(0),
+       TEMP_COMP_CAL = BIT(1),
+};
+
+static void ar9003_hw_setup_calibration(struct ath_hw *ah,
+                                       struct ath9k_cal_list *currCal)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       /* Select calibration to run */
+       switch (currCal->calData->calType) {
+       case IQ_MISMATCH_CAL:
+               /*
+                * Start calibration with
+                * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
+                */
+               REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+                             AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
+               currCal->calData->calCountMax);
+               REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
+
+               ath_dbg(common, CALIBRATE,
+                       "starting IQ Mismatch Calibration\n");
+
+               /* Kick-off cal */
+               REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
+               break;
+       case TEMP_COMP_CAL:
+               REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
+                             AR_PHY_65NM_CH0_THERM_LOCAL, 1);
+               REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
+                             AR_PHY_65NM_CH0_THERM_START, 1);
+
+               ath_dbg(common, CALIBRATE,
+                       "starting Temperature Compensation Calibration\n");
+               break;
+       }
+}
+
+/*
+ * Generic calibration routine.
+ * Recalibrate the lower PHY chips to account for temperature/environment
+ * changes.
+ */
+static bool ar9003_hw_per_calibration(struct ath_hw *ah,
+                                     struct ath9k_channel *ichan,
+                                     u8 rxchainmask,
+                                     struct ath9k_cal_list *currCal)
+{
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+       /* Cal is assumed not done until explicitly set below */
+       bool iscaldone = false;
+
+       /* Calibration in progress. */
+       if (currCal->calState == CAL_RUNNING) {
+               /* Check to see if it has finished. */
+               if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
+                       /*
+                       * Accumulate cal measures for active chains
+                       */
+                       currCal->calData->calCollect(ah);
+                       ah->cal_samples++;
+
+                       if (ah->cal_samples >=
+                           currCal->calData->calNumSamples) {
+                               unsigned int i, numChains = 0;
+                               for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+                                       if (rxchainmask & (1 << i))
+                                               numChains++;
+                               }
+
+                               /*
+                               * Process accumulated data
+                               */
+                               currCal->calData->calPostProc(ah, numChains);
+
+                               /* Calibration has finished. */
+                               caldata->CalValid |= currCal->calData->calType;
+                               currCal->calState = CAL_DONE;
+                               iscaldone = true;
+                       } else {
+                       /*
+                        * Set-up collection of another sub-sample until we
+                        * get desired number
+                        */
+                       ar9003_hw_setup_calibration(ah, currCal);
+                       }
+               }
+       } else if (!(caldata->CalValid & currCal->calData->calType)) {
+               /* If current cal is marked invalid in channel, kick it off */
+               ath9k_hw_reset_calibration(ah, currCal);
+       }
+
+       return iscaldone;
+}
+
+static bool ar9003_hw_calibrate(struct ath_hw *ah,
+                               struct ath9k_channel *chan,
+                               u8 rxchainmask,
+                               bool longcal)
+{
+       bool iscaldone = true;
+       struct ath9k_cal_list *currCal = ah->cal_list_curr;
+
+       /*
+        * For given calibration:
+        * 1. Call generic cal routine
+        * 2. When this cal is done (isCalDone) if we have more cals waiting
+        *    (eg after reset), mask this to upper layers by not propagating
+        *    isCalDone if it is set to TRUE.
+        *    Instead, change isCalDone to FALSE and setup the waiting cal(s)
+        *    to be run.
+        */
+       if (currCal &&
+           (currCal->calState == CAL_RUNNING ||
+            currCal->calState == CAL_WAITING)) {
+               iscaldone = ar9003_hw_per_calibration(ah, chan,
+                                                     rxchainmask, currCal);
+               if (iscaldone) {
+                       ah->cal_list_curr = currCal = currCal->calNext;
+
+                       if (currCal->calState == CAL_WAITING) {
+                               iscaldone = false;
+                               ath9k_hw_reset_calibration(ah, currCal);
+                       }
+               }
+       }
+
+       /*
+        * Do NF cal only at longer intervals. Get the value from
+        * the previous NF cal and update history buffer.
+        */
+       if (longcal && ath9k_btcoex_ath9k_hw_getnf(ah, chan)) {
+               /*
+                * Load the NF from history buffer of the current channel.
+                * NF is slow time-variant, so it is OK to use a historical
+                * value.
+                */
+               ath9k_hw_loadnf(ah, ah->curchan);
+
+               /* start NF calibration, without updating BB NF register */
+               ath9k_hw_start_nfcal(ah, false);
+       }
+
+       return iscaldone;
+}
+
+static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
+{
+       int i;
+
+       /* Accumulate IQ cal measures for active chains */
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               if (ah->txchainmask & BIT(i)) {
+                       ah->totalPowerMeasI[i] +=
+                               REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+                       ah->totalPowerMeasQ[i] +=
+                               REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+                       ah->totalIqCorrMeas[i] +=
+                               (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+                       ath_dbg(ath9k_hw_common(ah), CALIBRATE,
+                               "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+                               ah->cal_samples, i, ah->totalPowerMeasI[i],
+                               ah->totalPowerMeasQ[i],
+                               ah->totalIqCorrMeas[i]);
+               }
+       }
+}
+
+static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 powerMeasQ, powerMeasI, iqCorrMeas;
+       u32 qCoffDenom, iCoffDenom;
+       int32_t qCoff, iCoff;
+       int iqCorrNeg, i;
+       static const u_int32_t offset_array[3] = {
+               AR_PHY_RX_IQCAL_CORR_B0,
+               AR_PHY_RX_IQCAL_CORR_B1,
+               AR_PHY_RX_IQCAL_CORR_B2,
+       };
+
+       for (i = 0; i < numChains; i++) {
+               powerMeasI = ah->totalPowerMeasI[i];
+               powerMeasQ = ah->totalPowerMeasQ[i];
+               iqCorrMeas = ah->totalIqCorrMeas[i];
+
+               ath_dbg(common, CALIBRATE,
+                       "Starting IQ Cal and Correction for Chain %d\n", i);
+
+               ath_dbg(common, CALIBRATE,
+                       "Original: Chn %d iq_corr_meas = 0x%08x\n",
+                       i, ah->totalIqCorrMeas[i]);
+
+               iqCorrNeg = 0;
+
+               if (iqCorrMeas > 0x80000000) {
+                       iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
+                       iqCorrNeg = 1;
+               }
+
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
+                       i, powerMeasI);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
+                       i, powerMeasQ);
+               ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
+
+               iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
+               qCoffDenom = powerMeasQ / 64;
+
+               if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
+                       iCoff = iqCorrMeas / iCoffDenom;
+                       qCoff = powerMeasI / qCoffDenom - 64;
+                       ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
+                               i, iCoff);
+                       ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
+                               i, qCoff);
+
+                       /* Force bounds on iCoff */
+                       if (iCoff >= 63)
+                               iCoff = 63;
+                       else if (iCoff <= -63)
+                               iCoff = -63;
+
+                       /* Negate iCoff if iqCorrNeg == 0 */
+                       if (iqCorrNeg == 0x0)
+                               iCoff = -iCoff;
+
+                       /* Force bounds on qCoff */
+                       if (qCoff >= 63)
+                               qCoff = 63;
+                       else if (qCoff <= -63)
+                               qCoff = -63;
+
+                       iCoff = iCoff & 0x7f;
+                       qCoff = qCoff & 0x7f;
+
+                       ath_dbg(common, CALIBRATE,
+                               "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
+                               i, iCoff, qCoff);
+                       ath_dbg(common, CALIBRATE,
+                               "Register offset (0x%04x) before update = 0x%x\n",
+                               offset_array[i],
+                               REG_READ(ah, offset_array[i]));
+
+                       REG_RMW_FIELD(ah, offset_array[i],
+                                     AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
+                                     iCoff);
+                       REG_RMW_FIELD(ah, offset_array[i],
+                                     AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
+                                     qCoff);
+                       ath_dbg(common, CALIBRATE,
+                               "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
+                               offset_array[i],
+                               AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
+                               REG_READ(ah, offset_array[i]));
+                       ath_dbg(common, CALIBRATE,
+                               "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
+                               offset_array[i],
+                               AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
+                               REG_READ(ah, offset_array[i]));
+
+                       ath_dbg(common, CALIBRATE,
+                               "IQ Cal and Correction done for Chain %d\n", i);
+               }
+       }
+
+       REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
+                   AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
+       ath_dbg(common, CALIBRATE,
+               "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
+               (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
+               AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
+               REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
+}
+
+static const struct ath9k_percal_data iq_cal_single_sample = {
+       IQ_MISMATCH_CAL,
+       MIN_CAL_SAMPLES,
+       PER_MAX_LOG_COUNT,
+       ar9003_hw_iqcal_collect,
+       ar9003_hw_iqcalibrate
+};
+
+static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
+{
+       ah->iq_caldata.calData = &iq_cal_single_sample;
+}
+
+/*
+ * solve 4x4 linear equation used in loopback iq cal.
+ */
+static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah,
+                                  s32 sin_2phi_1,
+                                  s32 cos_2phi_1,
+                                  s32 sin_2phi_2,
+                                  s32 cos_2phi_2,
+                                  s32 mag_a0_d0,
+                                  s32 phs_a0_d0,
+                                  s32 mag_a1_d0,
+                                  s32 phs_a1_d0,
+                                  s32 solved_eq[])
+{
+       s32 f1 = cos_2phi_1 - cos_2phi_2,
+           f3 = sin_2phi_1 - sin_2phi_2,
+           f2;
+       s32 mag_tx, phs_tx, mag_rx, phs_rx;
+       const s32 result_shift = 1 << 15;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       f2 = (f1 * f1 + f3 * f3) / result_shift;
+
+       if (!f2) {
+               ath_dbg(common, CALIBRATE, "Divide by 0\n");
+               return false;
+       }
+
+       /* mag mismatch, tx */
+       mag_tx = f1 * (mag_a0_d0  - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
+       /* phs mismatch, tx */
+       phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
+
+       mag_tx = (mag_tx / f2);
+       phs_tx = (phs_tx / f2);
+
+       /* mag mismatch, rx */
+       mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
+                result_shift;
+       /* phs mismatch, rx */
+       phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
+                result_shift;
+
+       solved_eq[0] = mag_tx;
+       solved_eq[1] = phs_tx;
+       solved_eq[2] = mag_rx;
+       solved_eq[3] = phs_rx;
+
+       return true;
+}
+
+static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah, s32 in_re, s32 in_im)
+{
+       s32 abs_i = abs(in_re),
+           abs_q = abs(in_im),
+           max_abs, min_abs;
+
+       if (abs_i > abs_q) {
+               max_abs = abs_i;
+               min_abs = abs_q;
+       } else {
+               max_abs = abs_q;
+               min_abs = abs_i;
+       }
+
+       return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
+}
+
+#define DELPT 32
+
+static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
+                                  s32 chain_idx,
+                                  const s32 iq_res[],
+                                  s32 iqc_coeff[])
+{
+       s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
+           i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
+           i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
+           i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
+       s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
+           phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
+           sin_2phi_1, cos_2phi_1,
+           sin_2phi_2, cos_2phi_2;
+       s32 mag_tx, phs_tx, mag_rx, phs_rx;
+       s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
+           q_q_coff, q_i_coff;
+       const s32 res_scale = 1 << 15;
+       const s32 delpt_shift = 1 << 8;
+       s32 mag1, mag2;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
+       i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
+       iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
+
+       if (i2_m_q2_a0_d0 > 0x800)
+               i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
+
+       if (i2_p_q2_a0_d0 > 0x800)
+               i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
+
+       if (iq_corr_a0_d0 > 0x800)
+               iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
+
+       i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
+       i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
+       iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
+
+       if (i2_m_q2_a0_d1 > 0x800)
+               i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
+
+       if (i2_p_q2_a0_d1 > 0x800)
+               i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1);
+
+       if (iq_corr_a0_d1 > 0x800)
+               iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
+
+       i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
+       i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
+       iq_corr_a1_d0 = iq_res[4] & 0xfff;
+
+       if (i2_m_q2_a1_d0 > 0x800)
+               i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
+
+       if (i2_p_q2_a1_d0 > 0x800)
+               i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
+
+       if (iq_corr_a1_d0 > 0x800)
+               iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
+
+       i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
+       i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
+       iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
+
+       if (i2_m_q2_a1_d1 > 0x800)
+               i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
+
+       if (i2_p_q2_a1_d1 > 0x800)
+               i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
+
+       if (iq_corr_a1_d1 > 0x800)
+               iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
+
+       if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
+           (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
+               ath_dbg(common, CALIBRATE,
+                       "Divide by 0:\n"
+                       "a0_d0=%d\n"
+                       "a0_d1=%d\n"
+                       "a2_d0=%d\n"
+                       "a1_d1=%d\n",
+                       i2_p_q2_a0_d0, i2_p_q2_a0_d1,
+                       i2_p_q2_a1_d0, i2_p_q2_a1_d1);
+               return false;
+       }
+
+       mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
+       phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
+
+       mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
+       phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
+
+       mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
+       phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
+
+       mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
+       phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
+
+       /* w/o analog phase shift */
+       sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
+       /* w/o analog phase shift */
+       cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
+       /* w/  analog phase shift */
+       sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
+       /* w/  analog phase shift */
+       cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
+
+       /*
+        * force sin^2 + cos^2 = 1;
+        * find magnitude by approximation
+        */
+       mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
+       mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
+
+       if ((mag1 == 0) || (mag2 == 0)) {
+               ath_dbg(common, CALIBRATE, "Divide by 0: mag1=%d, mag2=%d\n",
+                       mag1, mag2);
+               return false;
+       }
+
+       /* normalization sin and cos by mag */
+       sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
+       cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
+       sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
+       cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
+
+       /* calculate IQ mismatch */
+       if (!ar9003_hw_solve_iq_cal(ah,
+                            sin_2phi_1, cos_2phi_1,
+                            sin_2phi_2, cos_2phi_2,
+                            mag_a0_d0, phs_a0_d0,
+                            mag_a1_d0,
+                            phs_a1_d0, solved_eq)) {
+               ath_dbg(common, CALIBRATE,
+                       "Call to ar9003_hw_solve_iq_cal() failed\n");
+               return false;
+       }
+
+       mag_tx = solved_eq[0];
+       phs_tx = solved_eq[1];
+       mag_rx = solved_eq[2];
+       phs_rx = solved_eq[3];
+
+       ath_dbg(common, CALIBRATE,
+               "chain %d: mag mismatch=%d phase mismatch=%d\n",
+               chain_idx, mag_tx/res_scale, phs_tx/res_scale);
+
+       if (res_scale == mag_tx) {
+               ath_dbg(common, CALIBRATE,
+                       "Divide by 0: mag_tx=%d, res_scale=%d\n",
+                       mag_tx, res_scale);
+               return false;
+       }
+
+       /* calculate and quantize Tx IQ correction factor */
+       mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
+       phs_corr_tx = -phs_tx;
+
+       q_q_coff = (mag_corr_tx * 128 / res_scale);
+       q_i_coff = (phs_corr_tx * 256 / res_scale);
+
+       ath_dbg(common, CALIBRATE, "tx chain %d: mag corr=%d  phase corr=%d\n",
+               chain_idx, q_q_coff, q_i_coff);
+
+       if (q_i_coff < -63)
+               q_i_coff = -63;
+       if (q_i_coff > 63)
+               q_i_coff = 63;
+       if (q_q_coff < -63)
+               q_q_coff = -63;
+       if (q_q_coff > 63)
+               q_q_coff = 63;
+
+       iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
+
+       ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
+               chain_idx, iqc_coeff[0]);
+
+       if (-mag_rx == res_scale) {
+               ath_dbg(common, CALIBRATE,
+                       "Divide by 0: mag_rx=%d, res_scale=%d\n",
+                       mag_rx, res_scale);
+               return false;
+       }
+
+       /* calculate and quantize Rx IQ correction factors */
+       mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
+       phs_corr_rx = -phs_rx;
+
+       q_q_coff = (mag_corr_rx * 128 / res_scale);
+       q_i_coff = (phs_corr_rx * 256 / res_scale);
+
+       ath_dbg(common, CALIBRATE, "rx chain %d: mag corr=%d  phase corr=%d\n",
+               chain_idx, q_q_coff, q_i_coff);
+
+       if (q_i_coff < -63)
+               q_i_coff = -63;
+       if (q_i_coff > 63)
+               q_i_coff = 63;
+       if (q_q_coff < -63)
+               q_q_coff = -63;
+       if (q_q_coff > 63)
+               q_q_coff = 63;
+
+       iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
+
+       ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
+               chain_idx, iqc_coeff[1]);
+
+       return true;
+}
+
+static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
+                                    int max_delta)
+{
+       int mp_max = -64, max_idx = 0;
+       int mp_min = 63, min_idx = 0;
+       int mp_avg = 0, i, outlier_idx = 0, mp_count = 0;
+
+       /* find min/max mismatch across all calibrated gains */
+       for (i = 0; i < nmeasurement; i++) {
+               if (mp_coeff[i] > mp_max) {
+                       mp_max = mp_coeff[i];
+                       max_idx = i;
+               } else if (mp_coeff[i] < mp_min) {
+                       mp_min = mp_coeff[i];
+                       min_idx = i;
+               }
+       }
+
+       /* find average (exclude max abs value) */
+       for (i = 0; i < nmeasurement; i++) {
+               if ((abs(mp_coeff[i]) < abs(mp_max)) ||
+                   (abs(mp_coeff[i]) < abs(mp_min))) {
+                       mp_avg += mp_coeff[i];
+                       mp_count++;
+               }
+       }
+
+       /*
+        * finding mean magnitude/phase if possible, otherwise
+        * just use the last value as the mean
+        */
+       if (mp_count)
+               mp_avg /= mp_count;
+       else
+               mp_avg = mp_coeff[nmeasurement - 1];
+
+       /* detect outlier */
+       if (abs(mp_max - mp_min) > max_delta) {
+               if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
+                       outlier_idx = max_idx;
+               else
+                       outlier_idx = min_idx;
+
+               mp_coeff[outlier_idx] = mp_avg;
+       }
+}
+
+static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
+                                                struct coeff *coeff,
+                                                bool is_reusable)
+{
+       int i, im, nmeasurement;
+       u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+
+       memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
+       for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
+               tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
+                                       AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
+               if (!AR_SREV_9485(ah)) {
+                       tx_corr_coeff[i * 2][1] =
+                       tx_corr_coeff[(i * 2) + 1][1] =
+                                       AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
+
+                       tx_corr_coeff[i * 2][2] =
+                       tx_corr_coeff[(i * 2) + 1][2] =
+                                       AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
+               }
+       }
+
+       /* Load the average of 2 passes */
+       for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+               if (!(ah->txchainmask & (1 << i)))
+                       continue;
+               nmeasurement = REG_READ_FIELD(ah,
+                               AR_PHY_TX_IQCAL_STATUS_B0,
+                               AR_PHY_CALIBRATED_GAINS_0);
+
+               if (nmeasurement > MAX_MEASUREMENT)
+                       nmeasurement = MAX_MEASUREMENT;
+
+               /* detect outlier only if nmeasurement > 1 */
+               if (nmeasurement > 1) {
+                       /* Detect magnitude outlier */
+                       ar9003_hw_detect_outlier(coeff->mag_coeff[i],
+                                       nmeasurement, MAX_MAG_DELTA);
+
+                       /* Detect phase outlier */
+                       ar9003_hw_detect_outlier(coeff->phs_coeff[i],
+                                       nmeasurement, MAX_PHS_DELTA);
+               }
+
+               for (im = 0; im < nmeasurement; im++) {
+
+                       coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
+                               ((coeff->phs_coeff[i][im] & 0x7f) << 7);
+
+                       if ((im % 2) == 0)
+                               REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+                                       AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
+                                       coeff->iqc_coeff[0]);
+                       else
+                               REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+                                       AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
+                                       coeff->iqc_coeff[0]);
+
+                       if (caldata)
+                               caldata->tx_corr_coeff[im][i] =
+                                       coeff->iqc_coeff[0];
+               }
+               if (caldata)
+                       caldata->num_measures[i] = nmeasurement;
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
+                     AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
+       REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
+                     AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
+
+       if (caldata)
+               caldata->done_txiqcal_once = is_reusable;
+
+       return;
+}
+
+static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u8 tx_gain_forced;
+
+       tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                                       AR_PHY_TXGAIN_FORCE);
+       if (tx_gain_forced)
+               REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                             AR_PHY_TXGAIN_FORCE, 0);
+
+       REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
+                     AR_PHY_TX_IQCAL_START_DO_CAL, 1);
+
+       if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
+                       AR_PHY_TX_IQCAL_START_DO_CAL, 0,
+                       AH_WAIT_TIMEOUT)) {
+               ath_dbg(common, CALIBRATE, "Tx IQ Cal is not completed\n");
+               return false;
+       }
+       return true;
+}
+
+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
+               AR_PHY_TX_IQCAL_STATUS_B0,
+               AR_PHY_TX_IQCAL_STATUS_B1,
+               AR_PHY_TX_IQCAL_STATUS_B2,
+       };
+       const u_int32_t chan_info_tab[] = {
+               AR_PHY_CHAN_INFO_TAB_0,
+               AR_PHY_CHAN_INFO_TAB_1,
+               AR_PHY_CHAN_INFO_TAB_2,
+       };
+       struct coeff coeff;
+       s32 iq_res[6];
+       int i, im, j;
+       int nmeasurement;
+
+       for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+               if (!(ah->txchainmask & (1 << i)))
+                       continue;
+
+               nmeasurement = REG_READ_FIELD(ah,
+                               AR_PHY_TX_IQCAL_STATUS_B0,
+                               AR_PHY_CALIBRATED_GAINS_0);
+               if (nmeasurement > MAX_MEASUREMENT)
+                       nmeasurement = MAX_MEASUREMENT;
+
+               for (im = 0; im < nmeasurement; im++) {
+                       ath_dbg(common, CALIBRATE,
+                               "Doing Tx IQ Cal for chain %d\n", i);
+
+                       if (REG_READ(ah, txiqcal_status[i]) &
+                                       AR_PHY_TX_IQCAL_STATUS_FAILED) {
+                               ath_dbg(common, CALIBRATE,
+                                       "Tx IQ Cal failed for chain %d\n", i);
+                               goto tx_iqcal_fail;
+                       }
+
+                       for (j = 0; j < 3; j++) {
+                               u32 idx = 2 * j, offset = 4 * (3 * im + j);
+
+                               REG_RMW_FIELD(ah,
+                                               AR_PHY_CHAN_INFO_MEMORY,
+                                               AR_PHY_CHAN_INFO_TAB_S2_READ,
+                                               0);
+
+                               /* 32 bits */
+                               iq_res[idx] = REG_READ(ah,
+                                               chan_info_tab[i] +
+                                               offset);
+
+                               REG_RMW_FIELD(ah,
+                                               AR_PHY_CHAN_INFO_MEMORY,
+                                               AR_PHY_CHAN_INFO_TAB_S2_READ,
+                                               1);
+
+                               /* 16 bits */
+                               iq_res[idx + 1] = 0xffff & REG_READ(ah,
+                                               chan_info_tab[i] + offset);
+
+                               ath_dbg(common, CALIBRATE,
+                                       "IQ_RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
+                                       idx, iq_res[idx], idx + 1,
+                                       iq_res[idx + 1]);
+                       }
+
+                       if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
+                                               coeff.iqc_coeff)) {
+                               ath_dbg(common, CALIBRATE,
+                                       "Failed in calculation of IQ correction\n");
+                               goto tx_iqcal_fail;
+                       }
+
+                       coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
+                       coeff.phs_coeff[i][im] =
+                               (coeff.iqc_coeff[0] >> 7) & 0x7f;
+
+                       if (coeff.mag_coeff[i][im] > 63)
+                               coeff.mag_coeff[i][im] -= 128;
+                       if (coeff.phs_coeff[i][im] > 63)
+                               coeff.phs_coeff[i][im] -= 128;
+               }
+       }
+       ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable);
+
+       return;
+
+tx_iqcal_fail:
+       ath_dbg(common, CALIBRATE, "Tx IQ Cal failed\n");
+       return;
+}
+
+static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
+{
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+       u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
+       int i, im;
+
+       memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
+       for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
+               tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
+                                       AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
+               if (!AR_SREV_9485(ah)) {
+                       tx_corr_coeff[i * 2][1] =
+                       tx_corr_coeff[(i * 2) + 1][1] =
+                                       AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
+
+                       tx_corr_coeff[i * 2][2] =
+                       tx_corr_coeff[(i * 2) + 1][2] =
+                                       AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
+               }
+       }
+
+       for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+               if (!(ah->txchainmask & (1 << i)))
+                       continue;
+
+               for (im = 0; im < caldata->num_measures[i]; im++) {
+                       if ((im % 2) == 0)
+                               REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+                                    AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
+                                    caldata->tx_corr_coeff[im][i]);
+                       else
+                               REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+                                    AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
+                                    caldata->tx_corr_coeff[im][i]);
+               }
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
+                     AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
+       REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
+                     AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
+}
+
+static bool ar9003_hw_init_cal(struct ath_hw *ah,
+                              struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+       bool txiqcal_done = false, txclcal_done = false;
+       bool is_reusable = true, status = true;
+       bool run_rtt_cal = false, run_agc_cal;
+       bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT);
+       u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL |
+                                         AR_PHY_AGC_CONTROL_FLTR_CAL   |
+                                         AR_PHY_AGC_CONTROL_PKDET_CAL;
+       int i, j;
+       u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0,
+                                         AR_PHY_CL_TAB_1,
+                                         AR_PHY_CL_TAB_2 };
+
+       if (rtt) {
+               if (!ar9003_hw_rtt_restore(ah, chan))
+                       run_rtt_cal = true;
+
+               if (run_rtt_cal)
+                       ath_dbg(common, CALIBRATE,
+                               "RTT calibration to be done\n");
+       }
+
+       run_agc_cal = run_rtt_cal;
+
+       if (run_rtt_cal) {
+               ar9003_hw_rtt_enable(ah);
+               ar9003_hw_rtt_set_mask(ah, 0x00);
+               ar9003_hw_rtt_clear_hist(ah);
+       }
+
+       if (rtt && !run_rtt_cal) {
+               agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL);
+               agc_supp_cals &= agc_ctrl;
+               agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL |
+                            AR_PHY_AGC_CONTROL_FLTR_CAL |
+                            AR_PHY_AGC_CONTROL_PKDET_CAL);
+               REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
+       }
+
+       if (ah->enabled_cals & TX_CL_CAL) {
+               if (caldata && caldata->done_txclcal_once)
+                       REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
+                                   AR_PHY_CL_CAL_ENABLE);
+               else {
+                       REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL,
+                                   AR_PHY_CL_CAL_ENABLE);
+                       run_agc_cal = true;
+               }
+       }
+
+       if (!(ah->enabled_cals & TX_IQ_CAL))
+               goto skip_tx_iqcal;
+
+       /* Do Tx IQ Calibration */
+       REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
+                     AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
+                     DELPT);
+
+       /*
+        * For AR9485 or later chips, TxIQ cal runs as part of
+        * AGC calibration
+        */
+       if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
+               if (caldata && !caldata->done_txiqcal_once)
+                       REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+                                   AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
+               else
+                       REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+                                   AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
+               txiqcal_done = run_agc_cal = true;
+               goto skip_tx_iqcal;
+       } else if (caldata && !caldata->done_txiqcal_once)
+               run_agc_cal = true;
+
+       if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
+               ar9003_mci_init_cal_req(ah, &is_reusable);
+
+       txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
+       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+       udelay(5);
+       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+skip_tx_iqcal:
+       if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
+               /* Calibrate the AGC */
+               REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+                         REG_READ(ah, AR_PHY_AGC_CONTROL) |
+                         AR_PHY_AGC_CONTROL_CAL);
+
+               /* Poll for offset calibration complete */
+               status = ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+                                      AR_PHY_AGC_CONTROL_CAL,
+                                      0, AH_WAIT_TIMEOUT);
+       }
+
+       if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
+               ar9003_mci_init_cal_done(ah);
+
+       if (rtt && !run_rtt_cal) {
+               agc_ctrl |= agc_supp_cals;
+               REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
+       }
+
+       if (!status) {
+               if (run_rtt_cal)
+                       ar9003_hw_rtt_disable(ah);
+
+               ath_dbg(common, CALIBRATE,
+                       "offset calibration failed to complete in 1ms; noisy environment?\n");
+               return false;
+       }
+
+       if (txiqcal_done)
+               ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
+       else if (caldata && caldata->done_txiqcal_once)
+               ar9003_hw_tx_iq_cal_reload(ah);
+
+#define CL_TAB_ENTRY(reg_base) (reg_base + (4 * j))
+       if (caldata && (ah->enabled_cals & TX_CL_CAL)) {
+               txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) &
+                                          AR_PHY_AGC_CONTROL_CLC_SUCCESS);
+               if (caldata->done_txclcal_once) {
+                       for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+                               if (!(ah->txchainmask & (1 << i)))
+                                       continue;
+                               for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
+                                       REG_WRITE(ah, CL_TAB_ENTRY(cl_idx[i]),
+                                                 caldata->tx_clcal[i][j]);
+                       }
+               } else if (is_reusable && txclcal_done) {
+                       for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+                               if (!(ah->txchainmask & (1 << i)))
+                                       continue;
+                               for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
+                                       caldata->tx_clcal[i][j] =
+                                               REG_READ(ah,
+                                                 CL_TAB_ENTRY(cl_idx[i]));
+                       }
+                       caldata->done_txclcal_once = true;
+               }
+       }
+#undef CL_TAB_ENTRY
+
+       if (run_rtt_cal && caldata) {
+               if (is_reusable) {
+                       if (!ath9k_hw_rfbus_req(ah))
+                               ath_err(ath9k_hw_common(ah),
+                                       "Could not stop baseband\n");
+                       else
+                               ar9003_hw_rtt_fill_hist(ah);
+
+                       ath9k_hw_rfbus_done(ah);
+               }
+
+               ar9003_hw_rtt_disable(ah);
+       }
+
+       /* Initialize list pointers */
+       ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+       ah->supp_cals = IQ_MISMATCH_CAL;
+
+       if (ah->supp_cals & IQ_MISMATCH_CAL) {
+               INIT_CAL(&ah->iq_caldata);
+               INSERT_CAL(ah, &ah->iq_caldata);
+               ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
+       }
+
+       if (ah->supp_cals & TEMP_COMP_CAL) {
+               INIT_CAL(&ah->tempCompCalData);
+               INSERT_CAL(ah, &ah->tempCompCalData);
+               ath_dbg(common, CALIBRATE,
+                       "enabling Temperature Compensation Calibration\n");
+       }
+
+       /* Initialize current pointer to first element in list */
+       ah->cal_list_curr = ah->cal_list;
+
+       if (ah->cal_list_curr)
+               ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
+
+       if (caldata)
+               caldata->CalValid = 0;
+
+       return true;
+}
+
+void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
+{
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+       struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+       priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
+       priv_ops->init_cal = ar9003_hw_init_cal;
+       priv_ops->setup_calibration = ar9003_hw_setup_calibration;
+
+       ops->calibrate = ar9003_hw_calibrate;
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_eeprom.c
new file mode 100644 (file)
index 0000000..1f7c28b
--- /dev/null
@@ -0,0 +1,5350 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <asm/unaligned.h>
+#include "hw.h"
+#include "ar9003_phy.h"
+#include "ar9003_eeprom.h"
+
+#define COMP_HDR_LEN 4
+#define COMP_CKSUM_LEN 2
+
+#define LE16(x) __constant_cpu_to_le16(x)
+#define LE32(x) __constant_cpu_to_le32(x)
+
+/* Local defines to distinguish between extension and control CTL's */
+#define EXT_ADDITIVE (0x8000)
+#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
+#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
+#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN   9  /* 10*log10(3)*2 */
+#define PWRINCR_3_TO_1_CHAIN      9             /* 10*log(3)*2 */
+#define PWRINCR_3_TO_2_CHAIN      3             /* floor(10*log(3/2)*2) */
+#define PWRINCR_2_TO_1_CHAIN      6             /* 10*log(2)*2 */
+
+#define SUB_NUM_CTL_MODES_AT_5G_40 2    /* excluding HT40, EXT-OFDM */
+#define SUB_NUM_CTL_MODES_AT_2G_40 3    /* excluding HT40, EXT-OFDM, EXT-CCK */
+
+#define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6))
+
+#define EEPROM_DATA_LEN_9485   1088
+
+static int ar9003_hw_power_interpolate(int32_t x,
+                                      int32_t *px, int32_t *py, u_int16_t np);
+
+
+static const struct ar9300_eeprom ar9300_default = {
+       .eepromVersion = 2,
+       .templateVersion = 2,
+       .macAddr = {0, 2, 3, 4, 5, 6},
+       .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       .baseEepHeader = {
+               .regDmn = { LE16(0), LE16(0x1f) },
+               .txrxMask =  0x77, /* 4 bits tx and 4 bits rx */
+               .opCapFlags = {
+                       .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+                       .eepMisc = 0,
+               },
+               .rfSilent = 0,
+               .blueToothOptions = 0,
+               .deviceCap = 0,
+               .deviceType = 5, /* takes lower byte in eeprom location */
+               .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+               .params_for_tuning_caps = {0, 0},
+               .featureEnable = 0x0c,
+                /*
+                 * bit0 - enable tx temp comp - disabled
+                 * bit1 - enable tx volt comp - disabled
+                 * bit2 - enable fastClock - enabled
+                 * bit3 - enable doubling - enabled
+                 * bit4 - enable internal regulator - disabled
+                 * bit5 - enable pa predistortion - disabled
+                 */
+               .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+               .eepromWriteEnableGpio = 3,
+               .wlanDisableGpio = 0,
+               .wlanLedGpio = 8,
+               .rxBandSelectGpio = 0xff,
+               .txrxgain = 0,
+               .swreg = 0,
+        },
+       .modalHeader2G = {
+       /* ar9300_modal_eep_header  2g */
+               /* 4 idle,t1,t2,b(4 bits per setting) */
+               .antCtrlCommon = LE32(0x110),
+               /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+               .antCtrlCommon2 = LE32(0x22222),
+
+               /*
+                * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+                * rx1, rx12, b (2 bits each)
+                */
+               .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
+
+               /*
+                * xatten1DB[AR9300_MAX_CHAINS];  3 xatten1_db
+                * for ar9280 (0xa20c/b20c 5:0)
+                */
+               .xatten1DB = {0, 0, 0},
+
+               /*
+                * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+                * for ar9280 (0xa20c/b20c 16:12
+                */
+               .xatten1Margin = {0, 0, 0},
+               .tempSlope = 36,
+               .voltSlope = 0,
+
+               /*
+                * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+                * channels in usual fbin coding format
+                */
+               .spurChans = {0, 0, 0, 0, 0},
+
+               /*
+                * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+                * if the register is per chain
+                */
+               .noiseFloorThreshCh = {-1, 0, 0},
+               .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               .quick_drop = 0,
+               .xpaBiasLvl = 0,
+               .txFrameToDataStart = 0x0e,
+               .txFrameToPaOn = 0x0e,
+               .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+               .antennaGain = 0,
+               .switchSettling = 0x2c,
+               .adcDesiredSize = -30,
+               .txEndToXpaOff = 0,
+               .txEndToRxOn = 0x2,
+               .txFrameToXpaOn = 0xe,
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+               .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0, 0,
+               },
+        },
+       .base_ext1 = {
+               .ant_div_control = 0,
+               .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+       },
+       .calFreqPier2G = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1),
+        },
+       /* ar9300_cal_data_per_freq_op_loop 2g */
+       .calPierData2G = {
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+        },
+       .calTarget_freqbin_Cck = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2484, 1),
+        },
+       .calTarget_freqbin_2G = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+        },
+       .calTarget_freqbin_2GHT20 = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+        },
+       .calTarget_freqbin_2GHT40 = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+        },
+       .calTargetPowerCck = {
+                /* 1L-5L,5S,11L,11S */
+                { {36, 36, 36, 36} },
+                { {36, 36, 36, 36} },
+       },
+       .calTargetPower2G = {
+                /* 6-24,36,48,54 */
+                { {32, 32, 28, 24} },
+                { {32, 32, 28, 24} },
+                { {32, 32, 28, 24} },
+       },
+       .calTargetPower2GHT20 = {
+               { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+               { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+               { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+       },
+       .calTargetPower2GHT40 = {
+               { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+               { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+               { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
+       },
+       .ctlIndex_2G =  {
+               0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+               0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+       },
+       .ctl_freqbin_2G = {
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2457, 1),
+                       FREQ2FBIN(2462, 1)
+               },
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2462, 1),
+                       0xFF,
+               },
+
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2462, 1),
+                       0xFF,
+               },
+               {
+                       FREQ2FBIN(2422, 1),
+                       FREQ2FBIN(2427, 1),
+                       FREQ2FBIN(2447, 1),
+                       FREQ2FBIN(2452, 1)
+               },
+
+               {
+                       /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+               },
+
+               {
+                       /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0,
+               },
+
+               {
+                       /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2472, 1),
+                       0,
+               },
+
+               {
+                       /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+                       /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+                       /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+                       /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+               },
+
+               {
+                       /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+               },
+
+               {
+                       /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0
+               },
+
+               {
+                       /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0
+               },
+
+               {
+                       /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+                       /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+                       /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+                       /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+               }
+        },
+       .ctlPowerData_2G = {
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+        },
+       .modalHeader5G = {
+               /* 4 idle,t1,t2,b (4 bits per setting) */
+               .antCtrlCommon = LE32(0x110),
+               /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+               .antCtrlCommon2 = LE32(0x22222),
+                /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+               .antCtrlChain = {
+                       LE16(0x000), LE16(0x000), LE16(0x000),
+               },
+                /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+               .xatten1DB = {0, 0, 0},
+
+               /*
+                * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+                * for merlin (0xa20c/b20c 16:12
+                */
+               .xatten1Margin = {0, 0, 0},
+               .tempSlope = 68,
+               .voltSlope = 0,
+               /* spurChans spur channels in usual fbin coding format */
+               .spurChans = {0, 0, 0, 0, 0},
+               /* noiseFloorThreshCh Check if the register is per chain */
+               .noiseFloorThreshCh = {-1, 0, 0},
+               .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               .quick_drop = 0,
+               .xpaBiasLvl = 0,
+               .txFrameToDataStart = 0x0e,
+               .txFrameToPaOn = 0x0e,
+               .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+               .antennaGain = 0,
+               .switchSettling = 0x2d,
+               .adcDesiredSize = -30,
+               .txEndToXpaOff = 0,
+               .txEndToRxOn = 0x2,
+               .txFrameToXpaOn = 0xe,
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0c80c080),
+               .papdRateMaskHt40 = LE32(0x0080c080),
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0, 0,
+               },
+        },
+       .base_ext2 = {
+               .tempSlopeLow = 0,
+               .tempSlopeHigh = 0,
+               .xatten1DBLow = {0, 0, 0},
+               .xatten1MarginLow = {0, 0, 0},
+               .xatten1DBHigh = {0, 0, 0},
+               .xatten1MarginHigh = {0, 0, 0}
+       },
+       .calFreqPier5G = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5220, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5725, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calPierData5G = {
+                       {
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                       },
+                       {
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                       },
+                       {
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                       },
+
+       },
+       .calTarget_freqbin_5G = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5220, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5725, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTarget_freqbin_5GHT20 = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5240, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5745, 0),
+               FREQ2FBIN(5725, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTarget_freqbin_5GHT40 = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5240, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5745, 0),
+               FREQ2FBIN(5725, 0),
+               FREQ2FBIN(5825, 0)
+        },
+       .calTargetPower5G = {
+               /* 6-24,36,48,54 */
+               { {20, 20, 20, 10} },
+               { {20, 20, 20, 10} },
+               { {20, 20, 20, 10} },
+               { {20, 20, 20, 10} },
+               { {20, 20, 20, 10} },
+               { {20, 20, 20, 10} },
+               { {20, 20, 20, 10} },
+               { {20, 20, 20, 10} },
+        },
+       .calTargetPower5GHT20 = {
+               /*
+                * 0_8_16,1-3_9-11_17-19,
+                * 4,5,6,7,12,13,14,15,20,21,22,23
+                */
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+        },
+       .calTargetPower5GHT40 =  {
+               /*
+                * 0_8_16,1-3_9-11_17-19,
+                * 4,5,6,7,12,13,14,15,20,21,22,23
+                */
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+               { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
+        },
+       .ctlIndex_5G =  {
+               0x10, 0x16, 0x18, 0x40, 0x46,
+               0x48, 0x30, 0x36, 0x38
+       },
+       .ctl_freqbin_5G =  {
+               {
+                       /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+                       /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+                       /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+               {
+                       /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+                       /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+                       /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+
+               {
+                       /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+                       /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+                       /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+                       /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+               },
+
+               {
+                       /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+                       /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+                       /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+               },
+
+               {
+                       /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+               },
+
+               {
+                       /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+                       /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+                       /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[5].ctlEdges[7].bChannel */ 0xFF
+               },
+
+               {
+                       /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+                       /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+                       /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+                       /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+               },
+
+               {
+                       /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+                       /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+                       /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+
+               {
+                       /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+                       /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+                       /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+                       /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+               }
+        },
+       .ctlPowerData_5G = {
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                       }
+               },
+        }
+};
+
+static const struct ar9300_eeprom ar9300_x113 = {
+       .eepromVersion = 2,
+       .templateVersion = 6,
+       .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+       .custData = {"x113-023-f0000"},
+       .baseEepHeader = {
+               .regDmn = { LE16(0), LE16(0x1f) },
+               .txrxMask =  0x77, /* 4 bits tx and 4 bits rx */
+               .opCapFlags = {
+                       .opFlags = AR5416_OPFLAGS_11A,
+                       .eepMisc = 0,
+               },
+               .rfSilent = 0,
+               .blueToothOptions = 0,
+               .deviceCap = 0,
+               .deviceType = 5, /* takes lower byte in eeprom location */
+               .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+               .params_for_tuning_caps = {0, 0},
+               .featureEnable = 0x0d,
+                /*
+                 * bit0 - enable tx temp comp - disabled
+                 * bit1 - enable tx volt comp - disabled
+                 * bit2 - enable fastClock - enabled
+                 * bit3 - enable doubling - enabled
+                 * bit4 - enable internal regulator - disabled
+                 * bit5 - enable pa predistortion - disabled
+                 */
+               .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+               .eepromWriteEnableGpio = 6,
+               .wlanDisableGpio = 0,
+               .wlanLedGpio = 8,
+               .rxBandSelectGpio = 0xff,
+               .txrxgain = 0x21,
+               .swreg = 0,
+        },
+       .modalHeader2G = {
+       /* ar9300_modal_eep_header  2g */
+               /* 4 idle,t1,t2,b(4 bits per setting) */
+               .antCtrlCommon = LE32(0x110),
+               /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+               .antCtrlCommon2 = LE32(0x44444),
+
+               /*
+                * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+                * rx1, rx12, b (2 bits each)
+                */
+               .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
+
+               /*
+                * xatten1DB[AR9300_MAX_CHAINS];  3 xatten1_db
+                * for ar9280 (0xa20c/b20c 5:0)
+                */
+               .xatten1DB = {0, 0, 0},
+
+               /*
+                * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+                * for ar9280 (0xa20c/b20c 16:12
+                */
+               .xatten1Margin = {0, 0, 0},
+               .tempSlope = 25,
+               .voltSlope = 0,
+
+               /*
+                * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+                * channels in usual fbin coding format
+                */
+               .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+               /*
+                * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+                * if the register is per chain
+                */
+               .noiseFloorThreshCh = {-1, 0, 0},
+               .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               .quick_drop = 0,
+               .xpaBiasLvl = 0,
+               .txFrameToDataStart = 0x0e,
+               .txFrameToPaOn = 0x0e,
+               .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+               .antennaGain = 0,
+               .switchSettling = 0x2c,
+               .adcDesiredSize = -30,
+               .txEndToXpaOff = 0,
+               .txEndToRxOn = 0x2,
+               .txFrameToXpaOn = 0xe,
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0c80c080),
+               .papdRateMaskHt40 = LE32(0x0080c080),
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0, 0,
+               },
+        },
+        .base_ext1 = {
+               .ant_div_control = 0,
+               .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+        },
+       .calFreqPier2G = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1),
+        },
+       /* ar9300_cal_data_per_freq_op_loop 2g */
+       .calPierData2G = {
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+        },
+       .calTarget_freqbin_Cck = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2472, 1),
+        },
+       .calTarget_freqbin_2G = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+        },
+       .calTarget_freqbin_2GHT20 = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+        },
+       .calTarget_freqbin_2GHT40 = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+        },
+       .calTargetPowerCck = {
+                /* 1L-5L,5S,11L,11S */
+                { {34, 34, 34, 34} },
+                { {34, 34, 34, 34} },
+       },
+       .calTargetPower2G = {
+                /* 6-24,36,48,54 */
+                { {34, 34, 32, 32} },
+                { {34, 34, 32, 32} },
+                { {34, 34, 32, 32} },
+       },
+       .calTargetPower2GHT20 = {
+               { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+               { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+               { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+       },
+       .calTargetPower2GHT40 = {
+               { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+               { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+               { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+       },
+       .ctlIndex_2G =  {
+               0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+               0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+       },
+       .ctl_freqbin_2G = {
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2457, 1),
+                       FREQ2FBIN(2462, 1)
+               },
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2462, 1),
+                       0xFF,
+               },
+
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2462, 1),
+                       0xFF,
+               },
+               {
+                       FREQ2FBIN(2422, 1),
+                       FREQ2FBIN(2427, 1),
+                       FREQ2FBIN(2447, 1),
+                       FREQ2FBIN(2452, 1)
+               },
+
+               {
+                       /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+               },
+
+               {
+                       /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0,
+               },
+
+               {
+                       /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2472, 1),
+                       0,
+               },
+
+               {
+                       /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+                       /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+                       /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+                       /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+               },
+
+               {
+                       /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+               },
+
+               {
+                       /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0
+               },
+
+               {
+                       /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0
+               },
+
+               {
+                       /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+                       /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+                       /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+                       /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+               }
+        },
+       .ctlPowerData_2G = {
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+        },
+       .modalHeader5G = {
+               /* 4 idle,t1,t2,b (4 bits per setting) */
+               .antCtrlCommon = LE32(0x220),
+               /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+               .antCtrlCommon2 = LE32(0x11111),
+                /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+               .antCtrlChain = {
+                       LE16(0x150), LE16(0x150), LE16(0x150),
+               },
+                /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+               .xatten1DB = {0, 0, 0},
+
+               /*
+                * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+                * for merlin (0xa20c/b20c 16:12
+                */
+               .xatten1Margin = {0, 0, 0},
+               .tempSlope = 68,
+               .voltSlope = 0,
+               /* spurChans spur channels in usual fbin coding format */
+               .spurChans = {FREQ2FBIN(5500, 0), 0, 0, 0, 0},
+               /* noiseFloorThreshCh Check if the register is per chain */
+               .noiseFloorThreshCh = {-1, 0, 0},
+               .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               .quick_drop = 0,
+               .xpaBiasLvl = 0xf,
+               .txFrameToDataStart = 0x0e,
+               .txFrameToPaOn = 0x0e,
+               .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+               .antennaGain = 0,
+               .switchSettling = 0x2d,
+               .adcDesiredSize = -30,
+               .txEndToXpaOff = 0,
+               .txEndToRxOn = 0x2,
+               .txFrameToXpaOn = 0xe,
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+               .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0, 0,
+               },
+        },
+       .base_ext2 = {
+               .tempSlopeLow = 72,
+               .tempSlopeHigh = 105,
+               .xatten1DBLow = {0, 0, 0},
+               .xatten1MarginLow = {0, 0, 0},
+               .xatten1DBHigh = {0, 0, 0},
+               .xatten1MarginHigh = {0, 0, 0}
+        },
+       .calFreqPier5G = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5240, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5745, 0),
+               FREQ2FBIN(5785, 0)
+       },
+       .calPierData5G = {
+                       {
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                       },
+                       {
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                       },
+                       {
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                       },
+
+       },
+       .calTarget_freqbin_5G = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5220, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5745, 0),
+               FREQ2FBIN(5785, 0)
+       },
+       .calTarget_freqbin_5GHT20 = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5240, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5745, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTarget_freqbin_5GHT40 = {
+               FREQ2FBIN(5190, 0),
+               FREQ2FBIN(5230, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5410, 0),
+               FREQ2FBIN(5510, 0),
+               FREQ2FBIN(5670, 0),
+               FREQ2FBIN(5755, 0),
+               FREQ2FBIN(5825, 0)
+        },
+       .calTargetPower5G = {
+               /* 6-24,36,48,54 */
+               { {42, 40, 40, 34} },
+               { {42, 40, 40, 34} },
+               { {42, 40, 40, 34} },
+               { {42, 40, 40, 34} },
+               { {42, 40, 40, 34} },
+               { {42, 40, 40, 34} },
+               { {42, 40, 40, 34} },
+               { {42, 40, 40, 34} },
+        },
+       .calTargetPower5GHT20 = {
+               /*
+                * 0_8_16,1-3_9-11_17-19,
+                * 4,5,6,7,12,13,14,15,20,21,22,23
+                */
+               { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+               { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+               { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+               { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+               { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+               { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+               { {38, 38, 38, 38, 32, 28, 38, 38, 32, 28, 38, 38, 32, 26} },
+               { {36, 36, 36, 36, 32, 28, 36, 36, 32, 28, 36, 36, 32, 26} },
+        },
+       .calTargetPower5GHT40 =  {
+               /*
+                * 0_8_16,1-3_9-11_17-19,
+                * 4,5,6,7,12,13,14,15,20,21,22,23
+                */
+               { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+               { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+               { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+               { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+               { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+               { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+               { {36, 36, 36, 36, 30, 26, 36, 36, 30, 26, 36, 36, 30, 24} },
+               { {34, 34, 34, 34, 30, 26, 34, 34, 30, 26, 34, 34, 30, 24} },
+        },
+       .ctlIndex_5G =  {
+               0x10, 0x16, 0x18, 0x40, 0x46,
+               0x48, 0x30, 0x36, 0x38
+       },
+       .ctl_freqbin_5G =  {
+               {
+                       /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+                       /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+                       /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+               {
+                       /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+                       /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+                       /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+
+               {
+                       /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+                       /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+                       /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+                       /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+               },
+
+               {
+                       /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+                       /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+                       /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+               },
+
+               {
+                       /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+               },
+
+               {
+                       /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+                       /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+                       /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[5].ctlEdges[7].bChannel */ 0xFF
+               },
+
+               {
+                       /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+                       /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+                       /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+                       /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+               },
+
+               {
+                       /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+                       /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+                       /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+
+               {
+                       /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+                       /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+                       /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+                       /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+               }
+        },
+       .ctlPowerData_5G = {
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                       }
+               },
+        }
+};
+
+
+static const struct ar9300_eeprom ar9300_h112 = {
+       .eepromVersion = 2,
+       .templateVersion = 3,
+       .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+       .custData = {"h112-241-f0000"},
+       .baseEepHeader = {
+               .regDmn = { LE16(0), LE16(0x1f) },
+               .txrxMask =  0x77, /* 4 bits tx and 4 bits rx */
+               .opCapFlags = {
+                       .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+                       .eepMisc = 0,
+               },
+               .rfSilent = 0,
+               .blueToothOptions = 0,
+               .deviceCap = 0,
+               .deviceType = 5, /* takes lower byte in eeprom location */
+               .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+               .params_for_tuning_caps = {0, 0},
+               .featureEnable = 0x0d,
+               /*
+                * bit0 - enable tx temp comp - disabled
+                * bit1 - enable tx volt comp - disabled
+                * bit2 - enable fastClock - enabled
+                * bit3 - enable doubling - enabled
+                * bit4 - enable internal regulator - disabled
+                * bit5 - enable pa predistortion - disabled
+                */
+               .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+               .eepromWriteEnableGpio = 6,
+               .wlanDisableGpio = 0,
+               .wlanLedGpio = 8,
+               .rxBandSelectGpio = 0xff,
+               .txrxgain = 0x10,
+               .swreg = 0,
+       },
+       .modalHeader2G = {
+               /* ar9300_modal_eep_header  2g */
+               /* 4 idle,t1,t2,b(4 bits per setting) */
+               .antCtrlCommon = LE32(0x110),
+               /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+               .antCtrlCommon2 = LE32(0x44444),
+
+               /*
+                * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+                * rx1, rx12, b (2 bits each)
+                */
+               .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
+
+               /*
+                * xatten1DB[AR9300_MAX_CHAINS];  3 xatten1_db
+                * for ar9280 (0xa20c/b20c 5:0)
+                */
+               .xatten1DB = {0, 0, 0},
+
+               /*
+                * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+                * for ar9280 (0xa20c/b20c 16:12
+                */
+               .xatten1Margin = {0, 0, 0},
+               .tempSlope = 25,
+               .voltSlope = 0,
+
+               /*
+                * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+                * channels in usual fbin coding format
+                */
+               .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+               /*
+                * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+                * if the register is per chain
+                */
+               .noiseFloorThreshCh = {-1, 0, 0},
+               .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               .quick_drop = 0,
+               .xpaBiasLvl = 0,
+               .txFrameToDataStart = 0x0e,
+               .txFrameToPaOn = 0x0e,
+               .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+               .antennaGain = 0,
+               .switchSettling = 0x2c,
+               .adcDesiredSize = -30,
+               .txEndToXpaOff = 0,
+               .txEndToRxOn = 0x2,
+               .txFrameToXpaOn = 0xe,
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0c80c080),
+               .papdRateMaskHt40 = LE32(0x0080c080),
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0, 0,
+               },
+       },
+       .base_ext1 = {
+               .ant_div_control = 0,
+               .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+       },
+       .calFreqPier2G = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2462, 1),
+       },
+       /* ar9300_cal_data_per_freq_op_loop 2g */
+       .calPierData2G = {
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+       },
+       .calTarget_freqbin_Cck = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2472, 1),
+       },
+       .calTarget_freqbin_2G = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+       },
+       .calTarget_freqbin_2GHT20 = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+       },
+       .calTarget_freqbin_2GHT40 = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+       },
+       .calTargetPowerCck = {
+               /* 1L-5L,5S,11L,11S */
+               { {34, 34, 34, 34} },
+               { {34, 34, 34, 34} },
+       },
+       .calTargetPower2G = {
+               /* 6-24,36,48,54 */
+               { {34, 34, 32, 32} },
+               { {34, 34, 32, 32} },
+               { {34, 34, 32, 32} },
+       },
+       .calTargetPower2GHT20 = {
+               { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+               { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+               { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+       },
+       .calTargetPower2GHT40 = {
+               { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+               { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+               { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+       },
+       .ctlIndex_2G =  {
+               0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+               0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+       },
+       .ctl_freqbin_2G = {
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2457, 1),
+                       FREQ2FBIN(2462, 1)
+               },
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2462, 1),
+                       0xFF,
+               },
+
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2462, 1),
+                       0xFF,
+               },
+               {
+                       FREQ2FBIN(2422, 1),
+                       FREQ2FBIN(2427, 1),
+                       FREQ2FBIN(2447, 1),
+                       FREQ2FBIN(2452, 1)
+               },
+
+               {
+                       /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+               },
+
+               {
+                       /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0,
+               },
+
+               {
+                       /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2472, 1),
+                       0,
+               },
+
+               {
+                       /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+                       /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+                       /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+                       /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+               },
+
+               {
+                       /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+               },
+
+               {
+                       /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0
+               },
+
+               {
+                       /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0
+               },
+
+               {
+                       /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+                       /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+                       /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+                       /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+               }
+       },
+       .ctlPowerData_2G = {
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+               { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+       },
+       .modalHeader5G = {
+               /* 4 idle,t1,t2,b (4 bits per setting) */
+               .antCtrlCommon = LE32(0x220),
+               /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+               .antCtrlCommon2 = LE32(0x44444),
+               /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+               .antCtrlChain = {
+                       LE16(0x150), LE16(0x150), LE16(0x150),
+               },
+               /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+               .xatten1DB = {0, 0, 0},
+
+               /*
+                * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+                * for merlin (0xa20c/b20c 16:12
+                */
+               .xatten1Margin = {0, 0, 0},
+               .tempSlope = 45,
+               .voltSlope = 0,
+               /* spurChans spur channels in usual fbin coding format */
+               .spurChans = {0, 0, 0, 0, 0},
+               /* noiseFloorThreshCh Check if the register is per chain */
+               .noiseFloorThreshCh = {-1, 0, 0},
+               .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               .quick_drop = 0,
+               .xpaBiasLvl = 0,
+               .txFrameToDataStart = 0x0e,
+               .txFrameToPaOn = 0x0e,
+               .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+               .antennaGain = 0,
+               .switchSettling = 0x2d,
+               .adcDesiredSize = -30,
+               .txEndToXpaOff = 0,
+               .txEndToRxOn = 0x2,
+               .txFrameToXpaOn = 0xe,
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+               .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0, 0,
+               },
+       },
+       .base_ext2 = {
+               .tempSlopeLow = 40,
+               .tempSlopeHigh = 50,
+               .xatten1DBLow = {0, 0, 0},
+               .xatten1MarginLow = {0, 0, 0},
+               .xatten1DBHigh = {0, 0, 0},
+               .xatten1MarginHigh = {0, 0, 0}
+       },
+       .calFreqPier5G = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5220, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5785, 0)
+       },
+       .calPierData5G = {
+               {
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+               },
+               {
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+               },
+               {
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+               },
+
+       },
+       .calTarget_freqbin_5G = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5240, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTarget_freqbin_5GHT20 = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5240, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5745, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTarget_freqbin_5GHT40 = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5240, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5745, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTargetPower5G = {
+               /* 6-24,36,48,54 */
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+       },
+       .calTargetPower5GHT20 = {
+               /*
+                * 0_8_16,1-3_9-11_17-19,
+                * 4,5,6,7,12,13,14,15,20,21,22,23
+                */
+               { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} },
+               { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} },
+               { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} },
+               { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} },
+               { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} },
+               { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} },
+               { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} },
+               { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} },
+       },
+       .calTargetPower5GHT40 =  {
+               /*
+                * 0_8_16,1-3_9-11_17-19,
+                * 4,5,6,7,12,13,14,15,20,21,22,23
+                */
+               { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} },
+               { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} },
+               { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} },
+               { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} },
+               { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} },
+               { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} },
+               { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} },
+               { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} },
+       },
+       .ctlIndex_5G =  {
+               0x10, 0x16, 0x18, 0x40, 0x46,
+               0x48, 0x30, 0x36, 0x38
+       },
+       .ctl_freqbin_5G =  {
+               {
+                       /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+                       /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+                       /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+               {
+                       /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+                       /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+                       /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+
+               {
+                       /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+                       /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+                       /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+                       /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+               },
+
+               {
+                       /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+                       /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+                       /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+               },
+
+               {
+                       /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+               },
+
+               {
+                       /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+                       /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+                       /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[5].ctlEdges[7].bChannel */ 0xFF
+               },
+
+               {
+                       /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+                       /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+                       /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+                       /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+               },
+
+               {
+                       /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+                       /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+                       /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+
+               {
+                       /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+                       /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+                       /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+                       /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+               }
+       },
+       .ctlPowerData_5G = {
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                       }
+               },
+       }
+};
+
+
+static const struct ar9300_eeprom ar9300_x112 = {
+       .eepromVersion = 2,
+       .templateVersion = 5,
+       .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+       .custData = {"x112-041-f0000"},
+       .baseEepHeader = {
+               .regDmn = { LE16(0), LE16(0x1f) },
+               .txrxMask =  0x77, /* 4 bits tx and 4 bits rx */
+               .opCapFlags = {
+                       .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+                       .eepMisc = 0,
+               },
+               .rfSilent = 0,
+               .blueToothOptions = 0,
+               .deviceCap = 0,
+               .deviceType = 5, /* takes lower byte in eeprom location */
+               .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+               .params_for_tuning_caps = {0, 0},
+               .featureEnable = 0x0d,
+               /*
+                * bit0 - enable tx temp comp - disabled
+                * bit1 - enable tx volt comp - disabled
+                * bit2 - enable fastclock - enabled
+                * bit3 - enable doubling - enabled
+                * bit4 - enable internal regulator - disabled
+                * bit5 - enable pa predistortion - disabled
+                */
+               .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+               .eepromWriteEnableGpio = 6,
+               .wlanDisableGpio = 0,
+               .wlanLedGpio = 8,
+               .rxBandSelectGpio = 0xff,
+               .txrxgain = 0x0,
+               .swreg = 0,
+       },
+       .modalHeader2G = {
+               /* ar9300_modal_eep_header  2g */
+               /* 4 idle,t1,t2,b(4 bits per setting) */
+               .antCtrlCommon = LE32(0x110),
+               /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+               .antCtrlCommon2 = LE32(0x22222),
+
+               /*
+                * antCtrlChain[ar9300_max_chains]; 6 idle, t, r,
+                * rx1, rx12, b (2 bits each)
+                */
+               .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) },
+
+               /*
+                * xatten1DB[AR9300_max_chains];  3 xatten1_db
+                * for ar9280 (0xa20c/b20c 5:0)
+                */
+               .xatten1DB = {0x1b, 0x1b, 0x1b},
+
+               /*
+                * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin
+                * for ar9280 (0xa20c/b20c 16:12
+                */
+               .xatten1Margin = {0x15, 0x15, 0x15},
+               .tempSlope = 50,
+               .voltSlope = 0,
+
+               /*
+                * spurChans[OSPrey_eeprom_modal_sPURS]; spur
+                * channels in usual fbin coding format
+                */
+               .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+               /*
+                * noiseFloorThreshch[ar9300_max_cHAINS]; 3 Check
+                * if the register is per chain
+                */
+               .noiseFloorThreshCh = {-1, 0, 0},
+               .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               .quick_drop = 0,
+               .xpaBiasLvl = 0,
+               .txFrameToDataStart = 0x0e,
+               .txFrameToPaOn = 0x0e,
+               .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+               .antennaGain = 0,
+               .switchSettling = 0x2c,
+               .adcDesiredSize = -30,
+               .txEndToXpaOff = 0,
+               .txEndToRxOn = 0x2,
+               .txFrameToXpaOn = 0xe,
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0c80c080),
+               .papdRateMaskHt40 = LE32(0x0080c080),
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0, 0,
+               },
+       },
+       .base_ext1 = {
+               .ant_div_control = 0,
+               .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+       },
+       .calFreqPier2G = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1),
+       },
+       /* ar9300_cal_data_per_freq_op_loop 2g */
+       .calPierData2G = {
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+       },
+       .calTarget_freqbin_Cck = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2472, 1),
+       },
+       .calTarget_freqbin_2G = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+       },
+       .calTarget_freqbin_2GHT20 = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+       },
+       .calTarget_freqbin_2GHT40 = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+       },
+       .calTargetPowerCck = {
+               /* 1L-5L,5S,11L,11s */
+               { {38, 38, 38, 38} },
+               { {38, 38, 38, 38} },
+       },
+       .calTargetPower2G = {
+               /* 6-24,36,48,54 */
+               { {38, 38, 36, 34} },
+               { {38, 38, 36, 34} },
+               { {38, 38, 34, 32} },
+       },
+       .calTargetPower2GHT20 = {
+               { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} },
+               { {36, 36, 36, 36, 36, 34, 36, 34, 32, 30, 30, 30, 28, 26} },
+               { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} },
+       },
+       .calTargetPower2GHT40 = {
+               { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} },
+               { {36, 36, 36, 36, 34, 32, 34, 32, 30, 28, 28, 28, 28, 24} },
+               { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} },
+       },
+       .ctlIndex_2G =  {
+               0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+               0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+       },
+       .ctl_freqbin_2G = {
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2457, 1),
+                       FREQ2FBIN(2462, 1)
+               },
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2462, 1),
+                       0xFF,
+               },
+
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2462, 1),
+                       0xFF,
+               },
+               {
+                       FREQ2FBIN(2422, 1),
+                       FREQ2FBIN(2427, 1),
+                       FREQ2FBIN(2447, 1),
+                       FREQ2FBIN(2452, 1)
+               },
+
+               {
+                       /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+                       /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+                       /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+                       /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(2484, 1),
+               },
+
+               {
+                       /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+                       /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+                       /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+                       0,
+               },
+
+               {
+                       /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+                       /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2472, 1),
+                       0,
+               },
+
+               {
+                       /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(2422, 1),
+                       /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(2427, 1),
+                       /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(2447, 1),
+                       /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(2462, 1),
+               },
+
+               {
+                       /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+                       /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+                       /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+               },
+
+               {
+                       /* Data[9].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+                       /* Data[9].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+                       /* Data[9].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+                       0
+               },
+
+               {
+                       /* Data[10].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+                       /* Data[10].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+                       /* Data[10].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+                       0
+               },
+
+               {
+                       /* Data[11].ctledges[0].bchannel */ FREQ2FBIN(2422, 1),
+                       /* Data[11].ctledges[1].bchannel */ FREQ2FBIN(2427, 1),
+                       /* Data[11].ctledges[2].bchannel */ FREQ2FBIN(2447, 1),
+                       /* Data[11].ctledges[3].bchannel */ FREQ2FBIN(2462, 1),
+               }
+       },
+       .ctlPowerData_2G = {
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+               { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+               { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+       },
+       .modalHeader5G = {
+               /* 4 idle,t1,t2,b (4 bits per setting) */
+               .antCtrlCommon = LE32(0x110),
+               /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+               .antCtrlCommon2 = LE32(0x22222),
+               /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+               .antCtrlChain = {
+                       LE16(0x0), LE16(0x0), LE16(0x0),
+               },
+               /* xatten1DB 3 xatten1_db for ar9280 (0xa20c/b20c 5:0) */
+               .xatten1DB = {0x13, 0x19, 0x17},
+
+               /*
+                * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin
+                * for merlin (0xa20c/b20c 16:12
+                */
+               .xatten1Margin = {0x19, 0x19, 0x19},
+               .tempSlope = 70,
+               .voltSlope = 15,
+               /* spurChans spur channels in usual fbin coding format */
+               .spurChans = {0, 0, 0, 0, 0},
+               /* noiseFloorThreshch check if the register is per chain */
+               .noiseFloorThreshCh = {-1, 0, 0},
+               .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               .quick_drop = 0,
+               .xpaBiasLvl = 0,
+               .txFrameToDataStart = 0x0e,
+               .txFrameToPaOn = 0x0e,
+               .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+               .antennaGain = 0,
+               .switchSettling = 0x2d,
+               .adcDesiredSize = -30,
+               .txEndToXpaOff = 0,
+               .txEndToRxOn = 0x2,
+               .txFrameToXpaOn = 0xe,
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+               .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0, 0,
+               },
+       },
+       .base_ext2 = {
+               .tempSlopeLow = 72,
+               .tempSlopeHigh = 105,
+               .xatten1DBLow = {0x10, 0x14, 0x10},
+               .xatten1MarginLow = {0x19, 0x19 , 0x19},
+               .xatten1DBHigh = {0x1d, 0x20, 0x24},
+               .xatten1MarginHigh = {0x10, 0x10, 0x10}
+       },
+       .calFreqPier5G = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5220, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5785, 0)
+       },
+       .calPierData5G = {
+               {
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+               },
+               {
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+               },
+               {
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+                       {0, 0, 0, 0, 0},
+               },
+
+       },
+       .calTarget_freqbin_5G = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5220, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5725, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTarget_freqbin_5GHT20 = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5220, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5725, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTarget_freqbin_5GHT40 = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5220, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5725, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTargetPower5G = {
+               /* 6-24,36,48,54 */
+               { {32, 32, 28, 26} },
+               { {32, 32, 28, 26} },
+               { {32, 32, 28, 26} },
+               { {32, 32, 26, 24} },
+               { {32, 32, 26, 24} },
+               { {32, 32, 24, 22} },
+               { {30, 30, 24, 22} },
+               { {30, 30, 24, 22} },
+       },
+       .calTargetPower5GHT20 = {
+               /*
+                * 0_8_16,1-3_9-11_17-19,
+                * 4,5,6,7,12,13,14,15,20,21,22,23
+                */
+               { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+               { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+               { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+               { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 22, 22, 20, 20} },
+               { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 20, 18, 16, 16} },
+               { {32, 32, 32, 32, 28, 26, 32, 24, 20, 16, 18, 16, 14, 14} },
+               { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} },
+               { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} },
+       },
+       .calTargetPower5GHT40 =  {
+               /*
+                * 0_8_16,1-3_9-11_17-19,
+                * 4,5,6,7,12,13,14,15,20,21,22,23
+                */
+               { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+               { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+               { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+               { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 22, 22, 20, 20} },
+               { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 20, 18, 16, 16} },
+               { {32, 32, 32, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+               { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+               { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+       },
+       .ctlIndex_5G =  {
+               0x10, 0x16, 0x18, 0x40, 0x46,
+               0x48, 0x30, 0x36, 0x38
+       },
+       .ctl_freqbin_5G =  {
+               {
+                       /* Data[0].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+                       /* Data[0].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+                       /* Data[0].ctledges[2].bchannel */ FREQ2FBIN(5280, 0),
+                       /* Data[0].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+                       /* Data[0].ctledges[4].bchannel */ FREQ2FBIN(5600, 0),
+                       /* Data[0].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+                       /* Data[0].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+                       /* Data[0].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+               },
+               {
+                       /* Data[1].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+                       /* Data[1].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+                       /* Data[1].ctledges[2].bchannel */ FREQ2FBIN(5280, 0),
+                       /* Data[1].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+                       /* Data[1].ctledges[4].bchannel */ FREQ2FBIN(5520, 0),
+                       /* Data[1].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+                       /* Data[1].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+                       /* Data[1].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+               },
+
+               {
+                       /* Data[2].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+                       /* Data[2].ctledges[1].bchannel */ FREQ2FBIN(5230, 0),
+                       /* Data[2].ctledges[2].bchannel */ FREQ2FBIN(5270, 0),
+                       /* Data[2].ctledges[3].bchannel */ FREQ2FBIN(5310, 0),
+                       /* Data[2].ctledges[4].bchannel */ FREQ2FBIN(5510, 0),
+                       /* Data[2].ctledges[5].bchannel */ FREQ2FBIN(5550, 0),
+                       /* Data[2].ctledges[6].bchannel */ FREQ2FBIN(5670, 0),
+                       /* Data[2].ctledges[7].bchannel */ FREQ2FBIN(5755, 0)
+               },
+
+               {
+                       /* Data[3].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+                       /* Data[3].ctledges[1].bchannel */ FREQ2FBIN(5200, 0),
+                       /* Data[3].ctledges[2].bchannel */ FREQ2FBIN(5260, 0),
+                       /* Data[3].ctledges[3].bchannel */ FREQ2FBIN(5320, 0),
+                       /* Data[3].ctledges[4].bchannel */ FREQ2FBIN(5500, 0),
+                       /* Data[3].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+                       /* Data[3].ctledges[6].bchannel */ 0xFF,
+                       /* Data[3].ctledges[7].bchannel */ 0xFF,
+               },
+
+               {
+                       /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+                       /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+                       /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(5500, 0),
+                       /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(5700, 0),
+                       /* Data[4].ctledges[4].bchannel */ 0xFF,
+                       /* Data[4].ctledges[5].bchannel */ 0xFF,
+                       /* Data[4].ctledges[6].bchannel */ 0xFF,
+                       /* Data[4].ctledges[7].bchannel */ 0xFF,
+               },
+
+               {
+                       /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+                       /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(5270, 0),
+                       /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(5310, 0),
+                       /* Data[5].ctledges[3].bchannel */ FREQ2FBIN(5510, 0),
+                       /* Data[5].ctledges[4].bchannel */ FREQ2FBIN(5590, 0),
+                       /* Data[5].ctledges[5].bchannel */ FREQ2FBIN(5670, 0),
+                       /* Data[5].ctledges[6].bchannel */ 0xFF,
+                       /* Data[5].ctledges[7].bchannel */ 0xFF
+               },
+
+               {
+                       /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+                       /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(5200, 0),
+                       /* Data[6].ctledges[2].bchannel */ FREQ2FBIN(5220, 0),
+                       /* Data[6].ctledges[3].bchannel */ FREQ2FBIN(5260, 0),
+                       /* Data[6].ctledges[4].bchannel */ FREQ2FBIN(5500, 0),
+                       /* Data[6].ctledges[5].bchannel */ FREQ2FBIN(5600, 0),
+                       /* Data[6].ctledges[6].bchannel */ FREQ2FBIN(5700, 0),
+                       /* Data[6].ctledges[7].bchannel */ FREQ2FBIN(5745, 0)
+               },
+
+               {
+                       /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+                       /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+                       /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(5320, 0),
+                       /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+                       /* Data[7].ctledges[4].bchannel */ FREQ2FBIN(5560, 0),
+                       /* Data[7].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+                       /* Data[7].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+                       /* Data[7].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+               },
+
+               {
+                       /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+                       /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(5230, 0),
+                       /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(5270, 0),
+                       /* Data[8].ctledges[3].bchannel */ FREQ2FBIN(5510, 0),
+                       /* Data[8].ctledges[4].bchannel */ FREQ2FBIN(5550, 0),
+                       /* Data[8].ctledges[5].bchannel */ FREQ2FBIN(5670, 0),
+                       /* Data[8].ctledges[6].bchannel */ FREQ2FBIN(5755, 0),
+                       /* Data[8].ctledges[7].bchannel */ FREQ2FBIN(5795, 0)
+               }
+       },
+       .ctlPowerData_5G = {
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                       }
+               },
+       }
+};
+
+static const struct ar9300_eeprom ar9300_h116 = {
+       .eepromVersion = 2,
+       .templateVersion = 4,
+       .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+       .custData = {"h116-041-f0000"},
+       .baseEepHeader = {
+               .regDmn = { LE16(0), LE16(0x1f) },
+               .txrxMask =  0x33, /* 4 bits tx and 4 bits rx */
+               .opCapFlags = {
+                       .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+                       .eepMisc = 0,
+               },
+               .rfSilent = 0,
+               .blueToothOptions = 0,
+               .deviceCap = 0,
+               .deviceType = 5, /* takes lower byte in eeprom location */
+               .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+               .params_for_tuning_caps = {0, 0},
+               .featureEnable = 0x0d,
+                /*
+                 * bit0 - enable tx temp comp - disabled
+                 * bit1 - enable tx volt comp - disabled
+                 * bit2 - enable fastClock - enabled
+                 * bit3 - enable doubling - enabled
+                 * bit4 - enable internal regulator - disabled
+                 * bit5 - enable pa predistortion - disabled
+                 */
+               .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+               .eepromWriteEnableGpio = 6,
+               .wlanDisableGpio = 0,
+               .wlanLedGpio = 8,
+               .rxBandSelectGpio = 0xff,
+               .txrxgain = 0x10,
+               .swreg = 0,
+        },
+       .modalHeader2G = {
+       /* ar9300_modal_eep_header  2g */
+               /* 4 idle,t1,t2,b(4 bits per setting) */
+               .antCtrlCommon = LE32(0x110),
+               /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+               .antCtrlCommon2 = LE32(0x44444),
+
+               /*
+                * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+                * rx1, rx12, b (2 bits each)
+                */
+               .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) },
+
+               /*
+                * xatten1DB[AR9300_MAX_CHAINS];  3 xatten1_db
+                * for ar9280 (0xa20c/b20c 5:0)
+                */
+               .xatten1DB = {0x1f, 0x1f, 0x1f},
+
+               /*
+                * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+                * for ar9280 (0xa20c/b20c 16:12
+                */
+               .xatten1Margin = {0x12, 0x12, 0x12},
+               .tempSlope = 25,
+               .voltSlope = 0,
+
+               /*
+                * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+                * channels in usual fbin coding format
+                */
+               .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+               /*
+                * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+                * if the register is per chain
+                */
+               .noiseFloorThreshCh = {-1, 0, 0},
+               .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               .quick_drop = 0,
+               .xpaBiasLvl = 0,
+               .txFrameToDataStart = 0x0e,
+               .txFrameToPaOn = 0x0e,
+               .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+               .antennaGain = 0,
+               .switchSettling = 0x2c,
+               .adcDesiredSize = -30,
+               .txEndToXpaOff = 0,
+               .txEndToRxOn = 0x2,
+               .txFrameToXpaOn = 0xe,
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0c80C080),
+               .papdRateMaskHt40 = LE32(0x0080C080),
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0, 0,
+               },
+        },
+        .base_ext1 = {
+               .ant_div_control = 0,
+               .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+        },
+       .calFreqPier2G = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2462, 1),
+        },
+       /* ar9300_cal_data_per_freq_op_loop 2g */
+       .calPierData2G = {
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+               { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+        },
+       .calTarget_freqbin_Cck = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2472, 1),
+        },
+       .calTarget_freqbin_2G = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+        },
+       .calTarget_freqbin_2GHT20 = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+        },
+       .calTarget_freqbin_2GHT40 = {
+               FREQ2FBIN(2412, 1),
+               FREQ2FBIN(2437, 1),
+               FREQ2FBIN(2472, 1)
+        },
+       .calTargetPowerCck = {
+                /* 1L-5L,5S,11L,11S */
+                { {34, 34, 34, 34} },
+                { {34, 34, 34, 34} },
+       },
+       .calTargetPower2G = {
+                /* 6-24,36,48,54 */
+                { {34, 34, 32, 32} },
+                { {34, 34, 32, 32} },
+                { {34, 34, 32, 32} },
+       },
+       .calTargetPower2GHT20 = {
+               { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+               { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+               { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+       },
+       .calTargetPower2GHT40 = {
+               { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+               { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+               { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+       },
+       .ctlIndex_2G =  {
+               0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+               0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+       },
+       .ctl_freqbin_2G = {
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2457, 1),
+                       FREQ2FBIN(2462, 1)
+               },
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2462, 1),
+                       0xFF,
+               },
+
+               {
+                       FREQ2FBIN(2412, 1),
+                       FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2462, 1),
+                       0xFF,
+               },
+               {
+                       FREQ2FBIN(2422, 1),
+                       FREQ2FBIN(2427, 1),
+                       FREQ2FBIN(2447, 1),
+                       FREQ2FBIN(2452, 1)
+               },
+
+               {
+                       /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+               },
+
+               {
+                       /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0,
+               },
+
+               {
+                       /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       FREQ2FBIN(2472, 1),
+                       0,
+               },
+
+               {
+                       /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+                       /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+                       /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+                       /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+               },
+
+               {
+                       /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+               },
+
+               {
+                       /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0
+               },
+
+               {
+                       /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+                       /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+                       /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+                       0
+               },
+
+               {
+                       /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+                       /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+                       /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+                       /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+               }
+        },
+       .ctlPowerData_2G = {
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+        },
+       .modalHeader5G = {
+               /* 4 idle,t1,t2,b (4 bits per setting) */
+               .antCtrlCommon = LE32(0x220),
+               /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+               .antCtrlCommon2 = LE32(0x44444),
+                /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+               .antCtrlChain = {
+                       LE16(0x150), LE16(0x150), LE16(0x150),
+               },
+                /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+               .xatten1DB = {0x19, 0x19, 0x19},
+
+               /*
+                * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+                * for merlin (0xa20c/b20c 16:12
+                */
+               .xatten1Margin = {0x14, 0x14, 0x14},
+               .tempSlope = 70,
+               .voltSlope = 0,
+               /* spurChans spur channels in usual fbin coding format */
+               .spurChans = {0, 0, 0, 0, 0},
+               /* noiseFloorThreshCh Check if the register is per chain */
+               .noiseFloorThreshCh = {-1, 0, 0},
+               .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               .quick_drop = 0,
+               .xpaBiasLvl = 0,
+               .txFrameToDataStart = 0x0e,
+               .txFrameToPaOn = 0x0e,
+               .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+               .antennaGain = 0,
+               .switchSettling = 0x2d,
+               .adcDesiredSize = -30,
+               .txEndToXpaOff = 0,
+               .txEndToRxOn = 0x2,
+               .txFrameToXpaOn = 0xe,
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+               .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0, 0,
+               },
+        },
+       .base_ext2 = {
+               .tempSlopeLow = 35,
+               .tempSlopeHigh = 50,
+               .xatten1DBLow = {0, 0, 0},
+               .xatten1MarginLow = {0, 0, 0},
+               .xatten1DBHigh = {0, 0, 0},
+               .xatten1MarginHigh = {0, 0, 0}
+        },
+       .calFreqPier5G = {
+               FREQ2FBIN(5160, 0),
+               FREQ2FBIN(5220, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5785, 0)
+       },
+       .calPierData5G = {
+                       {
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                       },
+                       {
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                       },
+                       {
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                               {0, 0, 0, 0, 0},
+                       },
+
+       },
+       .calTarget_freqbin_5G = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5240, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5600, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTarget_freqbin_5GHT20 = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5240, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5745, 0),
+               FREQ2FBIN(5825, 0)
+       },
+       .calTarget_freqbin_5GHT40 = {
+               FREQ2FBIN(5180, 0),
+               FREQ2FBIN(5240, 0),
+               FREQ2FBIN(5320, 0),
+               FREQ2FBIN(5400, 0),
+               FREQ2FBIN(5500, 0),
+               FREQ2FBIN(5700, 0),
+               FREQ2FBIN(5745, 0),
+               FREQ2FBIN(5825, 0)
+        },
+       .calTargetPower5G = {
+               /* 6-24,36,48,54 */
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+               { {30, 30, 28, 24} },
+        },
+       .calTargetPower5GHT20 = {
+               /*
+                * 0_8_16,1-3_9-11_17-19,
+                * 4,5,6,7,12,13,14,15,20,21,22,23
+                */
+               { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} },
+               { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} },
+               { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} },
+               { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} },
+               { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} },
+               { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} },
+               { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} },
+               { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} },
+        },
+       .calTargetPower5GHT40 =  {
+               /*
+                * 0_8_16,1-3_9-11_17-19,
+                * 4,5,6,7,12,13,14,15,20,21,22,23
+                */
+               { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} },
+               { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} },
+               { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} },
+               { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} },
+               { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} },
+               { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} },
+               { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} },
+               { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} },
+        },
+       .ctlIndex_5G =  {
+               0x10, 0x16, 0x18, 0x40, 0x46,
+               0x48, 0x30, 0x36, 0x38
+       },
+       .ctl_freqbin_5G =  {
+               {
+                       /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+                       /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+                       /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+               {
+                       /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+                       /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+                       /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+
+               {
+                       /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+                       /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+                       /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+                       /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+               },
+
+               {
+                       /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+                       /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+                       /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+               },
+
+               {
+                       /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+               },
+
+               {
+                       /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+                       /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+                       /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+                       /* Data[5].ctlEdges[7].bChannel */ 0xFF
+               },
+
+               {
+                       /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+                       /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+                       /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+                       /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+               },
+
+               {
+                       /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+                       /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+                       /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+                       /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+                       /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+                       /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+                       /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+                       /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+               },
+
+               {
+                       /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+                       /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+                       /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+                       /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+                       /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+                       /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+                       /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+                       /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+               }
+        },
+       .ctlPowerData_5G = {
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                       }
+               },
+               {
+                       {
+                               CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                       }
+               },
+        }
+};
+
+
+static const struct ar9300_eeprom *ar9300_eep_templates[] = {
+       &ar9300_default,
+       &ar9300_x112,
+       &ar9300_h116,
+       &ar9300_h112,
+       &ar9300_x113,
+};
+
+static const struct ar9300_eeprom *ar9003_eeprom_struct_find_by_id(int id)
+{
+#define N_LOOP (sizeof(ar9300_eep_templates) / sizeof(ar9300_eep_templates[0]))
+       int it;
+
+       for (it = 0; it < N_LOOP; it++)
+               if (ar9300_eep_templates[it]->templateVersion == id)
+                       return ar9300_eep_templates[it];
+       return NULL;
+#undef N_LOOP
+}
+
+
+static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
+{
+       if (fbin == AR5416_BCHAN_UNUSED)
+               return fbin;
+
+       return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
+{
+       return 0;
+}
+
+static int interpolate(int x, int xa, int xb, int ya, int yb)
+{
+       int bf, factor, plus;
+
+       bf = 2 * (yb - ya) * (x - xa) / (xb - xa);
+       factor = bf / 2;
+       plus = bf % 2;
+       return ya + factor + plus;
+}
+
+static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
+                                     enum eeprom_param param)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
+
+       switch (param) {
+       case EEP_MAC_LSW:
+               return get_unaligned_be16(eep->macAddr);
+       case EEP_MAC_MID:
+               return get_unaligned_be16(eep->macAddr + 2);
+       case EEP_MAC_MSW:
+               return get_unaligned_be16(eep->macAddr + 4);
+       case EEP_REG_0:
+               return le16_to_cpu(pBase->regDmn[0]);
+       case EEP_OP_CAP:
+               return pBase->deviceCap;
+       case EEP_OP_MODE:
+               return pBase->opCapFlags.opFlags;
+       case EEP_RF_SILENT:
+               return pBase->rfSilent;
+       case EEP_TX_MASK:
+               return (pBase->txrxMask >> 4) & 0xf;
+       case EEP_RX_MASK:
+               return pBase->txrxMask & 0xf;
+       case EEP_DRIVE_STRENGTH:
+#define AR9300_EEP_BASE_DRIV_STRENGTH  0x1
+               return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH;
+       case EEP_INTERNAL_REGULATOR:
+               /* Bit 4 is internal regulator flag */
+               return (pBase->featureEnable & 0x10) >> 4;
+       case EEP_SWREG:
+               return le32_to_cpu(pBase->swreg);
+       case EEP_PAPRD:
+               return !!(pBase->featureEnable & BIT(5));
+       case EEP_CHAIN_MASK_REDUCE:
+               return (pBase->miscConfiguration >> 0x3) & 0x1;
+       case EEP_ANT_DIV_CTL1:
+               return eep->base_ext1.ant_div_control;
+       case EEP_ANTENNA_GAIN_5G:
+               return eep->modalHeader5G.antennaGain;
+       case EEP_ANTENNA_GAIN_2G:
+               return eep->modalHeader2G.antennaGain;
+       case EEP_QUICK_DROP:
+               return pBase->miscConfiguration & BIT(1);
+       default:
+               return 0;
+       }
+}
+
+static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
+                                   u8 *buffer)
+{
+       u16 val;
+
+       if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
+               return false;
+
+       *buffer = (val >> (8 * (address % 2))) & 0xff;
+       return true;
+}
+
+static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
+                                   u8 *buffer)
+{
+       u16 val;
+
+       if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
+               return false;
+
+       buffer[0] = val >> 8;
+       buffer[1] = val & 0xff;
+
+       return true;
+}
+
+static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
+                              int count)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       int i;
+
+       if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
+               ath_dbg(common, EEPROM, "eeprom address not in range\n");
+               return false;
+       }
+
+       /*
+        * Since we're reading the bytes in reverse order from a little-endian
+        * word stream, an even address means we only use the lower half of
+        * the 16-bit word at that address
+        */
+       if (address % 2 == 0) {
+               if (!ar9300_eeprom_read_byte(common, address--, buffer++))
+                       goto error;
+
+               count--;
+       }
+
+       for (i = 0; i < count / 2; i++) {
+               if (!ar9300_eeprom_read_word(common, address, buffer))
+                       goto error;
+
+               address -= 2;
+               buffer += 2;
+       }
+
+       if (count % 2)
+               if (!ar9300_eeprom_read_byte(common, address, buffer))
+                       goto error;
+
+       return true;
+
+error:
+       ath_dbg(common, EEPROM, "unable to read eeprom region at offset %d\n",
+               address);
+       return false;
+}
+
+static bool ar9300_otp_read_word(struct ath_hw *ah, int addr, u32 *data)
+{
+       REG_READ(ah, AR9300_OTP_BASE + (4 * addr));
+
+       if (!ath9k_btcoex_ath9k_hw_wait(ah, AR9300_OTP_STATUS, AR9300_OTP_STATUS_TYPE,
+                          AR9300_OTP_STATUS_VALID, 1000))
+               return false;
+
+       *data = REG_READ(ah, AR9300_OTP_READ_DATA);
+       return true;
+}
+
+static bool ar9300_read_otp(struct ath_hw *ah, int address, u8 *buffer,
+                           int count)
+{
+       u32 data;
+       int i;
+
+       for (i = 0; i < count; i++) {
+               int offset = 8 * ((address - i) % 4);
+               if (!ar9300_otp_read_word(ah, (address - i) / 4, &data))
+                       return false;
+
+               buffer[i] = (data >> offset) & 0xff;
+       }
+
+       return true;
+}
+
+
+static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
+                                  int *length, int *major, int *minor)
+{
+       unsigned long value[4];
+
+       value[0] = best[0];
+       value[1] = best[1];
+       value[2] = best[2];
+       value[3] = best[3];
+       *code = ((value[0] >> 5) & 0x0007);
+       *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020);
+       *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f);
+       *major = (value[2] & 0x000f);
+       *minor = (value[3] & 0x00ff);
+}
+
+static u16 ar9300_comp_cksum(u8 *data, int dsize)
+{
+       int it, checksum = 0;
+
+       for (it = 0; it < dsize; it++) {
+               checksum += data[it];
+               checksum &= 0xffff;
+       }
+
+       return checksum;
+}
+
+static bool ar9300_uncompress_block(struct ath_hw *ah,
+                                   u8 *mptr,
+                                   int mdataSize,
+                                   u8 *block,
+                                   int size)
+{
+       int it;
+       int spot;
+       int offset;
+       int length;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       spot = 0;
+
+       for (it = 0; it < size; it += (length+2)) {
+               offset = block[it];
+               offset &= 0xff;
+               spot += offset;
+               length = block[it+1];
+               length &= 0xff;
+
+               if (length > 0 && spot >= 0 && spot+length <= mdataSize) {
+                       ath_dbg(common, EEPROM,
+                               "Restore at %d: spot=%d offset=%d length=%d\n",
+                               it, spot, offset, length);
+                       memcpy(&mptr[spot], &block[it+2], length);
+                       spot += length;
+               } else if (length > 0) {
+                       ath_dbg(common, EEPROM,
+                               "Bad restore at %d: spot=%d offset=%d length=%d\n",
+                               it, spot, offset, length);
+                       return false;
+               }
+       }
+       return true;
+}
+
+static int ar9300_compress_decision(struct ath_hw *ah,
+                                   int it,
+                                   int code,
+                                   int reference,
+                                   u8 *mptr,
+                                   u8 *word, int length, int mdata_size)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       const struct ar9300_eeprom *eep = NULL;
+
+       switch (code) {
+       case _CompressNone:
+               if (length != mdata_size) {
+                       ath_dbg(common, EEPROM,
+                               "EEPROM structure size mismatch memory=%d eeprom=%d\n",
+                               mdata_size, length);
+                       return -1;
+               }
+               memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
+               ath_dbg(common, EEPROM,
+                       "restored eeprom %d: uncompressed, length %d\n",
+                       it, length);
+               break;
+       case _CompressBlock:
+               if (reference == 0) {
+               } else {
+                       eep = ar9003_eeprom_struct_find_by_id(reference);
+                       if (eep == NULL) {
+                               ath_dbg(common, EEPROM,
+                                       "can't find reference eeprom struct %d\n",
+                                       reference);
+                               return -1;
+                       }
+                       memcpy(mptr, eep, mdata_size);
+               }
+               ath_dbg(common, EEPROM,
+                       "restore eeprom %d: block, reference %d, length %d\n",
+                       it, reference, length);
+               ar9300_uncompress_block(ah, mptr, mdata_size,
+                                       (u8 *) (word + COMP_HDR_LEN), length);
+               break;
+       default:
+               ath_dbg(common, EEPROM, "unknown compression code %d\n", code);
+               return -1;
+       }
+       return 0;
+}
+
+typedef bool (*eeprom_read_op)(struct ath_hw *ah, int address, u8 *buffer,
+                              int count);
+
+static bool ar9300_check_header(void *data)
+{
+       u32 *word = data;
+       return !(*word == 0 || *word == ~0);
+}
+
+static bool ar9300_check_eeprom_header(struct ath_hw *ah, eeprom_read_op read,
+                                      int base_addr)
+{
+       u8 header[4];
+
+       if (!read(ah, base_addr, header, 4))
+               return false;
+
+       return ar9300_check_header(header);
+}
+
+static int ar9300_eeprom_restore_flash(struct ath_hw *ah, u8 *mptr,
+                                      int mdata_size)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u16 *data = (u16 *) mptr;
+       int i;
+
+       for (i = 0; i < mdata_size / 2; i++, data++)
+               ath9k_hw_nvram_read(common, i, data);
+
+       return 0;
+}
+/*
+ * Read the configuration data from the eeprom.
+ * The data can be put in any specified memory buffer.
+ *
+ * Returns -1 on error.
+ * Returns address of next memory location on success.
+ */
+static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
+                                         u8 *mptr, int mdata_size)
+{
+#define MDEFAULT 15
+#define MSTATE 100
+       int cptr;
+       u8 *word;
+       int code;
+       int reference, length, major, minor;
+       int osize;
+       int it;
+       u16 checksum, mchecksum;
+       struct ath_common *common = ath9k_hw_common(ah);
+       eeprom_read_op read;
+
+       if (ath9k_hw_use_flash(ah))
+               return ar9300_eeprom_restore_flash(ah, mptr, mdata_size);
+
+       word = kzalloc(2048, GFP_KERNEL);
+       if (!word)
+               return -ENOMEM;
+
+       memcpy(mptr, &ar9300_default, mdata_size);
+
+       read = ar9300_read_eeprom;
+       if (AR_SREV_9485(ah))
+               cptr = AR9300_BASE_ADDR_4K;
+       else if (AR_SREV_9330(ah))
+               cptr = AR9300_BASE_ADDR_512;
+       else
+               cptr = AR9300_BASE_ADDR;
+       ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n",
+               cptr);
+       if (ar9300_check_eeprom_header(ah, read, cptr))
+               goto found;
+
+       cptr = AR9300_BASE_ADDR_512;
+       ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n",
+               cptr);
+       if (ar9300_check_eeprom_header(ah, read, cptr))
+               goto found;
+
+       read = ar9300_read_otp;
+       cptr = AR9300_BASE_ADDR;
+       ath_dbg(common, EEPROM, "Trying OTP access at Address 0x%04x\n", cptr);
+       if (ar9300_check_eeprom_header(ah, read, cptr))
+               goto found;
+
+       cptr = AR9300_BASE_ADDR_512;
+       ath_dbg(common, EEPROM, "Trying OTP access at Address 0x%04x\n", cptr);
+       if (ar9300_check_eeprom_header(ah, read, cptr))
+               goto found;
+
+       goto fail;
+
+found:
+       ath_dbg(common, EEPROM, "Found valid EEPROM data\n");
+
+       for (it = 0; it < MSTATE; it++) {
+               if (!read(ah, cptr, word, COMP_HDR_LEN))
+                       goto fail;
+
+               if (!ar9300_check_header(word))
+                       break;
+
+               ar9300_comp_hdr_unpack(word, &code, &reference,
+                                      &length, &major, &minor);
+               ath_dbg(common, EEPROM,
+                       "Found block at %x: code=%d ref=%d length=%d major=%d minor=%d\n",
+                       cptr, code, reference, length, major, minor);
+               if ((!AR_SREV_9485(ah) && length >= 1024) ||
+                   (AR_SREV_9485(ah) && length > EEPROM_DATA_LEN_9485)) {
+                       ath_dbg(common, EEPROM, "Skipping bad header\n");
+                       cptr -= COMP_HDR_LEN;
+                       continue;
+               }
+
+               osize = length;
+               read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
+               checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
+               mchecksum = get_unaligned_le16(&word[COMP_HDR_LEN + osize]);
+               ath_dbg(common, EEPROM, "checksum %x %x\n",
+                       checksum, mchecksum);
+               if (checksum == mchecksum) {
+                       ar9300_compress_decision(ah, it, code, reference, mptr,
+                                                word, length, mdata_size);
+               } else {
+                       ath_dbg(common, EEPROM,
+                               "skipping block with bad checksum\n");
+               }
+               cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
+       }
+
+       kfree(word);
+       return cptr;
+
+fail:
+       kfree(word);
+       return -1;
+}
+
+/*
+ * Restore the configuration structure by reading the eeprom.
+ * This function destroys any existing in-memory structure
+ * content.
+ */
+static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
+{
+       u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep;
+
+       if (ar9300_eeprom_restore_internal(ah, mptr,
+                       sizeof(struct ar9300_eeprom)) < 0)
+               return false;
+
+       return true;
+}
+
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ar9003_dump_modal_eeprom(char *buf, u32 len, u32 size,
+                                   struct ar9300_modal_eep_header *modal_hdr)
+{
+       PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
+       PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
+       PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2]));
+       PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
+       PR_EEP("Ant. Common Control2", le32_to_cpu(modal_hdr->antCtrlCommon2));
+       PR_EEP("Ant. Gain", modal_hdr->antennaGain);
+       PR_EEP("Switch Settle", modal_hdr->switchSettling);
+       PR_EEP("Chain0 xatten1DB", modal_hdr->xatten1DB[0]);
+       PR_EEP("Chain1 xatten1DB", modal_hdr->xatten1DB[1]);
+       PR_EEP("Chain2 xatten1DB", modal_hdr->xatten1DB[2]);
+       PR_EEP("Chain0 xatten1Margin", modal_hdr->xatten1Margin[0]);
+       PR_EEP("Chain1 xatten1Margin", modal_hdr->xatten1Margin[1]);
+       PR_EEP("Chain2 xatten1Margin", modal_hdr->xatten1Margin[2]);
+       PR_EEP("Temp Slope", modal_hdr->tempSlope);
+       PR_EEP("Volt Slope", modal_hdr->voltSlope);
+       PR_EEP("spur Channels0", modal_hdr->spurChans[0]);
+       PR_EEP("spur Channels1", modal_hdr->spurChans[1]);
+       PR_EEP("spur Channels2", modal_hdr->spurChans[2]);
+       PR_EEP("spur Channels3", modal_hdr->spurChans[3]);
+       PR_EEP("spur Channels4", modal_hdr->spurChans[4]);
+       PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+       PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
+       PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);
+       PR_EEP("Quick Drop", modal_hdr->quick_drop);
+       PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
+       PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+       PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+       PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+       PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+       PR_EEP("txClip", modal_hdr->txClip);
+       PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+
+       return len;
+}
+
+static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+                                      u8 *buf, u32 len, u32 size)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       struct ar9300_base_eep_hdr *pBase;
+
+       if (!dump_base_hdr) {
+               len += snprintf(buf + len, size - len,
+                               "%20s :\n", "2GHz modal Header");
+               len = ar9003_dump_modal_eeprom(buf, len, size,
+                                               &eep->modalHeader2G);
+               len += snprintf(buf + len, size - len,
+                               "%20s :\n", "5GHz modal Header");
+               len = ar9003_dump_modal_eeprom(buf, len, size,
+                                               &eep->modalHeader5G);
+               goto out;
+       }
+
+       pBase = &eep->baseEepHeader;
+
+       PR_EEP("EEPROM Version", ah->eeprom.ar9300_eep.eepromVersion);
+       PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
+       PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
+       PR_EEP("TX Mask", (pBase->txrxMask >> 4));
+       PR_EEP("RX Mask", (pBase->txrxMask & 0x0f));
+       PR_EEP("Allow 5GHz", !!(pBase->opCapFlags.opFlags &
+                               AR5416_OPFLAGS_11A));
+       PR_EEP("Allow 2GHz", !!(pBase->opCapFlags.opFlags &
+                               AR5416_OPFLAGS_11G));
+       PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags.opFlags &
+                                       AR5416_OPFLAGS_N_2G_HT20));
+       PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags.opFlags &
+                                       AR5416_OPFLAGS_N_2G_HT40));
+       PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags.opFlags &
+                                       AR5416_OPFLAGS_N_5G_HT20));
+       PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags.opFlags &
+                                       AR5416_OPFLAGS_N_5G_HT40));
+       PR_EEP("Big Endian", !!(pBase->opCapFlags.eepMisc & 0x01));
+       PR_EEP("RF Silent", pBase->rfSilent);
+       PR_EEP("BT option", pBase->blueToothOptions);
+       PR_EEP("Device Cap", pBase->deviceCap);
+       PR_EEP("Device Type", pBase->deviceType);
+       PR_EEP("Power Table Offset", pBase->pwrTableOffset);
+       PR_EEP("Tuning Caps1", pBase->params_for_tuning_caps[0]);
+       PR_EEP("Tuning Caps2", pBase->params_for_tuning_caps[1]);
+       PR_EEP("Enable Tx Temp Comp", !!(pBase->featureEnable & BIT(0)));
+       PR_EEP("Enable Tx Volt Comp", !!(pBase->featureEnable & BIT(1)));
+       PR_EEP("Enable fast clock", !!(pBase->featureEnable & BIT(2)));
+       PR_EEP("Enable doubling", !!(pBase->featureEnable & BIT(3)));
+       PR_EEP("Internal regulator", !!(pBase->featureEnable & BIT(4)));
+       PR_EEP("Enable Paprd", !!(pBase->featureEnable & BIT(5)));
+       PR_EEP("Driver Strength", !!(pBase->miscConfiguration & BIT(0)));
+       PR_EEP("Quick Drop", !!(pBase->miscConfiguration & BIT(1)));
+       PR_EEP("Chain mask Reduce", (pBase->miscConfiguration >> 0x3) & 0x1);
+       PR_EEP("Write enable Gpio", pBase->eepromWriteEnableGpio);
+       PR_EEP("WLAN Disable Gpio", pBase->wlanDisableGpio);
+       PR_EEP("WLAN LED Gpio", pBase->wlanLedGpio);
+       PR_EEP("Rx Band Select Gpio", pBase->rxBandSelectGpio);
+       PR_EEP("Tx Gain", pBase->txrxgain >> 4);
+       PR_EEP("Rx Gain", pBase->txrxgain & 0xf);
+       PR_EEP("SW Reg", le32_to_cpu(pBase->swreg));
+
+       len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+                       ah->eeprom.ar9300_eep.macAddr);
+out:
+       if (len > size)
+               len = size;
+
+       return len;
+}
+#else
+static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+                                      u8 *buf, u32 len, u32 size)
+{
+       return 0;
+}
+#endif
+
+/* XXX: review hardware docs */
+static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
+{
+       return ah->eeprom.ar9300_eep.eepromVersion;
+}
+
+/* XXX: could be read from the eepromVersion, not sure yet */
+static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
+{
+       return 0;
+}
+
+static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+       if (is2ghz)
+               return eep->modalHeader2G.xpaBiasLvl;
+       else
+               return eep->modalHeader5G.xpaBiasLvl;
+}
+
+static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
+{
+       int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
+
+       if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
+               REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
+       else if (AR_SREV_9462(ah))
+               REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
+       else {
+               REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
+               REG_RMW_FIELD(ah, AR_CH0_THERM,
+                               AR_CH0_THERM_XPABIASLVL_MSB,
+                               bias >> 2);
+               REG_RMW_FIELD(ah, AR_CH0_THERM,
+                               AR_CH0_THERM_XPASHORT2GND, 1);
+       }
+}
+
+static u16 ar9003_switch_com_spdt_get(struct ath_hw *ah, bool is_2ghz)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       __le16 val;
+
+       if (is_2ghz)
+               val = eep->modalHeader2G.switchcomspdt;
+       else
+               val = eep->modalHeader5G.switchcomspdt;
+       return le16_to_cpu(val);
+}
+
+
+static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       __le32 val;
+
+       if (is2ghz)
+               val = eep->modalHeader2G.antCtrlCommon;
+       else
+               val = eep->modalHeader5G.antCtrlCommon;
+       return le32_to_cpu(val);
+}
+
+static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       __le32 val;
+
+       if (is2ghz)
+               val = eep->modalHeader2G.antCtrlCommon2;
+       else
+               val = eep->modalHeader5G.antCtrlCommon2;
+       return le32_to_cpu(val);
+}
+
+static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
+                                       int chain,
+                                       bool is2ghz)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       __le16 val = 0;
+
+       if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
+               if (is2ghz)
+                       val = eep->modalHeader2G.antCtrlChain[chain];
+               else
+                       val = eep->modalHeader5G.antCtrlChain[chain];
+       }
+
+       return le16_to_cpu(val);
+}
+
+static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
+{
+       int chain;
+       u32 regval;
+       u32 ant_div_ctl1;
+       static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = {
+                       AR_PHY_SWITCH_CHAIN_0,
+                       AR_PHY_SWITCH_CHAIN_1,
+                       AR_PHY_SWITCH_CHAIN_2,
+       };
+
+       u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
+
+       if (AR_SREV_9462(ah)) {
+               REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+                               AR_SWITCH_TABLE_COM_AR9462_ALL, value);
+       } else
+               REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+                             AR_SWITCH_TABLE_COM_ALL, value);
+
+
+       /*
+        *   AR9462 defines new switch table for BT/WLAN,
+        *       here's new field name in XXX.ref for both 2G and 5G.
+        *   Register: [GLB_CONTROL] GLB_CONTROL (@0x20044)
+        *   15:12   R/W     SWITCH_TABLE_COM_SPDT_WLAN_RX
+        * SWITCH_TABLE_COM_SPDT_WLAN_RX
+        *
+        *   11:8     R/W     SWITCH_TABLE_COM_SPDT_WLAN_TX
+        * SWITCH_TABLE_COM_SPDT_WLAN_TX
+        *
+        *   7:4 R/W  SWITCH_TABLE_COM_SPDT_WLAN_IDLE
+        * SWITCH_TABLE_COM_SPDT_WLAN_IDLE
+        */
+       if (AR_SREV_9462_20_OR_LATER(ah)) {
+               value = ar9003_switch_com_spdt_get(ah, is2ghz);
+               REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
+                               AR_SWITCH_TABLE_COM_SPDT_ALL, value);
+               REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_SPDT_ENABLE);
+       }
+
+       value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
+       REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
+
+       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+               if ((ah->rxchainmask & BIT(chain)) ||
+                   (ah->txchainmask & BIT(chain))) {
+                       value = ar9003_hw_ant_ctrl_chain_get(ah, chain,
+                                                            is2ghz);
+                       REG_RMW_FIELD(ah, switch_chain_reg[chain],
+                                     AR_SWITCH_TABLE_ALL, value);
+               }
+       }
+
+       if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
+               value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1);
+               /*
+                * main_lnaconf, alt_lnaconf, main_tb, alt_tb
+                * are the fields present
+                */
+               regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+               regval &= (~AR_ANT_DIV_CTRL_ALL);
+               regval |= (value & 0x3f) << AR_ANT_DIV_CTRL_ALL_S;
+               /* enable_lnadiv */
+               regval &= (~AR_PHY_9485_ANT_DIV_LNADIV);
+               regval |= ((value >> 6) & 0x1) <<
+                               AR_PHY_9485_ANT_DIV_LNADIV_S;
+               REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+
+               /*enable fast_div */
+               regval = REG_READ(ah, AR_PHY_CCK_DETECT);
+               regval &= (~AR_FAST_DIV_ENABLE);
+               regval |= ((value >> 7) & 0x1) <<
+                               AR_FAST_DIV_ENABLE_S;
+               REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
+               ant_div_ctl1 =
+                       ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
+               /* check whether antenna diversity is enabled */
+               if ((ant_div_ctl1 >> 0x6) == 0x3) {
+                       regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+                       /*
+                        * clear bits 25-30 main_lnaconf, alt_lnaconf,
+                        * main_tb, alt_tb
+                        */
+                       regval &= (~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF |
+                                       AR_PHY_9485_ANT_DIV_ALT_LNACONF |
+                                       AR_PHY_9485_ANT_DIV_ALT_GAINTB |
+                                       AR_PHY_9485_ANT_DIV_MAIN_GAINTB));
+                       /* by default use LNA1 for the main antenna */
+                       regval |= (AR_PHY_9485_ANT_DIV_LNA1 <<
+                                       AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S);
+                       regval |= (AR_PHY_9485_ANT_DIV_LNA2 <<
+                                       AR_PHY_9485_ANT_DIV_ALT_LNACONF_S);
+                       REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+               }
+
+
+       }
+
+}
+
+static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
+{
+       int drive_strength;
+       unsigned long reg;
+
+       drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
+
+       if (!drive_strength)
+               return;
+
+       reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
+       reg &= ~0x00ffffc0;
+       reg |= 0x5 << 21;
+       reg |= 0x5 << 18;
+       reg |= 0x5 << 15;
+       reg |= 0x5 << 12;
+       reg |= 0x5 << 9;
+       reg |= 0x5 << 6;
+       REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
+
+       reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
+       reg &= ~0xffffffe0;
+       reg |= 0x5 << 29;
+       reg |= 0x5 << 26;
+       reg |= 0x5 << 23;
+       reg |= 0x5 << 20;
+       reg |= 0x5 << 17;
+       reg |= 0x5 << 14;
+       reg |= 0x5 << 11;
+       reg |= 0x5 << 8;
+       reg |= 0x5 << 5;
+       REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
+
+       reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
+       reg &= ~0xff800000;
+       reg |= 0x5 << 29;
+       reg |= 0x5 << 26;
+       reg |= 0x5 << 23;
+       REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
+}
+
+static u16 ar9003_hw_atten_chain_get(struct ath_hw *ah, int chain,
+                                    struct ath9k_channel *chan)
+{
+       int f[3], t[3];
+       u16 value;
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+       if (chain >= 0 && chain < 3) {
+               if (IS_CHAN_2GHZ(chan))
+                       return eep->modalHeader2G.xatten1DB[chain];
+               else if (eep->base_ext2.xatten1DBLow[chain] != 0) {
+                       t[0] = eep->base_ext2.xatten1DBLow[chain];
+                       f[0] = 5180;
+                       t[1] = eep->modalHeader5G.xatten1DB[chain];
+                       f[1] = 5500;
+                       t[2] = eep->base_ext2.xatten1DBHigh[chain];
+                       f[2] = 5785;
+                       value = ar9003_hw_power_interpolate((s32) chan->channel,
+                                                           f, t, 3);
+                       return value;
+               } else
+                       return eep->modalHeader5G.xatten1DB[chain];
+       }
+
+       return 0;
+}
+
+
+static u16 ar9003_hw_atten_chain_get_margin(struct ath_hw *ah, int chain,
+                                           struct ath9k_channel *chan)
+{
+       int f[3], t[3];
+       u16 value;
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+       if (chain >= 0 && chain < 3) {
+               if (IS_CHAN_2GHZ(chan))
+                       return eep->modalHeader2G.xatten1Margin[chain];
+               else if (eep->base_ext2.xatten1MarginLow[chain] != 0) {
+                       t[0] = eep->base_ext2.xatten1MarginLow[chain];
+                       f[0] = 5180;
+                       t[1] = eep->modalHeader5G.xatten1Margin[chain];
+                       f[1] = 5500;
+                       t[2] = eep->base_ext2.xatten1MarginHigh[chain];
+                       f[2] = 5785;
+                       value = ar9003_hw_power_interpolate((s32) chan->channel,
+                                                           f, t, 3);
+                       return value;
+               } else
+                       return eep->modalHeader5G.xatten1Margin[chain];
+       }
+
+       return 0;
+}
+
+static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       int i;
+       u16 value;
+       unsigned long ext_atten_reg[3] = {AR_PHY_EXT_ATTEN_CTL_0,
+                                         AR_PHY_EXT_ATTEN_CTL_1,
+                                         AR_PHY_EXT_ATTEN_CTL_2,
+                                        };
+
+       /* Test value. if 0 then attenuation is unused. Don't load anything. */
+       for (i = 0; i < 3; i++) {
+               if (ah->txchainmask & BIT(i)) {
+                       value = ar9003_hw_atten_chain_get(ah, i, chan);
+                       REG_RMW_FIELD(ah, ext_atten_reg[i],
+                                     AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
+
+                       value = ar9003_hw_atten_chain_get_margin(ah, i, chan);
+                       REG_RMW_FIELD(ah, ext_atten_reg[i],
+                                     AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
+                                     value);
+               }
+       }
+}
+
+static bool is_pmu_set(struct ath_hw *ah, u32 pmu_reg, int pmu_set)
+{
+       int timeout = 100;
+
+       while (pmu_set != REG_READ(ah, pmu_reg)) {
+               if (timeout-- == 0)
+                       return false;
+               REG_WRITE(ah, pmu_reg, pmu_set);
+               udelay(10);
+       }
+
+       return true;
+}
+
+static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
+{
+       int internal_regulator =
+               ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
+       u32 reg_val;
+
+       if (internal_regulator) {
+               if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
+                       int reg_pmu_set;
+
+                       reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM;
+                       REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+                       if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+                               return;
+
+                       if (AR_SREV_9330(ah)) {
+                               if (ah->is_clk_25mhz) {
+                                       reg_pmu_set = (3 << 1) | (8 << 4) |
+                                                     (3 << 8) | (1 << 14) |
+                                                     (6 << 17) | (1 << 20) |
+                                                     (3 << 24);
+                               } else {
+                                       reg_pmu_set = (4 << 1)  | (7 << 4) |
+                                                     (3 << 8)  | (1 << 14) |
+                                                     (6 << 17) | (1 << 20) |
+                                                     (3 << 24);
+                               }
+                       } else {
+                               reg_pmu_set = (5 << 1) | (7 << 4) |
+                                             (2 << 8) | (2 << 14) |
+                                             (6 << 17) | (1 << 20) |
+                                             (3 << 24) | (1 << 28);
+                       }
+
+                       REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
+                       if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set))
+                               return;
+
+                       reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0xFFC00000)
+                                       | (4 << 26);
+                       REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+                       if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+                               return;
+
+                       reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0x00200000)
+                                       | (1 << 21);
+                       REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+                       if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+                               return;
+               } else if (AR_SREV_9462(ah)) {
+                       reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+                       REG_WRITE(ah, AR_PHY_PMU1, reg_val);
+               } else {
+                       /* Internal regulator is ON. Write swreg register. */
+                       reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+                       REG_WRITE(ah, AR_RTC_REG_CONTROL1,
+                                 REG_READ(ah, AR_RTC_REG_CONTROL1) &
+                                 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
+                       REG_WRITE(ah, AR_RTC_REG_CONTROL0, reg_val);
+                       /* Set REG_CONTROL1.SWREG_PROGRAM */
+                       REG_WRITE(ah, AR_RTC_REG_CONTROL1,
+                                 REG_READ(ah,
+                                          AR_RTC_REG_CONTROL1) |
+                                          AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
+               }
+       } else {
+               if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
+                       REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
+                       while (REG_READ_FIELD(ah, AR_PHY_PMU2,
+                                               AR_PHY_PMU2_PGM))
+                               udelay(10);
+
+                       REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
+                       while (!REG_READ_FIELD(ah, AR_PHY_PMU1,
+                                               AR_PHY_PMU1_PWD))
+                               udelay(10);
+                       REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1);
+                       while (!REG_READ_FIELD(ah, AR_PHY_PMU2,
+                                               AR_PHY_PMU2_PGM))
+                               udelay(10);
+               } else if (AR_SREV_9462(ah))
+                       REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
+               else {
+                       reg_val = REG_READ(ah, AR_RTC_SLEEP_CLK) |
+                               AR_RTC_FORCE_SWREG_PRD;
+                       REG_WRITE(ah, AR_RTC_SLEEP_CLK, reg_val);
+               }
+       }
+
+}
+
+static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0];
+
+       if (eep->baseEepHeader.featureEnable & 0x40) {
+               tuning_caps_param &= 0x7f;
+               REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPINDAC,
+                             tuning_caps_param);
+               REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPOUTDAC,
+                             tuning_caps_param);
+       }
+}
+
+static void ar9003_hw_quick_drop_apply(struct ath_hw *ah, u16 freq)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       int quick_drop = ath9k_hw_ar9300_get_eeprom(ah, EEP_QUICK_DROP);
+       s32 t[3], f[3] = {5180, 5500, 5785};
+
+       if (!quick_drop)
+               return;
+
+       if (freq < 4000)
+               quick_drop = eep->modalHeader2G.quick_drop;
+       else {
+               t[0] = eep->base_ext1.quick_drop_low;
+               t[1] = eep->modalHeader5G.quick_drop;
+               t[2] = eep->base_ext1.quick_drop_high;
+               quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
+       }
+       REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
+}
+
+static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, u16 freq)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       u32 value;
+
+       value = (freq < 4000) ? eep->modalHeader2G.txEndToXpaOff :
+                               eep->modalHeader5G.txEndToXpaOff;
+
+       REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL,
+                     AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF, value);
+       REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL,
+                     AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF, value);
+}
+
+static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
+                                            struct ath9k_channel *chan)
+{
+       ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
+       ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
+       ar9003_hw_drive_strength_apply(ah);
+       ar9003_hw_atten_apply(ah, chan);
+       ar9003_hw_quick_drop_apply(ah, chan->channel);
+       if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
+               ar9003_hw_internal_regulator_apply(ah);
+       if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
+               ar9003_hw_apply_tuning_caps(ah);
+       ar9003_hw_txend_to_xpa_off_apply(ah, chan->channel);
+}
+
+static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
+                                     struct ath9k_channel *chan)
+{
+}
+
+/*
+ * Returns the interpolated y value corresponding to the specified x value
+ * from the np ordered pairs of data (px,py).
+ * The pairs do not have to be in any order.
+ * If the specified x value is less than any of the px,
+ * the returned y value is equal to the py for the lowest px.
+ * If the specified x value is greater than any of the px,
+ * the returned y value is equal to the py for the highest px.
+ */
+static int ar9003_hw_power_interpolate(int32_t x,
+                                      int32_t *px, int32_t *py, u_int16_t np)
+{
+       int ip = 0;
+       int lx = 0, ly = 0, lhave = 0;
+       int hx = 0, hy = 0, hhave = 0;
+       int dx = 0;
+       int y = 0;
+
+       lhave = 0;
+       hhave = 0;
+
+       /* identify best lower and higher x calibration measurement */
+       for (ip = 0; ip < np; ip++) {
+               dx = x - px[ip];
+
+               /* this measurement is higher than our desired x */
+               if (dx <= 0) {
+                       if (!hhave || dx > (x - hx)) {
+                               /* new best higher x measurement */
+                               hx = px[ip];
+                               hy = py[ip];
+                               hhave = 1;
+                       }
+               }
+               /* this measurement is lower than our desired x */
+               if (dx >= 0) {
+                       if (!lhave || dx < (x - lx)) {
+                               /* new best lower x measurement */
+                               lx = px[ip];
+                               ly = py[ip];
+                               lhave = 1;
+                       }
+               }
+       }
+
+       /* the low x is good */
+       if (lhave) {
+               /* so is the high x */
+               if (hhave) {
+                       /* they're the same, so just pick one */
+                       if (hx == lx)
+                               y = ly;
+                       else    /* interpolate  */
+                               y = interpolate(x, lx, hx, ly, hy);
+               } else          /* only low is good, use it */
+                       y = ly;
+       } else if (hhave)       /* only high is good, use it */
+               y = hy;
+       else /* nothing is good,this should never happen unless np=0, ???? */
+               y = -(1 << 30);
+       return y;
+}
+
+static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
+                                      u16 rateIndex, u16 freq, bool is2GHz)
+{
+       u16 numPiers, i;
+       s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
+       s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       struct cal_tgt_pow_legacy *pEepromTargetPwr;
+       u8 *pFreqBin;
+
+       if (is2GHz) {
+               numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
+               pEepromTargetPwr = eep->calTargetPower2G;
+               pFreqBin = eep->calTarget_freqbin_2G;
+       } else {
+               numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
+               pEepromTargetPwr = eep->calTargetPower5G;
+               pFreqBin = eep->calTarget_freqbin_5G;
+       }
+
+       /*
+        * create array of channels and targetpower from
+        * targetpower piers stored on eeprom
+        */
+       for (i = 0; i < numPiers; i++) {
+               freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
+               targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
+       }
+
+       /* interpolate to get target power for given frequency */
+       return (u8) ar9003_hw_power_interpolate((s32) freq,
+                                                freqArray,
+                                                targetPowerArray, numPiers);
+}
+
+static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
+                                           u16 rateIndex,
+                                           u16 freq, bool is2GHz)
+{
+       u16 numPiers, i;
+       s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
+       s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       struct cal_tgt_pow_ht *pEepromTargetPwr;
+       u8 *pFreqBin;
+
+       if (is2GHz) {
+               numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
+               pEepromTargetPwr = eep->calTargetPower2GHT20;
+               pFreqBin = eep->calTarget_freqbin_2GHT20;
+       } else {
+               numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
+               pEepromTargetPwr = eep->calTargetPower5GHT20;
+               pFreqBin = eep->calTarget_freqbin_5GHT20;
+       }
+
+       /*
+        * create array of channels and targetpower
+        * from targetpower piers stored on eeprom
+        */
+       for (i = 0; i < numPiers; i++) {
+               freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
+               targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
+       }
+
+       /* interpolate to get target power for given frequency */
+       return (u8) ar9003_hw_power_interpolate((s32) freq,
+                                                freqArray,
+                                                targetPowerArray, numPiers);
+}
+
+static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
+                                           u16 rateIndex,
+                                           u16 freq, bool is2GHz)
+{
+       u16 numPiers, i;
+       s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS];
+       s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS];
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       struct cal_tgt_pow_ht *pEepromTargetPwr;
+       u8 *pFreqBin;
+
+       if (is2GHz) {
+               numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
+               pEepromTargetPwr = eep->calTargetPower2GHT40;
+               pFreqBin = eep->calTarget_freqbin_2GHT40;
+       } else {
+               numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
+               pEepromTargetPwr = eep->calTargetPower5GHT40;
+               pFreqBin = eep->calTarget_freqbin_5GHT40;
+       }
+
+       /*
+        * create array of channels and targetpower from
+        * targetpower piers stored on eeprom
+        */
+       for (i = 0; i < numPiers; i++) {
+               freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
+               targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
+       }
+
+       /* interpolate to get target power for given frequency */
+       return (u8) ar9003_hw_power_interpolate((s32) freq,
+                                                freqArray,
+                                                targetPowerArray, numPiers);
+}
+
+static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
+                                          u16 rateIndex, u16 freq)
+{
+       u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i;
+       s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
+       s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck;
+       u8 *pFreqBin = eep->calTarget_freqbin_Cck;
+
+       /*
+        * create array of channels and targetpower from
+        * targetpower piers stored on eeprom
+        */
+       for (i = 0; i < numPiers; i++) {
+               freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
+               targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
+       }
+
+       /* interpolate to get target power for given frequency */
+       return (u8) ar9003_hw_power_interpolate((s32) freq,
+                                                freqArray,
+                                                targetPowerArray, numPiers);
+}
+
+/* Set tx power registers to array of values passed in */
+static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
+{
+#define POW_SM(_r, _s)     (((_r) & 0x3f) << (_s))
+       /* make sure forced gain is not set */
+       REG_WRITE(ah, AR_PHY_TX_FORCED_GAIN, 0);
+
+       /* Write the OFDM power per rate set */
+
+       /* 6 (LSB), 9, 12, 18 (MSB) */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(0),
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
+
+       /* 24 (LSB), 36, 48, 54 (MSB) */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(1),
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
+
+       /* Write the CCK power per rate set */
+
+       /* 1L (LSB), reserved, 2L, 2S (MSB) */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(2),
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
+                 /* POW_SM(txPowerTimes2,  8) | this is reserved for AR9003 */
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
+
+       /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(3),
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
+           );
+
+        /* Write the power for duplicated frames - HT40 */
+
+        /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(8),
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24],  8) |
+                 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L],  0)
+           );
+
+       /* Write the HT20 power per rate set */
+
+       /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(4),
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0)
+           );
+
+       /* 6 (LSB), 7, 12, 13 (MSB) */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(5),
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0)
+           );
+
+       /* 14 (LSB), 15, 20, 21 */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(9),
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0)
+           );
+
+       /* Mixed HT20 and HT40 rates */
+
+       /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(10),
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0)
+           );
+
+       /*
+        * Write the HT40 power per rate set
+        * correct PAR difference between HT40 and HT20/LEGACY
+        * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
+        */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(6),
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0)
+           );
+
+       /* 6 (LSB), 7, 12, 13 (MSB) */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(7),
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0)
+           );
+
+       /* 14 (LSB), 15, 20, 21 */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE(11),
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
+                 POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0)
+           );
+
+       return 0;
+#undef POW_SM
+}
+
+static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq,
+                                             u8 *targetPowerValT2)
+{
+       /* XXX: hard code for now, need to get from eeprom struct */
+       u8 ht40PowerIncForPdadc = 0;
+       bool is2GHz = false;
+       unsigned int i = 0;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (freq < 4000)
+               is2GHz = true;
+
+       targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
+           ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
+                                        is2GHz);
+       targetPowerValT2[ALL_TARGET_LEGACY_36] =
+           ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
+                                        is2GHz);
+       targetPowerValT2[ALL_TARGET_LEGACY_48] =
+           ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
+                                        is2GHz);
+       targetPowerValT2[ALL_TARGET_LEGACY_54] =
+           ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
+                                        is2GHz);
+       targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
+           ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
+                                            freq);
+       targetPowerValT2[ALL_TARGET_LEGACY_5S] =
+           ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq);
+       targetPowerValT2[ALL_TARGET_LEGACY_11L] =
+           ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq);
+       targetPowerValT2[ALL_TARGET_LEGACY_11S] =
+           ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq);
+       targetPowerValT2[ALL_TARGET_HT20_0_8_16] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
+                                             freq, is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_4] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_5] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_6] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_7] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_12] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_13] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_14] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_15] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_20] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_21] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_22] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT20_23] =
+           ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
+                                             is2GHz);
+       targetPowerValT2[ALL_TARGET_HT40_0_8_16] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
+                                             freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_4] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_5] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_6] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_7] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_12] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_13] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_14] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_15] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_20] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_21] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_22] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+       targetPowerValT2[ALL_TARGET_HT40_23] =
+           ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
+                                             is2GHz) + ht40PowerIncForPdadc;
+
+       for (i = 0; i < ar9300RateSize; i++) {
+               ath_dbg(common, EEPROM, "TPC[%02d] 0x%08x\n",
+                       i, targetPowerValT2[i]);
+       }
+}
+
+static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
+                                 int mode,
+                                 int ipier,
+                                 int ichain,
+                                 int *pfrequency,
+                                 int *pcorrection,
+                                 int *ptemperature, int *pvoltage)
+{
+       u8 *pCalPier;
+       struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
+       int is2GHz;
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (ichain >= AR9300_MAX_CHAINS) {
+               ath_dbg(common, EEPROM,
+                       "Invalid chain index, must be less than %d\n",
+                       AR9300_MAX_CHAINS);
+               return -1;
+       }
+
+       if (mode) {             /* 5GHz */
+               if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
+                       ath_dbg(common, EEPROM,
+                               "Invalid 5GHz cal pier index, must be less than %d\n",
+                               AR9300_NUM_5G_CAL_PIERS);
+                       return -1;
+               }
+               pCalPier = &(eep->calFreqPier5G[ipier]);
+               pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
+               is2GHz = 0;
+       } else {
+               if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
+                       ath_dbg(common, EEPROM,
+                               "Invalid 2GHz cal pier index, must be less than %d\n",
+                               AR9300_NUM_2G_CAL_PIERS);
+                       return -1;
+               }
+
+               pCalPier = &(eep->calFreqPier2G[ipier]);
+               pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
+               is2GHz = 1;
+       }
+
+       *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
+       *pcorrection = pCalPierStruct->refPower;
+       *ptemperature = pCalPierStruct->tempMeas;
+       *pvoltage = pCalPierStruct->voltMeas;
+
+       return 0;
+}
+
+static int ar9003_hw_power_control_override(struct ath_hw *ah,
+                                           int frequency,
+                                           int *correction,
+                                           int *voltage, int *temperature)
+{
+       int tempSlope = 0;
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       int f[3], t[3];
+
+       REG_RMW(ah, AR_PHY_TPC_11_B0,
+               (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+               AR_PHY_TPC_OLPC_GAIN_DELTA);
+       if (ah->caps.tx_chainmask & BIT(1))
+               REG_RMW(ah, AR_PHY_TPC_11_B1,
+                       (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+                       AR_PHY_TPC_OLPC_GAIN_DELTA);
+       if (ah->caps.tx_chainmask & BIT(2))
+               REG_RMW(ah, AR_PHY_TPC_11_B2,
+                       (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+                       AR_PHY_TPC_OLPC_GAIN_DELTA);
+
+       /* enable open loop power control on chip */
+       REG_RMW(ah, AR_PHY_TPC_6_B0,
+               (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
+               AR_PHY_TPC_6_ERROR_EST_MODE);
+       if (ah->caps.tx_chainmask & BIT(1))
+               REG_RMW(ah, AR_PHY_TPC_6_B1,
+                       (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
+                       AR_PHY_TPC_6_ERROR_EST_MODE);
+       if (ah->caps.tx_chainmask & BIT(2))
+               REG_RMW(ah, AR_PHY_TPC_6_B2,
+                       (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
+                       AR_PHY_TPC_6_ERROR_EST_MODE);
+
+       /*
+        * enable temperature compensation
+        * Need to use register names
+        */
+       if (frequency < 4000)
+               tempSlope = eep->modalHeader2G.tempSlope;
+       else if (eep->base_ext2.tempSlopeLow != 0) {
+               t[0] = eep->base_ext2.tempSlopeLow;
+               f[0] = 5180;
+               t[1] = eep->modalHeader5G.tempSlope;
+               f[1] = 5500;
+               t[2] = eep->base_ext2.tempSlopeHigh;
+               f[2] = 5785;
+               tempSlope = ar9003_hw_power_interpolate((s32) frequency,
+                                                       f, t, 3);
+       } else
+               tempSlope = eep->modalHeader5G.tempSlope;
+
+       REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
+
+       if (AR_SREV_9462_20(ah))
+               REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1,
+                             AR_PHY_TPC_19_B1_ALPHA_THERM, tempSlope);
+
+
+       REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
+                     temperature[0]);
+
+       return 0;
+}
+
+/* Apply the recorded correction values. */
+static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
+{
+       int ichain, ipier, npier;
+       int mode;
+       int lfrequency[AR9300_MAX_CHAINS],
+           lcorrection[AR9300_MAX_CHAINS],
+           ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
+       int hfrequency[AR9300_MAX_CHAINS],
+           hcorrection[AR9300_MAX_CHAINS],
+           htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
+       int fdiff;
+       int correction[AR9300_MAX_CHAINS],
+           voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
+       int pfrequency, pcorrection, ptemperature, pvoltage;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       mode = (frequency >= 4000);
+       if (mode)
+               npier = AR9300_NUM_5G_CAL_PIERS;
+       else
+               npier = AR9300_NUM_2G_CAL_PIERS;
+
+       for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
+               lfrequency[ichain] = 0;
+               hfrequency[ichain] = 100000;
+       }
+       /* identify best lower and higher frequency calibration measurement */
+       for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
+               for (ipier = 0; ipier < npier; ipier++) {
+                       if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
+                                                   &pfrequency, &pcorrection,
+                                                   &ptemperature, &pvoltage)) {
+                               fdiff = frequency - pfrequency;
+
+                               /*
+                                * this measurement is higher than
+                                * our desired frequency
+                                */
+                               if (fdiff <= 0) {
+                                       if (hfrequency[ichain] <= 0 ||
+                                           hfrequency[ichain] >= 100000 ||
+                                           fdiff >
+                                           (frequency - hfrequency[ichain])) {
+                                               /*
+                                                * new best higher
+                                                * frequency measurement
+                                                */
+                                               hfrequency[ichain] = pfrequency;
+                                               hcorrection[ichain] =
+                                                   pcorrection;
+                                               htemperature[ichain] =
+                                                   ptemperature;
+                                               hvoltage[ichain] = pvoltage;
+                                       }
+                               }
+                               if (fdiff >= 0) {
+                                       if (lfrequency[ichain] <= 0
+                                           || fdiff <
+                                           (frequency - lfrequency[ichain])) {
+                                               /*
+                                                * new best lower
+                                                * frequency measurement
+                                                */
+                                               lfrequency[ichain] = pfrequency;
+                                               lcorrection[ichain] =
+                                                   pcorrection;
+                                               ltemperature[ichain] =
+                                                   ptemperature;
+                                               lvoltage[ichain] = pvoltage;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /* interpolate  */
+       for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
+               ath_dbg(common, EEPROM, "ch=%d f=%d low=%d %d h=%d %d\n",
+                       ichain, frequency, lfrequency[ichain],
+                       lcorrection[ichain], hfrequency[ichain],
+                       hcorrection[ichain]);
+               /* they're the same, so just pick one */
+               if (hfrequency[ichain] == lfrequency[ichain]) {
+                       correction[ichain] = lcorrection[ichain];
+                       voltage[ichain] = lvoltage[ichain];
+                       temperature[ichain] = ltemperature[ichain];
+               }
+               /* the low frequency is good */
+               else if (frequency - lfrequency[ichain] < 1000) {
+                       /* so is the high frequency, interpolate */
+                       if (hfrequency[ichain] - frequency < 1000) {
+
+                               correction[ichain] = interpolate(frequency,
+                                               lfrequency[ichain],
+                                               hfrequency[ichain],
+                                               lcorrection[ichain],
+                                               hcorrection[ichain]);
+
+                               temperature[ichain] = interpolate(frequency,
+                                               lfrequency[ichain],
+                                               hfrequency[ichain],
+                                               ltemperature[ichain],
+                                               htemperature[ichain]);
+
+                               voltage[ichain] = interpolate(frequency,
+                                               lfrequency[ichain],
+                                               hfrequency[ichain],
+                                               lvoltage[ichain],
+                                               hvoltage[ichain]);
+                       }
+                       /* only low is good, use it */
+                       else {
+                               correction[ichain] = lcorrection[ichain];
+                               temperature[ichain] = ltemperature[ichain];
+                               voltage[ichain] = lvoltage[ichain];
+                       }
+               }
+               /* only high is good, use it */
+               else if (hfrequency[ichain] - frequency < 1000) {
+                       correction[ichain] = hcorrection[ichain];
+                       temperature[ichain] = htemperature[ichain];
+                       voltage[ichain] = hvoltage[ichain];
+               } else {        /* nothing is good, presume 0???? */
+                       correction[ichain] = 0;
+                       temperature[ichain] = 0;
+                       voltage[ichain] = 0;
+               }
+       }
+
+       ar9003_hw_power_control_override(ah, frequency, correction, voltage,
+                                        temperature);
+
+       ath_dbg(common, EEPROM,
+               "for frequency=%d, calibration correction = %d %d %d\n",
+               frequency, correction[0], correction[1], correction[2]);
+
+       return 0;
+}
+
+static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
+                                          int idx,
+                                          int edge,
+                                          bool is2GHz)
+{
+       struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
+       struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
+
+       if (is2GHz)
+               return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge]);
+       else
+               return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge]);
+}
+
+static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
+                                            int idx,
+                                            unsigned int edge,
+                                            u16 freq,
+                                            bool is2GHz)
+{
+       struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
+       struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
+
+       u8 *ctl_freqbin = is2GHz ?
+               &eep->ctl_freqbin_2G[idx][0] :
+               &eep->ctl_freqbin_5G[idx][0];
+
+       if (is2GHz) {
+               if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
+                   CTL_EDGE_FLAGS(ctl_2g[idx].ctlEdges[edge - 1]))
+                       return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge - 1]);
+       } else {
+               if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
+                   CTL_EDGE_FLAGS(ctl_5g[idx].ctlEdges[edge - 1]))
+                       return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]);
+       }
+
+       return MAX_RATE_POWER;
+}
+
+/*
+ * Find the maximum conformance test limit for the given channel and CTL info
+ */
+static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
+                                       u16 freq, int idx, bool is2GHz)
+{
+       u16 twiceMaxEdgePower = MAX_RATE_POWER;
+       u8 *ctl_freqbin = is2GHz ?
+               &eep->ctl_freqbin_2G[idx][0] :
+               &eep->ctl_freqbin_5G[idx][0];
+       u16 num_edges = is2GHz ?
+               AR9300_NUM_BAND_EDGES_2G : AR9300_NUM_BAND_EDGES_5G;
+       unsigned int edge;
+
+       /* Get the edge power */
+       for (edge = 0;
+            (edge < num_edges) && (ctl_freqbin[edge] != AR5416_BCHAN_UNUSED);
+            edge++) {
+               /*
+                * If there's an exact channel match or an inband flag set
+                * on the lower channel use the given rdEdgePower
+                */
+               if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) {
+                       twiceMaxEdgePower =
+                               ar9003_hw_get_direct_edge_power(eep, idx,
+                                                               edge, is2GHz);
+                       break;
+               } else if ((edge > 0) &&
+                          (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge],
+                                                     is2GHz))) {
+                       twiceMaxEdgePower =
+                               ar9003_hw_get_indirect_edge_power(eep, idx,
+                                                                 edge, freq,
+                                                                 is2GHz);
+                       /*
+                        * Leave loop - no more affecting edges possible in
+                        * this monotonic increasing list
+                        */
+                       break;
+               }
+       }
+       return twiceMaxEdgePower;
+}
+
+static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
+                                              struct ath9k_channel *chan,
+                                              u8 *pPwrArray, u16 cfgCtl,
+                                              u8 antenna_reduction,
+                                              u16 powerLimit)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
+       u16 twiceMaxEdgePower;
+       int i;
+       u16 scaledPower = 0, minCtlPower;
+       static const u16 ctlModesFor11a[] = {
+               CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+       };
+       static const u16 ctlModesFor11g[] = {
+               CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
+               CTL_11G_EXT, CTL_2GHT40
+       };
+       u16 numCtlModes;
+       const u16 *pCtlMode;
+       u16 ctlMode, freq;
+       struct chan_centers centers;
+       u8 *ctlIndex;
+       u8 ctlNum;
+       u16 twiceMinEdgePower;
+       bool is2ghz = IS_CHAN_2GHZ(chan);
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       scaledPower = powerLimit - antenna_reduction;
+
+       /*
+        * Reduce scaled Power by number of chains active to get
+        * to per chain tx power level
+        */
+       switch (ar5416_get_ntxchains(ah->txchainmask)) {
+       case 1:
+               break;
+       case 2:
+               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               else
+                       scaledPower = 0;
+               break;
+       case 3:
+               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               else
+                       scaledPower = 0;
+               break;
+       }
+
+       scaledPower = max((u16)0, scaledPower);
+
+       /*
+        * Get target powers from EEPROM - our baseline for TX Power
+        */
+       if (is2ghz) {
+               /* Setup for CTL modes */
+               /* CTL_11B, CTL_11G, CTL_2GHT20 */
+               numCtlModes =
+                       ARRAY_SIZE(ctlModesFor11g) -
+                                  SUB_NUM_CTL_MODES_AT_2G_40;
+               pCtlMode = ctlModesFor11g;
+               if (IS_CHAN_HT40(chan))
+                       /* All 2G CTL's */
+                       numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+       } else {
+               /* Setup for CTL modes */
+               /* CTL_11A, CTL_5GHT20 */
+               numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
+                                        SUB_NUM_CTL_MODES_AT_5G_40;
+               pCtlMode = ctlModesFor11a;
+               if (IS_CHAN_HT40(chan))
+                       /* All 5G CTL's */
+                       numCtlModes = ARRAY_SIZE(ctlModesFor11a);
+       }
+
+       /*
+        * For MIMO, need to apply regulatory caps individually across
+        * dynamically running modes: CCK, OFDM, HT20, HT40
+        *
+        * The outer loop walks through each possible applicable runtime mode.
+        * The inner loop walks through each ctlIndex entry in EEPROM.
+        * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
+        */
+       for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+               bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+                       (pCtlMode[ctlMode] == CTL_2GHT40);
+               if (isHt40CtlMode)
+                       freq = centers.synth_center;
+               else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+                       freq = centers.ext_center;
+               else
+                       freq = centers.ctl_center;
+
+               ath_dbg(common, REGULATORY,
+                       "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, EXT_ADDITIVE %d\n",
+                       ctlMode, numCtlModes, isHt40CtlMode,
+                       (pCtlMode[ctlMode] & EXT_ADDITIVE));
+
+               /* walk through each CTL index stored in EEPROM */
+               if (is2ghz) {
+                       ctlIndex = pEepData->ctlIndex_2G;
+                       ctlNum = AR9300_NUM_CTLS_2G;
+               } else {
+                       ctlIndex = pEepData->ctlIndex_5G;
+                       ctlNum = AR9300_NUM_CTLS_5G;
+               }
+
+               twiceMaxEdgePower = MAX_RATE_POWER;
+               for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) {
+                       ath_dbg(common, REGULATORY,
+                               "LOOP-Ctlidx %d: cfgCtl 0x%2.2x pCtlMode 0x%2.2x ctlIndex 0x%2.2x chan %d\n",
+                               i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
+                               chan->channel);
+
+                               /*
+                                * compare test group from regulatory
+                                * channel list with test mode from pCtlMode
+                                * list
+                                */
+                               if ((((cfgCtl & ~CTL_MODE_M) |
+                                      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+                                       ctlIndex[i]) ||
+                                   (((cfgCtl & ~CTL_MODE_M) |
+                                      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+                                    ((ctlIndex[i] & CTL_MODE_M) |
+                                      SD_NO_CTL))) {
+                                       twiceMinEdgePower =
+                                         ar9003_hw_get_max_edge_power(pEepData,
+                                                                      freq, i,
+                                                                      is2ghz);
+
+                                       if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
+                                               /*
+                                                * Find the minimum of all CTL
+                                                * edge powers that apply to
+                                                * this channel
+                                                */
+                                               twiceMaxEdgePower =
+                                                       min(twiceMaxEdgePower,
+                                                           twiceMinEdgePower);
+                                               else {
+                                                       /* specific */
+                                                       twiceMaxEdgePower =
+                                                         twiceMinEdgePower;
+                                                       break;
+                                               }
+                               }
+                       }
+
+                       minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+                       ath_dbg(common, REGULATORY,
+                               "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n",
+                               ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+                               scaledPower, minCtlPower);
+
+                       /* Apply ctl mode to correct target power set */
+                       switch (pCtlMode[ctlMode]) {
+                       case CTL_11B:
+                               for (i = ALL_TARGET_LEGACY_1L_5L;
+                                    i <= ALL_TARGET_LEGACY_11S; i++)
+                                       pPwrArray[i] =
+                                         (u8)min((u16)pPwrArray[i],
+                                                 minCtlPower);
+                               break;
+                       case CTL_11A:
+                       case CTL_11G:
+                               for (i = ALL_TARGET_LEGACY_6_24;
+                                    i <= ALL_TARGET_LEGACY_54; i++)
+                                       pPwrArray[i] =
+                                         (u8)min((u16)pPwrArray[i],
+                                                 minCtlPower);
+                               break;
+                       case CTL_5GHT20:
+                       case CTL_2GHT20:
+                               for (i = ALL_TARGET_HT20_0_8_16;
+                                    i <= ALL_TARGET_HT20_21; i++)
+                                       pPwrArray[i] =
+                                         (u8)min((u16)pPwrArray[i],
+                                                 minCtlPower);
+                               pPwrArray[ALL_TARGET_HT20_22] =
+                                 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
+                                         minCtlPower);
+                               pPwrArray[ALL_TARGET_HT20_23] =
+                                 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
+                                          minCtlPower);
+                               break;
+                       case CTL_5GHT40:
+                       case CTL_2GHT40:
+                               for (i = ALL_TARGET_HT40_0_8_16;
+                                    i <= ALL_TARGET_HT40_23; i++)
+                                       pPwrArray[i] =
+                                         (u8)min((u16)pPwrArray[i],
+                                                 minCtlPower);
+                               break;
+                       default:
+                           break;
+                       }
+       } /* end ctl mode checking */
+}
+
+static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx)
+{
+       u8 mod_idx = mcs_idx % 8;
+
+       if (mod_idx <= 3)
+               return mod_idx ? (base_pwridx + 1) : base_pwridx;
+       else
+               return base_pwridx + 4 * (mcs_idx / 8) + mod_idx - 2;
+}
+
+static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
+                                       struct ath9k_channel *chan, u16 cfgCtl,
+                                       u8 twiceAntennaReduction,
+                                       u8 powerLimit, bool test)
+{
+       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       struct ar9300_modal_eep_header *modal_hdr;
+       u8 targetPowerValT2[ar9300RateSize];
+       u8 target_power_val_t2_eep[ar9300RateSize];
+       unsigned int i = 0, paprd_scale_factor = 0;
+       u8 pwr_idx, min_pwridx = 0;
+
+       ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
+
+       if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+               if (IS_CHAN_2GHZ(chan))
+                       modal_hdr = &eep->modalHeader2G;
+               else
+                       modal_hdr = &eep->modalHeader5G;
+
+               ah->paprd_ratemask =
+                       le32_to_cpu(modal_hdr->papdRateMaskHt20) &
+                       AR9300_PAPRD_RATE_MASK;
+
+               ah->paprd_ratemask_ht40 =
+                       le32_to_cpu(modal_hdr->papdRateMaskHt40) &
+                       AR9300_PAPRD_RATE_MASK;
+
+               paprd_scale_factor = ar9003_get_paprd_scale_factor(ah, chan);
+               min_pwridx = IS_CHAN_HT40(chan) ? ALL_TARGET_HT40_0_8_16 :
+                                                 ALL_TARGET_HT20_0_8_16;
+
+               if (!ah->paprd_table_write_done) {
+                       memcpy(target_power_val_t2_eep, targetPowerValT2,
+                              sizeof(targetPowerValT2));
+                       for (i = 0; i < 24; i++) {
+                               pwr_idx = mcsidx_to_tgtpwridx(i, min_pwridx);
+                               if (ah->paprd_ratemask & (1 << i)) {
+                                       if (targetPowerValT2[pwr_idx] &&
+                                           targetPowerValT2[pwr_idx] ==
+                                           target_power_val_t2_eep[pwr_idx])
+                                               targetPowerValT2[pwr_idx] -=
+                                                       paprd_scale_factor;
+                               }
+                       }
+               }
+               memcpy(target_power_val_t2_eep, targetPowerValT2,
+                      sizeof(targetPowerValT2));
+       }
+
+       ar9003_hw_set_power_per_rate_table(ah, chan,
+                                          targetPowerValT2, cfgCtl,
+                                          twiceAntennaReduction,
+                                          powerLimit);
+
+       if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+               for (i = 0; i < ar9300RateSize; i++) {
+                       if ((ah->paprd_ratemask & (1 << i)) &&
+                           (abs(targetPowerValT2[i] -
+                               target_power_val_t2_eep[i]) >
+                           paprd_scale_factor)) {
+                               ah->paprd_ratemask &= ~(1 << i);
+                               ath_dbg(common, EEPROM,
+                                       "paprd disabled for mcs %d\n", i);
+                       }
+               }
+       }
+
+       regulatory->max_power_level = 0;
+       for (i = 0; i < ar9300RateSize; i++) {
+               if (targetPowerValT2[i] > regulatory->max_power_level)
+                       regulatory->max_power_level = targetPowerValT2[i];
+       }
+
+       ath9k_hw_update_regulatory_maxpower(ah);
+
+       if (test)
+               return;
+
+       for (i = 0; i < ar9300RateSize; i++) {
+               ath_dbg(common, EEPROM, "TPC[%02d] 0x%08x\n",
+                       i, targetPowerValT2[i]);
+       }
+
+       ah->txpower_limit = regulatory->max_power_level;
+
+       /* Write target power array to registers */
+       ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
+       ar9003_hw_calibration_apply(ah, chan->channel);
+
+       if (IS_CHAN_2GHZ(chan)) {
+               if (IS_CHAN_HT40(chan))
+                       i = ALL_TARGET_HT40_0_8_16;
+               else
+                       i = ALL_TARGET_HT20_0_8_16;
+       } else {
+               if (IS_CHAN_HT40(chan))
+                       i = ALL_TARGET_HT40_7;
+               else
+                       i = ALL_TARGET_HT20_7;
+       }
+       ah->paprd_target_power = targetPowerValT2[i];
+}
+
+static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
+                                           u16 i, bool is2GHz)
+{
+       return AR_NO_SPUR;
+}
+
+s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+       return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
+}
+
+s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+       return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
+}
+
+u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+       if (is_2ghz)
+               return eep->modalHeader2G.spurChans;
+       else
+               return eep->modalHeader5G.spurChans;
+}
+
+unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
+                                          struct ath9k_channel *chan)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+       if (IS_CHAN_2GHZ(chan))
+               return MS(le32_to_cpu(eep->modalHeader2G.papdRateMaskHt20),
+                         AR9300_PAPRD_SCALE_1);
+       else {
+               if (chan->channel >= 5700)
+               return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20),
+                         AR9300_PAPRD_SCALE_1);
+               else if (chan->channel >= 5400)
+                       return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
+                                  AR9300_PAPRD_SCALE_2);
+               else
+                       return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
+                                 AR9300_PAPRD_SCALE_1);
+       }
+}
+
+static u32 ath9k_hw_ar9003_dump_eep_power(struct ath_hw *ah, u8 *buf,
+                                         u32 len, u32 size)
+{
+#undef PR_EEP
+#define PR_EEP(_s, _val) \
+       do {                                                            \
+               len += snprintf(buf + len, size - len, _s, (_val));     \
+       } while (0)
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       int i, j;
+
+       PR_EEP("macAddr : %pM\n", eep->macAddr);
+       len += snprintf(buf + len, size - len, "calPierData2G :\n");
+       len += snprintf(buf + len, size - len,
+                       "Chain  refPower voltMeas tempMeas "
+                       "rxNoisefloorCal rxNoisefloorPower rxTempMeas\n");
+       for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+               if (!(ah->txchainmask & BIT(i)))
+                       continue;
+
+               for (j = 0; j < AR9300_NUM_2G_CAL_PIERS; j++) {
+                       len += snprintf(buf + len, size - len,
+                               "%2d %8d %8d %10d %10d %20d %8d\n", i,
+                               eep->calPierData2G[i][j].refPower,
+                               eep->calPierData2G[i][j].voltMeas,
+                               eep->calPierData2G[i][j].tempMeas,
+                               eep->calPierData2G[i][j].rxNoisefloorCal,
+                               eep->calPierData2G[i][j].rxNoisefloorPower,
+                               eep->calPierData2G[i][j].rxTempMeas);
+               }
+       }
+       len += snprintf(buf + len, size - len, "\ncalTarget_freqbin_Cck :\n");
+       for (i = 0; i < AR9300_NUM_2G_CCK_TARGET_POWERS; i++)
+               PR_EEP("%u ", FBIN2FREQ(eep->calTarget_freqbin_Cck[i], 1));
+       len += snprintf(buf + len, size - len, "\n");
+
+       len += snprintf(buf + len, size - len, "\ncalTarget_freqbin_2G :\n");
+       for (i = 0; i < AR9300_NUM_2G_20_TARGET_POWERS; i++)
+               PR_EEP("%u ", FBIN2FREQ(eep->calTarget_freqbin_2G[i], 1));
+       len += snprintf(buf + len, size - len, "\n");
+
+       len += snprintf(buf + len, size - len,
+                       "\ncalTarget_freqbin_2GHT20 :\n");
+       for (i = 0; i < AR9300_NUM_2G_20_TARGET_POWERS; i++)
+               PR_EEP("%u ", FBIN2FREQ(eep->calTarget_freqbin_2GHT20[i], 1));
+       len += snprintf(buf + len, size - len, "\n");
+
+       len += snprintf(buf + len, size - len,
+                       "\ncalTarget_freqbin_2GHT40 :\n");
+       for (i = 0; i < AR9300_NUM_2G_40_TARGET_POWERS; i++)
+               PR_EEP("%u ", FBIN2FREQ(eep->calTarget_freqbin_2GHT40[i], 1));
+       len += snprintf(buf + len, size - len, "\n");
+
+       len += snprintf(buf + len, size - len, "\ncalTargetPowerCck :\n");
+       for (i = 0; i < AR9300_NUM_2G_CCK_TARGET_POWERS; i++) {
+               for (j = 0; j < 4; j++)
+                       PR_EEP("%u ", (eep->calTargetPowerCck[i].tPow2x[j])/2);
+               len += snprintf(buf + len, size - len, "\n");
+       }
+
+       len += snprintf(buf + len, size - len, "\ncalTargetPower2G :\n");
+       for (i = 0; i < AR9300_NUM_2G_20_TARGET_POWERS; i++) {
+               for (j = 0; j < 4; j++)
+                       PR_EEP("%u ", (eep->calTargetPower2G[i].tPow2x[j])/2);
+               len += snprintf(buf + len, size - len, "\n");
+       }
+
+       len += snprintf(buf + len, size - len, "\ncalTargetPower2GHT20 :\n");
+       for (i = 0; i < AR9300_NUM_2G_20_TARGET_POWERS; i++) {
+               for (j = 0; j < 14; j++)
+                       PR_EEP("%u ",
+                              (eep->calTargetPower2GHT20[i].tPow2x[j])/2);
+               len += snprintf(buf + len, size - len, "\n");
+       }
+
+       len += snprintf(buf + len, size - len, "\ncalTargetPower2GHT40 :\n");
+       for (i = 0; i < AR9300_NUM_2G_40_TARGET_POWERS; i++) {
+               for (j = 0; j < 14; j++)
+                       PR_EEP("%u ",
+                              (eep->calTargetPower2GHT40[i].tPow2x[j])/2);
+               len += snprintf(buf + len, size - len, "\n");
+       }
+
+       len += snprintf(buf + len, size - len, "\nctlIndex_2G :\n");
+       for (i = 0; i < AR9300_NUM_CTLS_2G; i++)
+               PR_EEP("0x%x ", eep->ctlIndex_2G[i]);
+       len += snprintf(buf + len, size - len, "\n");
+
+       len += snprintf(buf + len, size - len, "\nctl_freqbin_2G:\n");
+       for (i = 0; i < AR9300_NUM_CTLS_2G; i++) {
+               for (j = 0; j < AR9300_NUM_BAND_EDGES_2G; j++)
+                       PR_EEP("%u ", FBIN2FREQ(eep->ctl_freqbin_2G[i][j], 1));
+               len += snprintf(buf + len, size - len, "\n");
+       }
+
+       len += snprintf(buf + len, size - len,
+                       "\nctlPowerData_2G : { power, flag }\n");
+       for (i = 0; i < AR9300_NUM_CTLS_2G; i++) {
+               for (j = 0; j < AR9300_NUM_BAND_EDGES_2G; j++) {
+                       len += snprintf(buf + len, size - len, "{ %d, %u } ",
+                          CTL_EDGE_TPOWER(eep->ctlPowerData_2G[i].ctlEdges[j]),
+                          CTL_EDGE_FLAGS(eep->ctlPowerData_2G[i].ctlEdges[j]));
+               }
+               len += snprintf(buf + len, size - len, "\n");
+       }
+       len += snprintf(buf + len, size - len, "\ncalPierData5G :\n");
+       len += snprintf(buf + len, size - len,
+                       "Chain  refPower voltMeas tempMeas "
+                       "rxNoisefloorCal rxNoisefloorPower rxTempMeas\n");
+       for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+               if (!(ah->txchainmask & BIT(i)))
+                       continue;
+
+               for (j = 0; j < AR9300_NUM_5G_CAL_PIERS; j++) {
+                       len += snprintf(buf + len, size - len,
+                               "%2d %8d %8d %10d %10d %20d %8d\n", i,
+                               eep->calPierData5G[i][j].refPower,
+                               eep->calPierData5G[i][j].voltMeas,
+                               eep->calPierData5G[i][j].tempMeas,
+                               eep->calPierData5G[i][j].rxNoisefloorCal,
+                               eep->calPierData5G[i][j].rxNoisefloorPower,
+                               eep->calPierData5G[i][j].rxTempMeas);
+               }
+       }
+       len += snprintf(buf + len, size - len, "\ncalTarget_freqbin_5G :\n");
+       for (i = 0; i < AR9300_NUM_5G_20_TARGET_POWERS; i++)
+               PR_EEP("%u ", FBIN2FREQ(eep->calTarget_freqbin_5G[i], 0));
+       len += snprintf(buf + len, size - len, "\n");
+
+       len += snprintf(buf + len, size - len,
+                       "\ncalTarget_freqbin_5GHT20 :\n");
+       for (i = 0; i < AR9300_NUM_5G_20_TARGET_POWERS; i++)
+               PR_EEP("%u ", FBIN2FREQ(eep->calTarget_freqbin_5GHT20[i], 0));
+       len += snprintf(buf + len, size - len, "\n");
+
+       len += snprintf(buf + len, size - len,
+                       "\ncalTarget_freqbin_5GHT40 :\n");
+       for (i = 0; i < AR9300_NUM_5G_40_TARGET_POWERS; i++)
+               PR_EEP("%u ", FBIN2FREQ(eep->calTarget_freqbin_5GHT40[i], 0));
+       len += snprintf(buf + len, size - len, "\n");
+
+       len += snprintf(buf + len, size - len, "\ncalTargetPower5G :\n");
+       for (i = 0; i < AR9300_NUM_5G_20_TARGET_POWERS; i++) {
+               for (j = 0; j < 4; j++)
+                       PR_EEP("%u ", (eep->calTargetPower5G[i].tPow2x[j])/2);
+               len += snprintf(buf + len, size - len, "\n");
+       }
+
+       len += snprintf(buf + len, size - len, "\ncalTargetPower5GHT20 :\n");
+       for (i = 0; i < AR9300_NUM_5G_20_TARGET_POWERS; i++) {
+               for (j = 0; j < 14; j++)
+                       PR_EEP("%u ",
+                              (eep->calTargetPower5GHT20[i].tPow2x[j])/2);
+               len += snprintf(buf + len, size - len, "\n");
+       }
+
+       len += snprintf(buf + len, size - len, "\ncalTargetPower5GHT40 :\n");
+       for (i = 0; i < AR9300_NUM_5G_40_TARGET_POWERS; i++) {
+               for (j = 0; j < 14; j++)
+                       PR_EEP("%u ",
+                              (eep->calTargetPower5GHT40[i].tPow2x[j])/2);
+               len += snprintf(buf + len, size - len, "\n");
+       }
+
+       len += snprintf(buf + len, size - len, "\nctlIndex_5G :\n");
+       for (i = 0; i < AR9300_NUM_CTLS_5G; i++)
+               PR_EEP("0x%x ", eep->ctlIndex_5G[i]);
+       len += snprintf(buf + len, size - len, "\n");
+
+       len += snprintf(buf + len, size - len, "\nctl_freqbin_5G:\n");
+       for (i = 0; i < AR9300_NUM_CTLS_5G; i++) {
+               for (j = 0; j < AR9300_NUM_BAND_EDGES_5G; j++)
+                       PR_EEP("%u ", FBIN2FREQ(eep->ctl_freqbin_5G[i][j], 0));
+               len += snprintf(buf + len, size - len, "\n");
+       }
+
+       len += snprintf(buf + len, size - len,
+                       "\nctlPowerData_5G : { power, flag }\n");
+       for (i = 0; i < AR9300_NUM_CTLS_5G; i++) {
+               for (j = 0; j < AR9300_NUM_BAND_EDGES_5G; j++) {
+                       len += snprintf(buf + len, size - len, "{ %d, %u } ",
+                          CTL_EDGE_TPOWER(eep->ctlPowerData_5G[i].ctlEdges[j]),
+                          CTL_EDGE_FLAGS(eep->ctlPowerData_5G[i].ctlEdges[j]));
+               }
+               len += snprintf(buf + len, size - len, "\n");
+       }
+       len += snprintf(buf + len, size - len, "\n");
+
+       if (ah->curchan)
+               PR_EEP("freq %d\n", ah->curchan->channel);
+
+       for (i = 0; i < 12; i++)
+               len += snprintf(buf + len, size - len,
+                               "Tx Power Rate %2d : 0x%08x\n",
+                               i, REG_READ(ah, AR_PHY_POWER_TX_RATE(i)));
+
+       if (len > size)
+               len = size;
+
+#undef PR_EEP
+       return len;
+}
+
+const struct eeprom_ops eep_ar9300_ops = {
+       .check_eeprom = ath9k_hw_ar9300_check_eeprom,
+       .get_eeprom = ath9k_hw_ar9300_get_eeprom,
+       .dump_eep_power = ath9k_hw_ar9003_dump_eep_power,
+       .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
+       .dump_eeprom = ath9k_hw_ar9003_dump_eeprom,
+       .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
+       .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
+       .set_board_values = ath9k_hw_ar9300_set_board_values,
+       .set_addac = ath9k_hw_ar9300_set_addac,
+       .set_txpower = ath9k_hw_ar9300_set_txpower,
+       .get_spur_channel = ath9k_hw_ar9300_get_spur_channel
+};
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_eeprom.h
new file mode 100644 (file)
index 0000000..bb223fe
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef AR9003_EEPROM_H
+#define AR9003_EEPROM_H
+
+#include <linux/types.h>
+
+#define AR9300_EEP_VER               0xD000
+#define AR9300_EEP_VER_MINOR_MASK    0xFFF
+#define AR9300_EEP_MINOR_VER_1       0x1
+#define AR9300_EEP_MINOR_VER         AR9300_EEP_MINOR_VER_1
+
+/* 16-bit offset location start of calibration struct */
+#define AR9300_EEP_START_LOC         256
+#define AR9300_NUM_5G_CAL_PIERS      8
+#define AR9300_NUM_2G_CAL_PIERS      3
+#define AR9300_NUM_5G_20_TARGET_POWERS  8
+#define AR9300_NUM_5G_40_TARGET_POWERS  8
+#define AR9300_NUM_2G_CCK_TARGET_POWERS 2
+#define AR9300_NUM_2G_20_TARGET_POWERS  3
+#define AR9300_NUM_2G_40_TARGET_POWERS  3
+/* #define AR9300_NUM_CTLS              21 */
+#define AR9300_NUM_CTLS_5G           9
+#define AR9300_NUM_CTLS_2G           12
+#define AR9300_NUM_BAND_EDGES_5G     8
+#define AR9300_NUM_BAND_EDGES_2G     4
+#define AR9300_EEPMISC_BIG_ENDIAN    0x01
+#define AR9300_EEPMISC_WOW           0x02
+#define AR9300_CUSTOMER_DATA_SIZE    20
+
+#define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x))
+#define AR9300_MAX_CHAINS            3
+#define AR9300_ANT_16S               25
+#define AR9300_FUTURE_MODAL_SZ       6
+
+#define AR9300_PAPRD_RATE_MASK         0x01ffffff
+#define AR9300_PAPRD_SCALE_1           0x0e000000
+#define AR9300_PAPRD_SCALE_1_S         25
+#define AR9300_PAPRD_SCALE_2           0x70000000
+#define AR9300_PAPRD_SCALE_2_S         28
+
+/* Delta from which to start power to pdadc table */
+/* This offset is used in both open loop and closed loop power control
+ * schemes. In open loop power control, it is not really needed, but for
+ * the "sake of consistency" it was kept. For certain AP designs, this
+ * value is overwritten by the value in the flag "pwrTableOffset" just
+ * before writing the pdadc vs pwr into the chip registers.
+ */
+#define AR9300_PWR_TABLE_OFFSET  0
+
+/* byte addressable */
+#define AR9300_EEPROM_SIZE (16*1024)
+
+#define AR9300_BASE_ADDR_4K 0xfff
+#define AR9300_BASE_ADDR 0x3ff
+#define AR9300_BASE_ADDR_512 0x1ff
+
+#define AR9300_OTP_BASE                        0x14000
+#define AR9300_OTP_STATUS              0x15f18
+#define AR9300_OTP_STATUS_TYPE         0x7
+#define AR9300_OTP_STATUS_VALID                0x4
+#define AR9300_OTP_STATUS_ACCESS_BUSY  0x2
+#define AR9300_OTP_STATUS_SM_BUSY      0x1
+#define AR9300_OTP_READ_DATA           0x15f1c
+
+enum targetPowerHTRates {
+       HT_TARGET_RATE_0_8_16,
+       HT_TARGET_RATE_1_3_9_11_17_19,
+       HT_TARGET_RATE_4,
+       HT_TARGET_RATE_5,
+       HT_TARGET_RATE_6,
+       HT_TARGET_RATE_7,
+       HT_TARGET_RATE_12,
+       HT_TARGET_RATE_13,
+       HT_TARGET_RATE_14,
+       HT_TARGET_RATE_15,
+       HT_TARGET_RATE_20,
+       HT_TARGET_RATE_21,
+       HT_TARGET_RATE_22,
+       HT_TARGET_RATE_23
+};
+
+enum targetPowerLegacyRates {
+       LEGACY_TARGET_RATE_6_24,
+       LEGACY_TARGET_RATE_36,
+       LEGACY_TARGET_RATE_48,
+       LEGACY_TARGET_RATE_54
+};
+
+enum targetPowerCckRates {
+       LEGACY_TARGET_RATE_1L_5L,
+       LEGACY_TARGET_RATE_5S,
+       LEGACY_TARGET_RATE_11L,
+       LEGACY_TARGET_RATE_11S
+};
+
+enum ar9300_Rates {
+       ALL_TARGET_LEGACY_6_24,
+       ALL_TARGET_LEGACY_36,
+       ALL_TARGET_LEGACY_48,
+       ALL_TARGET_LEGACY_54,
+       ALL_TARGET_LEGACY_1L_5L,
+       ALL_TARGET_LEGACY_5S,
+       ALL_TARGET_LEGACY_11L,
+       ALL_TARGET_LEGACY_11S,
+       ALL_TARGET_HT20_0_8_16,
+       ALL_TARGET_HT20_1_3_9_11_17_19,
+       ALL_TARGET_HT20_4,
+       ALL_TARGET_HT20_5,
+       ALL_TARGET_HT20_6,
+       ALL_TARGET_HT20_7,
+       ALL_TARGET_HT20_12,
+       ALL_TARGET_HT20_13,
+       ALL_TARGET_HT20_14,
+       ALL_TARGET_HT20_15,
+       ALL_TARGET_HT20_20,
+       ALL_TARGET_HT20_21,
+       ALL_TARGET_HT20_22,
+       ALL_TARGET_HT20_23,
+       ALL_TARGET_HT40_0_8_16,
+       ALL_TARGET_HT40_1_3_9_11_17_19,
+       ALL_TARGET_HT40_4,
+       ALL_TARGET_HT40_5,
+       ALL_TARGET_HT40_6,
+       ALL_TARGET_HT40_7,
+       ALL_TARGET_HT40_12,
+       ALL_TARGET_HT40_13,
+       ALL_TARGET_HT40_14,
+       ALL_TARGET_HT40_15,
+       ALL_TARGET_HT40_20,
+       ALL_TARGET_HT40_21,
+       ALL_TARGET_HT40_22,
+       ALL_TARGET_HT40_23,
+       ar9300RateSize,
+};
+
+
+struct eepFlags {
+       u8 opFlags;
+       u8 eepMisc;
+} __packed;
+
+enum CompressAlgorithm {
+       _CompressNone = 0,
+       _CompressLzma,
+       _CompressPairs,
+       _CompressBlock,
+       _Compress4,
+       _Compress5,
+       _Compress6,
+       _Compress7,
+};
+
+struct ar9300_base_eep_hdr {
+       __le16 regDmn[2];
+       /* 4 bits tx and 4 bits rx */
+       u8 txrxMask;
+       struct eepFlags opCapFlags;
+       u8 rfSilent;
+       u8 blueToothOptions;
+       u8 deviceCap;
+       /* takes lower byte in eeprom location */
+       u8 deviceType;
+       /* offset in dB to be added to beginning
+        * of pdadc table in calibration
+        */
+       int8_t pwrTableOffset;
+       u8 params_for_tuning_caps[2];
+       /*
+        * bit0 - enable tx temp comp
+        * bit1 - enable tx volt comp
+        * bit2 - enable fastClock - default to 1
+        * bit3 - enable doubling - default to 1
+        * bit4 - enable internal regulator - default to 1
+        */
+       u8 featureEnable;
+       /* misc flags: bit0 - turn down drivestrength */
+       u8 miscConfiguration;
+       u8 eepromWriteEnableGpio;
+       u8 wlanDisableGpio;
+       u8 wlanLedGpio;
+       u8 rxBandSelectGpio;
+       u8 txrxgain;
+       /* SW controlled internal regulator fields */
+       __le32 swreg;
+} __packed;
+
+struct ar9300_modal_eep_header {
+       /* 4 idle, t1, t2, b (4 bits per setting) */
+       __le32 antCtrlCommon;
+       /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+       __le32 antCtrlCommon2;
+       /* 6 idle, t, r, rx1, rx12, b (2 bits each) */
+       __le16 antCtrlChain[AR9300_MAX_CHAINS];
+       /* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+       u8 xatten1DB[AR9300_MAX_CHAINS];
+       /* 3  xatten1_margin for merlin (0xa20c/b20c 16:12 */
+       u8 xatten1Margin[AR9300_MAX_CHAINS];
+       int8_t tempSlope;
+       int8_t voltSlope;
+       /* spur channels in usual fbin coding format */
+       u8 spurChans[AR_EEPROM_MODAL_SPURS];
+       /* 3  Check if the register is per chain */
+       int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS];
+       u8 reserved[11];
+       int8_t quick_drop;
+       u8 xpaBiasLvl;
+       u8 txFrameToDataStart;
+       u8 txFrameToPaOn;
+       u8 txClip;
+       int8_t antennaGain;
+       u8 switchSettling;
+       int8_t adcDesiredSize;
+       u8 txEndToXpaOff;
+       u8 txEndToRxOn;
+       u8 txFrameToXpaOn;
+       u8 thresh62;
+       __le32 papdRateMaskHt20;
+       __le32 papdRateMaskHt40;
+       __le16 switchcomspdt;
+       u8 futureModal[8];
+} __packed;
+
+struct ar9300_cal_data_per_freq_op_loop {
+       int8_t refPower;
+       /* pdadc voltage at power measurement */
+       u8 voltMeas;
+       /* pcdac used for power measurement   */
+       u8 tempMeas;
+       /* range is -60 to -127 create a mapping equation 1db resolution */
+       int8_t rxNoisefloorCal;
+       /*range is same as noisefloor */
+       int8_t rxNoisefloorPower;
+       /* temp measured when noisefloor cal was performed */
+       u8 rxTempMeas;
+} __packed;
+
+struct cal_tgt_pow_legacy {
+       u8 tPow2x[4];
+} __packed;
+
+struct cal_tgt_pow_ht {
+       u8 tPow2x[14];
+} __packed;
+
+struct cal_ctl_data_2g {
+       u8 ctlEdges[AR9300_NUM_BAND_EDGES_2G];
+} __packed;
+
+struct cal_ctl_data_5g {
+       u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
+} __packed;
+
+struct ar9300_BaseExtension_1 {
+       u8 ant_div_control;
+       u8 future[11];
+       int8_t quick_drop_low;
+       int8_t quick_drop_high;
+} __packed;
+
+struct ar9300_BaseExtension_2 {
+       int8_t    tempSlopeLow;
+       int8_t    tempSlopeHigh;
+       u8   xatten1DBLow[AR9300_MAX_CHAINS];
+       u8   xatten1MarginLow[AR9300_MAX_CHAINS];
+       u8   xatten1DBHigh[AR9300_MAX_CHAINS];
+       u8   xatten1MarginHigh[AR9300_MAX_CHAINS];
+} __packed;
+
+struct ar9300_eeprom {
+       u8 eepromVersion;
+       u8 templateVersion;
+       u8 macAddr[6];
+       u8 custData[AR9300_CUSTOMER_DATA_SIZE];
+
+       struct ar9300_base_eep_hdr baseEepHeader;
+
+       struct ar9300_modal_eep_header modalHeader2G;
+       struct ar9300_BaseExtension_1 base_ext1;
+       u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS];
+       struct ar9300_cal_data_per_freq_op_loop
+        calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS];
+       u8 calTarget_freqbin_Cck[AR9300_NUM_2G_CCK_TARGET_POWERS];
+       u8 calTarget_freqbin_2G[AR9300_NUM_2G_20_TARGET_POWERS];
+       u8 calTarget_freqbin_2GHT20[AR9300_NUM_2G_20_TARGET_POWERS];
+       u8 calTarget_freqbin_2GHT40[AR9300_NUM_2G_40_TARGET_POWERS];
+       struct cal_tgt_pow_legacy
+        calTargetPowerCck[AR9300_NUM_2G_CCK_TARGET_POWERS];
+       struct cal_tgt_pow_legacy
+        calTargetPower2G[AR9300_NUM_2G_20_TARGET_POWERS];
+       struct cal_tgt_pow_ht
+        calTargetPower2GHT20[AR9300_NUM_2G_20_TARGET_POWERS];
+       struct cal_tgt_pow_ht
+        calTargetPower2GHT40[AR9300_NUM_2G_40_TARGET_POWERS];
+       u8 ctlIndex_2G[AR9300_NUM_CTLS_2G];
+       u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G];
+       struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G];
+       struct ar9300_modal_eep_header modalHeader5G;
+       struct ar9300_BaseExtension_2 base_ext2;
+       u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS];
+       struct ar9300_cal_data_per_freq_op_loop
+        calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS];
+       u8 calTarget_freqbin_5G[AR9300_NUM_5G_20_TARGET_POWERS];
+       u8 calTarget_freqbin_5GHT20[AR9300_NUM_5G_20_TARGET_POWERS];
+       u8 calTarget_freqbin_5GHT40[AR9300_NUM_5G_40_TARGET_POWERS];
+       struct cal_tgt_pow_legacy
+        calTargetPower5G[AR9300_NUM_5G_20_TARGET_POWERS];
+       struct cal_tgt_pow_ht
+        calTargetPower5GHT20[AR9300_NUM_5G_20_TARGET_POWERS];
+       struct cal_tgt_pow_ht
+        calTargetPower5GHT40[AR9300_NUM_5G_40_TARGET_POWERS];
+       u8 ctlIndex_5G[AR9300_NUM_CTLS_5G];
+       u8 ctl_freqbin_5G[AR9300_NUM_CTLS_5G][AR9300_NUM_BAND_EDGES_5G];
+       struct cal_ctl_data_5g ctlPowerData_5G[AR9300_NUM_CTLS_5G];
+} __packed;
+
+s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah);
+s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah);
+
+u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz);
+
+unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
+                                          struct ath9k_channel *chan);
+#endif
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_hw.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_hw.c
new file mode 100644 (file)
index 0000000..a0e3394
--- /dev/null
@@ -0,0 +1,782 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "ar9003_mac.h"
+#include "ar9003_2p2_initvals.h"
+#include "ar9485_initvals.h"
+#include "ar9340_initvals.h"
+#include "ar9330_1p1_initvals.h"
+#include "ar9330_1p2_initvals.h"
+#include "ar9580_1p0_initvals.h"
+#include "ar9462_2p0_initvals.h"
+
+/* General hardware code for the AR9003 hadware family */
+
+/*
+ * The AR9003 family uses a new INI format (pre, core, post
+ * arrays per subsystem). This provides support for the
+ * AR9003 2.2 chipsets.
+ */
+static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
+{
+#define PCIE_PLL_ON_CREQ_DIS_L1_2P0 \
+               ar9462_pciephy_pll_on_clkreq_disable_L1_2p0
+
+#define AR9462_BB_CTX_COEFJ(x) \
+               ar9462_##x##_baseband_core_txfir_coeff_japan_2484
+
+#define AR9462_BBC_TXIFR_COEFFJ \
+               ar9462_2p0_baseband_core_txfir_coeff_japan_2484
+       if (AR_SREV_9330_11(ah)) {
+               /* mac */
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+                               ar9331_1p1_mac_core,
+                               ARRAY_SIZE(ar9331_1p1_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9331_1p1_mac_postamble,
+                               ARRAY_SIZE(ar9331_1p1_mac_postamble), 5);
+
+               /* bb */
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9331_1p1_baseband_core,
+                               ARRAY_SIZE(ar9331_1p1_baseband_core), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9331_1p1_baseband_postamble,
+                               ARRAY_SIZE(ar9331_1p1_baseband_postamble), 5);
+
+               /* radio */
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9331_1p1_radio_core,
+                               ARRAY_SIZE(ar9331_1p1_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+               /* soc */
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9331_1p1_soc_preamble,
+                               ARRAY_SIZE(ar9331_1p1_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                               ar9331_1p1_soc_postamble,
+                               ARRAY_SIZE(ar9331_1p1_soc_postamble), 2);
+
+               /* rx/tx gain */
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9331_common_rx_gain_1p1,
+                               ARRAY_SIZE(ar9331_common_rx_gain_1p1), 2);
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_lowest_ob_db_tx_gain_1p1,
+                       ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+                       5);
+
+               /* additional clock settings */
+               if (ah->is_clk_25mhz)
+                       INIT_INI_ARRAY(&ah->iniAdditional,
+                                       ar9331_1p1_xtal_25M,
+                                       ARRAY_SIZE(ar9331_1p1_xtal_25M), 2);
+               else
+                       INIT_INI_ARRAY(&ah->iniAdditional,
+                                       ar9331_1p1_xtal_40M,
+                                       ARRAY_SIZE(ar9331_1p1_xtal_40M), 2);
+       } else if (AR_SREV_9330_12(ah)) {
+               /* mac */
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+                               ar9331_1p2_mac_core,
+                               ARRAY_SIZE(ar9331_1p2_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9331_1p2_mac_postamble,
+                               ARRAY_SIZE(ar9331_1p2_mac_postamble), 5);
+
+               /* bb */
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9331_1p2_baseband_core,
+                               ARRAY_SIZE(ar9331_1p2_baseband_core), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9331_1p2_baseband_postamble,
+                               ARRAY_SIZE(ar9331_1p2_baseband_postamble), 5);
+
+               /* radio */
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9331_1p2_radio_core,
+                               ARRAY_SIZE(ar9331_1p2_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+               /* soc */
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9331_1p2_soc_preamble,
+                               ARRAY_SIZE(ar9331_1p2_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                               ar9331_1p2_soc_postamble,
+                               ARRAY_SIZE(ar9331_1p2_soc_postamble), 2);
+
+               /* rx/tx gain */
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9331_common_rx_gain_1p2,
+                               ARRAY_SIZE(ar9331_common_rx_gain_1p2), 2);
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_lowest_ob_db_tx_gain_1p2,
+                       ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+                       5);
+
+               /* additional clock settings */
+               if (ah->is_clk_25mhz)
+                       INIT_INI_ARRAY(&ah->iniAdditional,
+                                       ar9331_1p2_xtal_25M,
+                                       ARRAY_SIZE(ar9331_1p2_xtal_25M), 2);
+               else
+                       INIT_INI_ARRAY(&ah->iniAdditional,
+                                       ar9331_1p2_xtal_40M,
+                                       ARRAY_SIZE(ar9331_1p2_xtal_40M), 2);
+       } else if (AR_SREV_9340(ah)) {
+               /* mac */
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+                               ar9340_1p0_mac_core,
+                               ARRAY_SIZE(ar9340_1p0_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9340_1p0_mac_postamble,
+                               ARRAY_SIZE(ar9340_1p0_mac_postamble), 5);
+
+               /* bb */
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9340_1p0_baseband_core,
+                               ARRAY_SIZE(ar9340_1p0_baseband_core), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9340_1p0_baseband_postamble,
+                               ARRAY_SIZE(ar9340_1p0_baseband_postamble), 5);
+
+               /* radio */
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9340_1p0_radio_core,
+                               ARRAY_SIZE(ar9340_1p0_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+                               ar9340_1p0_radio_postamble,
+                               ARRAY_SIZE(ar9340_1p0_radio_postamble), 5);
+
+               /* soc */
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9340_1p0_soc_preamble,
+                               ARRAY_SIZE(ar9340_1p0_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                               ar9340_1p0_soc_postamble,
+                               ARRAY_SIZE(ar9340_1p0_soc_postamble), 5);
+
+               /* rx/tx gain */
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9340Common_wo_xlna_rx_gain_table_1p0,
+                               ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
+                               5);
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9340Modes_high_ob_db_tx_gain_table_1p0,
+                               ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0),
+                               5);
+
+               INIT_INI_ARRAY(&ah->iniModesFastClock,
+                               ar9340Modes_fast_clock_1p0,
+                               ARRAY_SIZE(ar9340Modes_fast_clock_1p0),
+                               3);
+
+               if (!ah->is_clk_25mhz)
+                       INIT_INI_ARRAY(&ah->iniAdditional,
+                                      ar9340_1p0_radio_core_40M,
+                                      ARRAY_SIZE(ar9340_1p0_radio_core_40M),
+                                      2);
+       } else if (AR_SREV_9485_11(ah)) {
+               /* mac */
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+                               ar9485_1_1_mac_core,
+                               ARRAY_SIZE(ar9485_1_1_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9485_1_1_mac_postamble,
+                               ARRAY_SIZE(ar9485_1_1_mac_postamble), 5);
+
+               /* bb */
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1,
+                               ARRAY_SIZE(ar9485_1_1), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9485_1_1_baseband_core,
+                               ARRAY_SIZE(ar9485_1_1_baseband_core), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9485_1_1_baseband_postamble,
+                               ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5);
+
+               /* radio */
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9485_1_1_radio_core,
+                               ARRAY_SIZE(ar9485_1_1_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+                               ar9485_1_1_radio_postamble,
+                               ARRAY_SIZE(ar9485_1_1_radio_postamble), 2);
+
+               /* soc */
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9485_1_1_soc_preamble,
+                               ARRAY_SIZE(ar9485_1_1_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0);
+
+               /* rx/tx gain */
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9485Common_wo_xlna_rx_gain_1_1,
+                               ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2);
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9485_modes_lowest_ob_db_tx_gain_1_1,
+                               ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+                               5);
+
+               /* Load PCIE SERDES settings from INI */
+
+               /* Awake Setting */
+
+               INIT_INI_ARRAY(&ah->iniPcieSerdes,
+                               ar9485_1_1_pcie_phy_clkreq_disable_L1,
+                               ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
+                               2);
+
+               /* Sleep Setting */
+
+               INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+                               ar9485_1_1_pcie_phy_clkreq_disable_L1,
+                               ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
+                               2);
+       } else if (AR_SREV_9462_20(ah)) {
+
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core,
+                               ARRAY_SIZE(ar9462_2p0_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9462_2p0_mac_postamble,
+                               ARRAY_SIZE(ar9462_2p0_mac_postamble), 5);
+
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9462_2p0_baseband_core,
+                               ARRAY_SIZE(ar9462_2p0_baseband_core), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9462_2p0_baseband_postamble,
+                               ARRAY_SIZE(ar9462_2p0_baseband_postamble), 5);
+
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9462_2p0_radio_core,
+                               ARRAY_SIZE(ar9462_2p0_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+                               ar9462_2p0_radio_postamble,
+                               ARRAY_SIZE(ar9462_2p0_radio_postamble), 5);
+               INIT_INI_ARRAY(&ah->ini_radio_post_sys2ant,
+                               ar9462_2p0_radio_postamble_sys2ant,
+                               ARRAY_SIZE(ar9462_2p0_radio_postamble_sys2ant),
+                               5);
+
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9462_2p0_soc_preamble,
+                               ARRAY_SIZE(ar9462_2p0_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                               ar9462_2p0_soc_postamble,
+                               ARRAY_SIZE(ar9462_2p0_soc_postamble), 5);
+
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9462_common_rx_gain_table_2p0,
+                               ARRAY_SIZE(ar9462_common_rx_gain_table_2p0), 2);
+
+               /* Awake -> Sleep Setting */
+               INIT_INI_ARRAY(&ah->iniPcieSerdes,
+                               PCIE_PLL_ON_CREQ_DIS_L1_2P0,
+                               ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
+                               2);
+               /* Sleep -> Awake Setting */
+               INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+                               PCIE_PLL_ON_CREQ_DIS_L1_2P0,
+                               ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
+                               2);
+
+               /* Fast clock modal settings */
+               INIT_INI_ARRAY(&ah->iniModesFastClock,
+                               ar9462_modes_fast_clock_2p0,
+                               ARRAY_SIZE(ar9462_modes_fast_clock_2p0), 3);
+
+               INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+                               AR9462_BB_CTX_COEFJ(2p0),
+                               ARRAY_SIZE(AR9462_BB_CTX_COEFJ(2p0)), 2);
+
+               INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ,
+                               ARRAY_SIZE(AR9462_BBC_TXIFR_COEFFJ), 2);
+
+       } else if (AR_SREV_9580(ah)) {
+               /* mac */
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+                               ar9580_1p0_mac_core,
+                               ARRAY_SIZE(ar9580_1p0_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9580_1p0_mac_postamble,
+                               ARRAY_SIZE(ar9580_1p0_mac_postamble), 5);
+
+               /* bb */
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9580_1p0_baseband_core,
+                               ARRAY_SIZE(ar9580_1p0_baseband_core), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9580_1p0_baseband_postamble,
+                               ARRAY_SIZE(ar9580_1p0_baseband_postamble), 5);
+
+               /* radio */
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9580_1p0_radio_core,
+                               ARRAY_SIZE(ar9580_1p0_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+                               ar9580_1p0_radio_postamble,
+                               ARRAY_SIZE(ar9580_1p0_radio_postamble), 5);
+
+               /* soc */
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9580_1p0_soc_preamble,
+                               ARRAY_SIZE(ar9580_1p0_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                               ar9580_1p0_soc_postamble,
+                               ARRAY_SIZE(ar9580_1p0_soc_postamble), 5);
+
+               /* rx/tx gain */
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9580_1p0_rx_gain_table,
+                               ARRAY_SIZE(ar9580_1p0_rx_gain_table), 2);
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9580_1p0_low_ob_db_tx_gain_table,
+                               ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
+                               5);
+
+               INIT_INI_ARRAY(&ah->iniModesFastClock,
+                               ar9580_1p0_modes_fast_clock,
+                               ARRAY_SIZE(ar9580_1p0_modes_fast_clock),
+                               3);
+       } else {
+               /* mac */
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+                               ar9300_2p2_mac_core,
+                               ARRAY_SIZE(ar9300_2p2_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9300_2p2_mac_postamble,
+                               ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
+
+               /* bb */
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9300_2p2_baseband_core,
+                               ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9300_2p2_baseband_postamble,
+                               ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
+
+               /* radio */
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9300_2p2_radio_core,
+                               ARRAY_SIZE(ar9300_2p2_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+                               ar9300_2p2_radio_postamble,
+                               ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
+
+               /* soc */
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9300_2p2_soc_preamble,
+                               ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                               ar9300_2p2_soc_postamble,
+                               ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
+
+               /* rx/tx gain */
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9300Common_rx_gain_table_2p2,
+                               ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+                               ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+                               5);
+
+               /* Load PCIE SERDES settings from INI */
+
+               /* Awake Setting */
+
+               INIT_INI_ARRAY(&ah->iniPcieSerdes,
+                               ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
+                               ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
+                               2);
+
+               /* Sleep Setting */
+
+               INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+                               ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
+                               ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
+                               2);
+
+               /* Fast clock modal settings */
+               INIT_INI_ARRAY(&ah->iniModesFastClock,
+                               ar9300Modes_fast_clock_2p2,
+                               ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
+                               3);
+       }
+}
+
+static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_lowest_ob_db_tx_gain_1p2,
+                       ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+                       5);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_lowest_ob_db_tx_gain_1p1,
+                       ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+                       5);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+                       5);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9485_modes_lowest_ob_db_tx_gain_1_1,
+                       ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+                       5);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9580_1p0_lowest_ob_db_tx_gain_table,
+                       ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table),
+                       5);
+       else if (AR_SREV_9462_20(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9462_modes_low_ob_db_tx_gain_table_2p0,
+                       ARRAY_SIZE(ar9462_modes_low_ob_db_tx_gain_table_2p0),
+                       5);
+       else
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+                       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+                       5);
+}
+
+static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_high_ob_db_tx_gain_1p2,
+                       ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
+                       5);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_high_ob_db_tx_gain_1p1,
+                       ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
+                       5);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+                       5);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9485Modes_high_ob_db_tx_gain_1_1,
+                       ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
+                       5);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9580_1p0_high_ob_db_tx_gain_table,
+                       ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
+                       5);
+       else if (AR_SREV_9462_20(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9462_modes_high_ob_db_tx_gain_table_2p0,
+                       ARRAY_SIZE(ar9462_modes_high_ob_db_tx_gain_table_2p0),
+                       5);
+       else
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9300Modes_high_ob_db_tx_gain_table_2p2,
+                       ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
+                       5);
+}
+
+static void ar9003_tx_gain_table_mode2(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_low_ob_db_tx_gain_1p2,
+                       ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
+                       5);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_low_ob_db_tx_gain_1p1,
+                       ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
+                       5);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+                       5);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9485Modes_low_ob_db_tx_gain_1_1,
+                       ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
+                       5);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9580_1p0_low_ob_db_tx_gain_table,
+                       ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
+                       5);
+       else
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9300Modes_low_ob_db_tx_gain_table_2p2,
+                       ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
+                       5);
+}
+
+static void ar9003_tx_gain_table_mode3(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_high_power_tx_gain_1p2,
+                       ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
+                       5);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_high_power_tx_gain_1p1,
+                       ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
+                       5);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+                       5);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9485Modes_high_power_tx_gain_1_1,
+                       ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
+                       5);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9580_1p0_high_power_tx_gain_table,
+                       ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table),
+                       5);
+       else
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9300Modes_high_power_tx_gain_table_2p2,
+                       ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
+                       5);
+}
+
+static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
+{
+       switch (ar9003_hw_get_tx_gain_idx(ah)) {
+       case 0:
+       default:
+               ar9003_tx_gain_table_mode0(ah);
+               break;
+       case 1:
+               ar9003_tx_gain_table_mode1(ah);
+               break;
+       case 2:
+               ar9003_tx_gain_table_mode2(ah);
+               break;
+       case 3:
+               ar9003_tx_gain_table_mode3(ah);
+               break;
+       }
+}
+
+static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9331_common_rx_gain_1p2,
+                               ARRAY_SIZE(ar9331_common_rx_gain_1p2),
+                               2);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9331_common_rx_gain_1p1,
+                               ARRAY_SIZE(ar9331_common_rx_gain_1p1),
+                               2);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9340Common_rx_gain_table_1p0,
+                               ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
+                               2);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9485Common_wo_xlna_rx_gain_1_1,
+                               ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+                               2);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9580_1p0_rx_gain_table,
+                               ARRAY_SIZE(ar9580_1p0_rx_gain_table),
+                               2);
+       else if (AR_SREV_9462_20(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9462_common_rx_gain_table_2p0,
+                               ARRAY_SIZE(ar9462_common_rx_gain_table_2p0),
+                               2);
+       else
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9300Common_rx_gain_table_2p2,
+                               ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
+                               2);
+}
+
+static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9331_common_wo_xlna_rx_gain_1p2,
+                       ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
+                       2);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9331_common_wo_xlna_rx_gain_1p1,
+                       ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
+                       2);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9340Common_wo_xlna_rx_gain_table_1p0,
+                       ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
+                       2);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9485Common_wo_xlna_rx_gain_1_1,
+                       ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+                       2);
+       else if (AR_SREV_9462_20(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9462_common_wo_xlna_rx_gain_table_2p0,
+                       ARRAY_SIZE(ar9462_common_wo_xlna_rx_gain_table_2p0),
+                       2);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9580_1p0_wo_xlna_rx_gain_table,
+                       ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
+                       2);
+       else
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9300Common_wo_xlna_rx_gain_table_2p2,
+                       ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
+                       2);
+}
+
+static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
+{
+       if (AR_SREV_9462_20(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                              ar9462_common_mixed_rx_gain_table_2p0,
+                              ARRAY_SIZE(ar9462_common_mixed_rx_gain_table_2p0), 2);
+}
+
+static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
+{
+       switch (ar9003_hw_get_rx_gain_idx(ah)) {
+       case 0:
+       default:
+               ar9003_rx_gain_table_mode0(ah);
+               break;
+       case 1:
+               ar9003_rx_gain_table_mode1(ah);
+               break;
+       case 2:
+               ar9003_rx_gain_table_mode2(ah);
+               break;
+       }
+}
+
+/* set gain table pointers according to values read from the eeprom */
+static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
+{
+       ar9003_tx_gain_table_apply(ah);
+       ar9003_rx_gain_table_apply(ah);
+}
+
+/*
+ * Helper for ASPM support.
+ *
+ * Disable PLL when in L0s as well as receiver clock when in L1.
+ * This power saving option must be enabled through the SerDes.
+ *
+ * Programming the SerDes must go through the same 288 bit serial shift
+ * register as the other analog registers.  Hence the 9 writes.
+ */
+static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
+                                        bool power_off)
+{
+       /* Nothing to do on restore for 11N */
+       if (!power_off /* !restore */) {
+               /* set bit 19 to allow forcing of pcie core into L1 state */
+               REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+
+               /* Several PCIe massages to ensure proper behaviour */
+               if (ah->config.pcie_waen)
+                       REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
+               else
+                       REG_WRITE(ah, AR_WA, ah->WARegVal);
+       }
+
+       /*
+        * Configire PCIE after Ini init. SERDES values now come from ini file
+        * This enables PCIe low power mode.
+        */
+       if (ah->config.pcieSerDesWrite) {
+               unsigned int i;
+               struct ar5416IniArray *array;
+
+               array = power_off ? &ah->iniPcieSerdes :
+                                   &ah->iniPcieSerdesLowPower;
+
+               for (i = 0; i < array->ia_rows; i++) {
+                       REG_WRITE(ah,
+                                 INI_RA(array, i, 0),
+                                 INI_RA(array, i, 1));
+               }
+       }
+}
+
+/* Sets up the AR9003 hardware familiy callbacks */
+void ar9003_hw_attach_ops(struct ath_hw *ah)
+{
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+       struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
+       priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
+       priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
+
+       ops->config_pci_powersave = ar9003_hw_configpcipowersave;
+
+       ar9003_hw_attach_phy_ops(ah);
+       ar9003_hw_attach_calib_ops(ah);
+       ar9003_hw_attach_mac_ops(ah);
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_mac.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_mac.c
new file mode 100644 (file)
index 0000000..2001272
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/export.h>
+#include "hw.h"
+#include "ar9003_mac.h"
+#include "ar9003_mci.h"
+
+static void ar9003_hw_rx_enable(struct ath_hw *hw)
+{
+       REG_WRITE(hw, AR_CR, 0);
+}
+
+static void
+ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
+{
+       struct ar9003_txc *ads = ds;
+       int checksum = 0;
+       u32 val, ctl12, ctl17;
+       u8 desc_len;
+
+       desc_len = (AR_SREV_9462(ah) ? 0x18 : 0x17);
+
+       val = (ATHEROS_VENDOR_ID << AR_DescId_S) |
+             (1 << AR_TxRxDesc_S) |
+             (1 << AR_CtrlStat_S) |
+             (i->qcu << AR_TxQcuNum_S) | desc_len;
+
+       checksum += val;
+       ACCESS_ONCE(ads->info) = val;
+
+       checksum += i->link;
+       ACCESS_ONCE(ads->link) = i->link;
+
+       checksum += i->buf_addr[0];
+       ACCESS_ONCE(ads->data0) = i->buf_addr[0];
+       checksum += i->buf_addr[1];
+       ACCESS_ONCE(ads->data1) = i->buf_addr[1];
+       checksum += i->buf_addr[2];
+       ACCESS_ONCE(ads->data2) = i->buf_addr[2];
+       checksum += i->buf_addr[3];
+       ACCESS_ONCE(ads->data3) = i->buf_addr[3];
+
+       checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen);
+       ACCESS_ONCE(ads->ctl3) = val;
+       checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen);
+       ACCESS_ONCE(ads->ctl5) = val;
+       checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen);
+       ACCESS_ONCE(ads->ctl7) = val;
+       checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen);
+       ACCESS_ONCE(ads->ctl9) = val;
+
+       checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff);
+       ACCESS_ONCE(ads->ctl10) = checksum;
+
+       if (i->is_first || i->is_last) {
+               ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0)
+                       | set11nTries(i->rates, 1)
+                       | set11nTries(i->rates, 2)
+                       | set11nTries(i->rates, 3)
+                       | (i->dur_update ? AR_DurUpdateEna : 0)
+                       | SM(0, AR_BurstDur);
+
+               ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0)
+                       | set11nRate(i->rates, 1)
+                       | set11nRate(i->rates, 2)
+                       | set11nRate(i->rates, 3);
+       } else {
+               ACCESS_ONCE(ads->ctl13) = 0;
+               ACCESS_ONCE(ads->ctl14) = 0;
+       }
+
+       ads->ctl20 = 0;
+       ads->ctl21 = 0;
+       ads->ctl22 = 0;
+       ads->ctl23 = 0;
+
+       ctl17 = SM(i->keytype, AR_EncrType);
+       if (!i->is_first) {
+               ACCESS_ONCE(ads->ctl11) = 0;
+               ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore;
+               ACCESS_ONCE(ads->ctl15) = 0;
+               ACCESS_ONCE(ads->ctl16) = 0;
+               ACCESS_ONCE(ads->ctl17) = ctl17;
+               ACCESS_ONCE(ads->ctl18) = 0;
+               ACCESS_ONCE(ads->ctl19) = 0;
+               return;
+       }
+
+       ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
+               | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+               | SM(i->txpower, AR_XmitPower)
+               | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+               | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+               | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
+               | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+               | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
+                  (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
+
+       ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ?
+                SM(i->keyix, AR_DestIdx) : 0)
+               | SM(i->type, AR_FrameType)
+               | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+               | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+               | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+       ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
+       switch (i->aggr) {
+       case AGGR_BUF_FIRST:
+               ctl17 |= SM(i->aggr_len, AR_AggrLen);
+               /* fall through */
+       case AGGR_BUF_MIDDLE:
+               ctl12 |= AR_IsAggr | AR_MoreAggr;
+               ctl17 |= SM(i->ndelim, AR_PadDelim);
+               break;
+       case AGGR_BUF_LAST:
+               ctl12 |= AR_IsAggr;
+               break;
+       case AGGR_BUF_NONE:
+               break;
+       }
+
+       val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S;
+       ctl12 |= SM(val, AR_PAPRDChainMask);
+
+       ACCESS_ONCE(ads->ctl12) = ctl12;
+       ACCESS_ONCE(ads->ctl17) = ctl17;
+
+       ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0)
+               | set11nPktDurRTSCTS(i->rates, 1);
+
+       ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2)
+               | set11nPktDurRTSCTS(i->rates, 3);
+
+       ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0)
+               | set11nRateFlags(i->rates, 1)
+               | set11nRateFlags(i->rates, 2)
+               | set11nRateFlags(i->rates, 3)
+               | SM(i->rtscts_rate, AR_RTSCTSRate);
+
+       ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
+}
+
+static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
+{
+       int checksum;
+
+       checksum = ads->info + ads->link
+               + ads->data0 + ads->ctl3
+               + ads->data1 + ads->ctl5
+               + ads->data2 + ads->ctl7
+               + ads->data3 + ads->ctl9;
+
+       return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum;
+}
+
+static void ar9003_hw_set_desc_link(void *ds, u32 ds_link)
+{
+       struct ar9003_txc *ads = ds;
+
+       ads->link = ds_link;
+       ads->ctl10 &= ~AR_TxPtrChkSum;
+       ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
+}
+
+static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
+{
+       u32 isr = 0;
+       u32 mask2 = 0;
+       struct ath9k_hw_capabilities *pCap = &ah->caps;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 sync_cause = 0, async_cause, async_mask = AR_INTR_MAC_IRQ;
+
+       if (ath9k_hw_mci_is_enabled(ah))
+               async_mask |= AR_INTR_ASYNC_MASK_MCI;
+
+       async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
+
+       if (async_cause & async_mask) {
+               if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
+                               == AR_RTC_STATUS_ON)
+                       isr = REG_READ(ah, AR_ISR);
+       }
+
+
+       sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
+
+       *masked = 0;
+
+       if (!isr && !sync_cause && !async_cause)
+               return false;
+
+       if (isr) {
+               if (isr & AR_ISR_BCNMISC) {
+                       u32 isr2;
+                       isr2 = REG_READ(ah, AR_ISR_S2);
+
+                       mask2 |= ((isr2 & AR_ISR_S2_TIM) >>
+                                 MAP_ISR_S2_TIM);
+                       mask2 |= ((isr2 & AR_ISR_S2_DTIM) >>
+                                 MAP_ISR_S2_DTIM);
+                       mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >>
+                                 MAP_ISR_S2_DTIMSYNC);
+                       mask2 |= ((isr2 & AR_ISR_S2_CABEND) >>
+                                 MAP_ISR_S2_CABEND);
+                       mask2 |= ((isr2 & AR_ISR_S2_GTT) <<
+                                 MAP_ISR_S2_GTT);
+                       mask2 |= ((isr2 & AR_ISR_S2_CST) <<
+                                 MAP_ISR_S2_CST);
+                       mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >>
+                                 MAP_ISR_S2_TSFOOR);
+                       mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >>
+                                 MAP_ISR_S2_BB_WATCHDOG);
+
+                       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                               REG_WRITE(ah, AR_ISR_S2, isr2);
+                               isr &= ~AR_ISR_BCNMISC;
+                       }
+               }
+
+               if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED))
+                       isr = REG_READ(ah, AR_ISR_RAC);
+
+               if (isr == 0xffffffff) {
+                       *masked = 0;
+                       return false;
+               }
+
+               *masked = isr & ATH9K_INT_COMMON;
+
+               if (ah->config.rx_intr_mitigation)
+                       if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
+                               *masked |= ATH9K_INT_RXLP;
+
+               if (ah->config.tx_intr_mitigation)
+                       if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
+                               *masked |= ATH9K_INT_TX;
+
+               if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
+                       *masked |= ATH9K_INT_RXLP;
+
+               if (isr & AR_ISR_HP_RXOK)
+                       *masked |= ATH9K_INT_RXHP;
+
+               if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
+                       *masked |= ATH9K_INT_TX;
+
+                       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                               u32 s0, s1;
+                               s0 = REG_READ(ah, AR_ISR_S0);
+                               REG_WRITE(ah, AR_ISR_S0, s0);
+                               s1 = REG_READ(ah, AR_ISR_S1);
+                               REG_WRITE(ah, AR_ISR_S1, s1);
+
+                               isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR |
+                                        AR_ISR_TXEOL);
+                       }
+               }
+
+               if (isr & AR_ISR_GENTMR) {
+                       u32 s5;
+
+                       if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
+                               s5 = REG_READ(ah, AR_ISR_S5_S);
+                       else
+                               s5 = REG_READ(ah, AR_ISR_S5);
+
+                       ah->intr_gen_timer_trigger =
+                               MS(s5, AR_ISR_S5_GENTIMER_TRIG);
+
+                       ah->intr_gen_timer_thresh =
+                               MS(s5, AR_ISR_S5_GENTIMER_THRESH);
+
+                       if (ah->intr_gen_timer_trigger)
+                               *masked |= ATH9K_INT_GENTIMER;
+
+                       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                               REG_WRITE(ah, AR_ISR_S5, s5);
+                               isr &= ~AR_ISR_GENTMR;
+                       }
+
+               }
+
+               *masked |= mask2;
+
+               if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                       REG_WRITE(ah, AR_ISR, isr);
+
+                       (void) REG_READ(ah, AR_ISR);
+               }
+
+               if (*masked & ATH9K_INT_BB_WATCHDOG)
+                       ar9003_hw_bb_watchdog_read(ah);
+       }
+
+       if (async_cause & AR_INTR_ASYNC_MASK_MCI)
+               ar9003_mci_get_isr(ah, masked);
+
+       if (sync_cause) {
+               if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
+                       REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
+                       REG_WRITE(ah, AR_RC, 0);
+                       *masked |= ATH9K_INT_FATAL;
+               }
+
+               if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
+                       ath_dbg(common, INTERRUPT,
+                               "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
+
+               REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
+               (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
+
+       }
+       return true;
+}
+
+static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
+                                struct ath_tx_status *ts)
+{
+       struct ar9003_txs *ads;
+       u32 status;
+
+       ads = &ah->ts_ring[ah->ts_tail];
+
+       status = ACCESS_ONCE(ads->status8);
+       if ((status & AR_TxDone) == 0)
+               return -EINPROGRESS;
+
+       ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+
+       if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
+           (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
+               ath_dbg(ath9k_hw_common(ah), XMIT,
+                       "Tx Descriptor error %x\n", ads->ds_info);
+               memset(ads, 0, sizeof(*ads));
+               return -EIO;
+       }
+
+       ts->ts_rateindex = MS(status, AR_FinalTxIdx);
+       ts->ts_seqnum = MS(status, AR_SeqNum);
+       ts->tid = MS(status, AR_TxTid);
+
+       ts->qid = MS(ads->ds_info, AR_TxQcuNum);
+       ts->desc_id = MS(ads->status1, AR_TxDescId);
+       ts->ts_tstamp = ads->status4;
+       ts->ts_status = 0;
+       ts->ts_flags  = 0;
+
+       if (status & AR_TxOpExceeded)
+               ts->ts_status |= ATH9K_TXERR_XTXOP;
+       status = ACCESS_ONCE(ads->status2);
+       ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
+       ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
+       ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
+       if (status & AR_TxBaStatus) {
+               ts->ts_flags |= ATH9K_TX_BA;
+               ts->ba_low = ads->status5;
+               ts->ba_high = ads->status6;
+       }
+
+       status = ACCESS_ONCE(ads->status3);
+       if (status & AR_ExcessiveRetries)
+               ts->ts_status |= ATH9K_TXERR_XRETRY;
+       if (status & AR_Filtered)
+               ts->ts_status |= ATH9K_TXERR_FILT;
+       if (status & AR_FIFOUnderrun) {
+               ts->ts_status |= ATH9K_TXERR_FIFO;
+               ath9k_btcoex_ath9k_hw_updatetxtriglevel(ah, true);
+       }
+       if (status & AR_TxTimerExpired)
+               ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+       if (status & AR_DescCfgErr)
+               ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+       if (status & AR_TxDataUnderrun) {
+               ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+               ath9k_btcoex_ath9k_hw_updatetxtriglevel(ah, true);
+       }
+       if (status & AR_TxDelimUnderrun) {
+               ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+               ath9k_btcoex_ath9k_hw_updatetxtriglevel(ah, true);
+       }
+       ts->ts_shortretry = MS(status, AR_RTSFailCnt);
+       ts->ts_longretry = MS(status, AR_DataFailCnt);
+       ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
+
+       status = ACCESS_ONCE(ads->status7);
+       ts->ts_rssi = MS(status, AR_TxRSSICombined);
+       ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
+       ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+       ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
+
+       memset(ads, 0, sizeof(*ads));
+
+       return 0;
+}
+
+void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
+{
+       struct ath_hw_ops *ops = ath9k_hw_ops(hw);
+
+       ops->rx_enable = ar9003_hw_rx_enable;
+       ops->set_desc_link = ar9003_hw_set_desc_link;
+       ops->get_isr = ar9003_hw_get_isr;
+       ops->set_txdesc = ar9003_set_txdesc;
+       ops->proc_txdesc = ar9003_hw_proc_txdesc;
+}
+
+void ath9k_btcoex_ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
+{
+       REG_WRITE(ah, AR_DATABUF_SIZE, buf_size & AR_DATABUF_SIZE_MASK);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_set_rx_bufsize);
+
+void ath9k_btcoex_ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp,
+                           enum ath9k_rx_qtype qtype)
+{
+       if (qtype == ATH9K_RX_QUEUE_HP)
+               REG_WRITE(ah, AR_HP_RXDP, rxdp);
+       else
+               REG_WRITE(ah, AR_LP_RXDP, rxdp);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_addrxbuf_edma);
+
+int ath9k_btcoex_ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
+                                void *buf_addr)
+{
+       struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr;
+       unsigned int phyerr;
+
+       if ((rxsp->status11 & AR_RxDone) == 0)
+               return -EINPROGRESS;
+
+       if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
+               return -EINVAL;
+
+       if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
+               return -EINPROGRESS;
+
+       rxs->rs_status = 0;
+       rxs->rs_flags =  0;
+
+       rxs->rs_datalen = rxsp->status2 & AR_DataLen;
+       rxs->rs_tstamp =  rxsp->status3;
+
+       /* XXX: Keycache */
+       rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
+       rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
+       rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
+       rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
+       rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
+       rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
+       rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
+
+       if (rxsp->status11 & AR_RxKeyIdxValid)
+               rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
+       else
+               rxs->rs_keyix = ATH9K_RXKEYIX_INVALID;
+
+       rxs->rs_rate = MS(rxsp->status1, AR_RxRate);
+       rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0;
+
+       rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0;
+       rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0;
+       rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7);
+       rxs->rs_flags  = (rxsp->status4 & AR_GI) ? ATH9K_RX_GI : 0;
+       rxs->rs_flags  |= (rxsp->status4 & AR_2040) ? ATH9K_RX_2040 : 0;
+
+       rxs->evm0 = rxsp->status6;
+       rxs->evm1 = rxsp->status7;
+       rxs->evm2 = rxsp->status8;
+       rxs->evm3 = rxsp->status9;
+       rxs->evm4 = (rxsp->status10 & 0xffff);
+
+       if (rxsp->status11 & AR_PreDelimCRCErr)
+               rxs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
+
+       if (rxsp->status11 & AR_PostDelimCRCErr)
+               rxs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
+
+       if (rxsp->status11 & AR_DecryptBusyErr)
+               rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
+
+       if ((rxsp->status11 & AR_RxFrameOK) == 0) {
+               /*
+                * AR_CRCErr will bet set to true if we're on the last
+                * subframe and the AR_PostDelimCRCErr is caught.
+                * In a way this also gives us a guarantee that when
+                * (!(AR_CRCErr) && (AR_PostDelimCRCErr)) we cannot
+                * possibly be reviewing the last subframe. AR_CRCErr
+                * is the CRC of the actual data.
+                */
+               if (rxsp->status11 & AR_CRCErr)
+                       rxs->rs_status |= ATH9K_RXERR_CRC;
+               else if (rxsp->status11 & AR_DecryptCRCErr)
+                       rxs->rs_status |= ATH9K_RXERR_DECRYPT;
+               else if (rxsp->status11 & AR_MichaelErr)
+                       rxs->rs_status |= ATH9K_RXERR_MIC;
+               if (rxsp->status11 & AR_PHYErr) {
+                       phyerr = MS(rxsp->status11, AR_PHYErrCode);
+                       /*
+                        * If we reach a point here where AR_PostDelimCRCErr is
+                        * true it implies we're *not* on the last subframe. In
+                        * in that case that we know already that the CRC of
+                        * the frame was OK, and MAC would send an ACK for that
+                        * subframe, even if we did get a phy error of type
+                        * ATH9K_PHYERR_OFDM_RESTART. This is only applicable
+                        * to frame that are prior to the last subframe.
+                        * The AR_PostDelimCRCErr is the CRC for the MPDU
+                        * delimiter, which contains the 4 reserved bits,
+                        * the MPDU length (12 bits), and follows the MPDU
+                        * delimiter for an A-MPDU subframe (0x4E = 'N' ASCII).
+                        */
+                       if ((phyerr == ATH9K_PHYERR_OFDM_RESTART) &&
+                           (rxsp->status11 & AR_PostDelimCRCErr)) {
+                               rxs->rs_phyerr = 0;
+                       } else {
+                               rxs->rs_status |= ATH9K_RXERR_PHY;
+                               rxs->rs_phyerr = phyerr;
+                       }
+               };
+       }
+
+       if (rxsp->status11 & AR_KeyMiss)
+               rxs->rs_status |= ATH9K_RXERR_KEYMISS;
+
+       return 0;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_process_rxdesc_edma);
+
+void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah)
+{
+       ah->ts_tail = 0;
+
+       memset((void *) ah->ts_ring, 0,
+               ah->ts_size * sizeof(struct ar9003_txs));
+
+       ath_dbg(ath9k_hw_common(ah), XMIT,
+               "TS Start 0x%x End 0x%x Virt %p, Size %d\n",
+               ah->ts_paddr_start, ah->ts_paddr_end,
+               ah->ts_ring, ah->ts_size);
+
+       REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start);
+       REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end);
+}
+
+void ath9k_btcoex_ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start,
+                              u32 ts_paddr_start,
+                              u16 size)
+{
+
+       ah->ts_paddr_start = ts_paddr_start;
+       ah->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9003_txs));
+       ah->ts_size = size;
+       ah->ts_ring = (struct ar9003_txs *) ts_start;
+
+       ath9k_hw_reset_txstatus_ring(ah);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_setup_statusring);
+
+void ath9k_btcoex_ar9003_hw_dump_txdesc(struct ath_hw *ah)
+{
+       struct ar9003_txs *ads;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 status, i, len = 0;
+       u8 buf[1200];
+
+       memset(buf, 0, sizeof(buf));
+       ath_dbg(common, RX_STUCK, "ts_tail %d\n", ah->ts_tail);
+
+       for (i = 0; i < ah->ts_size; i++) {
+               ads = &ah->ts_ring[i];
+               status = ACCESS_ONCE(ads->status8);
+               len += sprintf(buf + len, "%d ", status & AR_TxDone);
+       }
+       ath_dbg(common, RX_STUCK, "ring status: %s\n", buf);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_hw_dump_txdesc);
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_mac.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_mac.h
new file mode 100644 (file)
index 0000000..33a0dc5
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef AR9003_MAC_H
+#define AR9003_MAC_H
+
+#define AR_DescId      0xffff0000
+#define AR_DescId_S    16
+#define AR_CtrlStat    0x00004000
+#define AR_CtrlStat_S  14
+#define AR_TxRxDesc    0x00008000
+#define AR_TxRxDesc_S  15
+#define AR_TxQcuNum    0x00000f00
+#define AR_TxQcuNum_S  8
+
+#define AR_BufLen      0x0fff0000
+#define AR_BufLen_S    16
+
+#define AR_TxDescId    0xffff0000
+#define AR_TxDescId_S  16
+#define AR_TxPtrChkSum 0x0000ffff
+
+#define AR_LowRxChain  0x00004000
+
+#define AR_Not_Sounding        0x20000000
+
+/* ctl 12 */
+#define AR_PAPRDChainMask      0x00000e00
+#define AR_PAPRDChainMask_S    9
+
+#define MAP_ISR_S2_CST          6
+#define MAP_ISR_S2_GTT          6
+#define MAP_ISR_S2_TIM          3
+#define MAP_ISR_S2_CABEND       0
+#define MAP_ISR_S2_DTIMSYNC     7
+#define MAP_ISR_S2_DTIM         7
+#define MAP_ISR_S2_TSFOOR       4
+#define MAP_ISR_S2_BB_WATCHDOG  6
+
+#define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds)
+
+struct ar9003_rxs {
+       u32 ds_info;
+       u32 status1;
+       u32 status2;
+       u32 status3;
+       u32 status4;
+       u32 status5;
+       u32 status6;
+       u32 status7;
+       u32 status8;
+       u32 status9;
+       u32 status10;
+       u32 status11;
+} __packed __aligned(4);
+
+/* Transmit Control Descriptor */
+struct ar9003_txc {
+       u32 info;   /* descriptor information */
+       u32 link;   /* link pointer */
+       u32 data0;  /* data pointer to 1st buffer */
+       u32 ctl3;   /* DMA control 3  */
+       u32 data1;  /* data pointer to 2nd buffer */
+       u32 ctl5;   /* DMA control 5  */
+       u32 data2;  /* data pointer to 3rd buffer */
+       u32 ctl7;   /* DMA control 7  */
+       u32 data3;  /* data pointer to 4th buffer */
+       u32 ctl9;   /* DMA control 9  */
+       u32 ctl10;  /* DMA control 10 */
+       u32 ctl11;  /* DMA control 11 */
+       u32 ctl12;  /* DMA control 12 */
+       u32 ctl13;  /* DMA control 13 */
+       u32 ctl14;  /* DMA control 14 */
+       u32 ctl15;  /* DMA control 15 */
+       u32 ctl16;  /* DMA control 16 */
+       u32 ctl17;  /* DMA control 17 */
+       u32 ctl18;  /* DMA control 18 */
+       u32 ctl19;  /* DMA control 19 */
+       u32 ctl20;  /* DMA control 20 */
+       u32 ctl21;  /* DMA control 21 */
+       u32 ctl22;  /* DMA control 22 */
+       u32 ctl23;  /* DMA control 23 */
+       u32 pad[8]; /* pad to cache line (128 bytes/32 dwords) */
+} __packed __aligned(4);
+
+struct ar9003_txs {
+       u32 ds_info;
+       u32 status1;
+       u32 status2;
+       u32 status3;
+       u32 status4;
+       u32 status5;
+       u32 status6;
+       u32 status7;
+       u32 status8;
+} __packed __aligned(4);
+
+void ar9003_hw_attach_mac_ops(struct ath_hw *hw);
+void ath9k_btcoex_ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size);
+void ath9k_btcoex_ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp,
+                           enum ath9k_rx_qtype qtype);
+
+int ath9k_btcoex_ath9k_hw_process_rxdesc_edma(struct ath_hw *ah,
+                                struct ath_rx_status *rxs,
+                                void *buf_addr);
+void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start,
+                              u32 ts_paddr_start,
+                              u16 size);
+#endif
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_mci.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_mci.c
new file mode 100644 (file)
index 0000000..8b2c034
--- /dev/null
@@ -0,0 +1,1419 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/export.h>
+#include "hw.h"
+#include "hw-ops.h"
+#include "ar9003_phy.h"
+#include "ar9003_mci.h"
+
+static void ar9003_mci_reset_req_wakeup(struct ath_hw *ah)
+{
+       REG_RMW_FIELD(ah, AR_MCI_COMMAND2,
+                     AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 1);
+       udelay(1);
+       REG_RMW_FIELD(ah, AR_MCI_COMMAND2,
+                     AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 0);
+}
+
+static int ar9003_mci_wait_for_interrupt(struct ath_hw *ah, u32 address,
+                                       u32 bit_position, int time_out)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       while (time_out) {
+               if (!(REG_READ(ah, address) & bit_position)) {
+                       udelay(10);
+                       time_out -= 10;
+
+                       if (time_out < 0)
+                               break;
+                       else
+                               continue;
+               }
+               REG_WRITE(ah, address, bit_position);
+
+               if (address != AR_MCI_INTERRUPT_RX_MSG_RAW)
+                       break;
+
+               if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)
+                       ar9003_mci_reset_req_wakeup(ah);
+
+               if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING |
+                                   AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING))
+                       REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
+                                 AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);
+
+               REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG);
+               break;
+       }
+
+       if (time_out <= 0) {
+               ath_dbg(common, MCI,
+                       "MCI Wait for Reg 0x%08x = 0x%08x timeout\n",
+                       address, bit_position);
+               ath_dbg(common, MCI,
+                       "MCI INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x\n",
+                       REG_READ(ah, AR_MCI_INTERRUPT_RAW),
+                       REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
+               time_out = 0;
+       }
+
+       return time_out;
+}
+
+static void ar9003_mci_remote_reset(struct ath_hw *ah, bool wait_done)
+{
+       u32 payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00};
+
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16,
+                               wait_done, false);
+       udelay(5);
+}
+
+static void ar9003_mci_send_lna_transfer(struct ath_hw *ah, bool wait_done)
+{
+       u32 payload = 0x00000000;
+
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1,
+                               wait_done, false);
+}
+
+static void ar9003_mci_send_req_wake(struct ath_hw *ah, bool wait_done)
+{
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_REQ_WAKE, MCI_FLAG_DISABLE_TIMESTAMP,
+                               NULL, 0, wait_done, false);
+       udelay(5);
+}
+
+static void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done)
+{
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_SYS_WAKING, MCI_FLAG_DISABLE_TIMESTAMP,
+                               NULL, 0, wait_done, false);
+}
+
+static void ar9003_mci_send_lna_take(struct ath_hw *ah, bool wait_done)
+{
+       u32 payload = 0x70000000;
+
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_LNA_TAKE, 0, &payload, 1,
+                               wait_done, false);
+}
+
+static void ar9003_mci_send_sys_sleeping(struct ath_hw *ah, bool wait_done)
+{
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_SYS_SLEEPING,
+                               MCI_FLAG_DISABLE_TIMESTAMP,
+                               NULL, 0, wait_done, false);
+}
+
+static void ar9003_mci_send_coex_version_query(struct ath_hw *ah,
+                                              bool wait_done)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 payload[4] = {0, 0, 0, 0};
+
+       if (mci->bt_version_known ||
+           (mci->bt_state == MCI_BT_SLEEP))
+               return;
+
+       MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
+                               MCI_GPM_COEX_VERSION_QUERY);
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);
+}
+
+static void ar9003_mci_send_coex_version_response(struct ath_hw *ah,
+                                                 bool wait_done)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 payload[4] = {0, 0, 0, 0};
+
+       MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
+                               MCI_GPM_COEX_VERSION_RESPONSE);
+       *(((u8 *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) =
+               mci->wlan_ver_major;
+       *(((u8 *)payload) + MCI_GPM_COEX_B_MINOR_VERSION) =
+               mci->wlan_ver_minor;
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);
+}
+
+static void ar9003_mci_send_coex_wlan_channels(struct ath_hw *ah,
+                                              bool wait_done)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 *payload = &mci->wlan_channels[0];
+
+       if (!mci->wlan_channels_update ||
+           (mci->bt_state == MCI_BT_SLEEP))
+               return;
+
+       MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
+                               MCI_GPM_COEX_WLAN_CHANNELS);
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);
+       MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff);
+}
+
+static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah,
+                                               bool wait_done, u8 query_type)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 payload[4] = {0, 0, 0, 0};
+       bool query_btinfo;
+
+       if (mci->bt_state == MCI_BT_SLEEP)
+               return;
+
+       query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO |
+                                       MCI_GPM_COEX_QUERY_BT_TOPOLOGY));
+       MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
+                               MCI_GPM_COEX_STATUS_QUERY);
+
+       *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type;
+
+       /*
+        * If bt_status_query message is  not sent successfully,
+        * then need_flush_btinfo should be set again.
+        */
+       if (!ath9k_btcoex_ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16,
+                               wait_done, true)) {
+               if (query_btinfo)
+                       mci->need_flush_btinfo = true;
+       }
+
+       if (query_btinfo)
+               mci->query_bt = false;
+}
+
+static void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt,
+                                            bool wait_done)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 payload[4] = {0, 0, 0, 0};
+
+       MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
+                               MCI_GPM_COEX_HALT_BT_GPM);
+
+       if (halt) {
+               mci->query_bt = true;
+               /* Send next unhalt no matter halt sent or not */
+               mci->unhalt_bt_gpm = true;
+               mci->need_flush_btinfo = true;
+               *(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) =
+                       MCI_GPM_COEX_BT_GPM_HALT;
+       } else
+               *(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) =
+                       MCI_GPM_COEX_BT_GPM_UNHALT;
+
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);
+}
+
+static void ar9003_mci_prep_interface(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 saved_mci_int_en;
+       u32 mci_timeout = 150;
+
+       mci->bt_state = MCI_BT_SLEEP;
+       saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN);
+
+       REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
+                 REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
+                 REG_READ(ah, AR_MCI_INTERRUPT_RAW));
+
+       ar9003_mci_remote_reset(ah, true);
+       ar9003_mci_send_req_wake(ah, true);
+
+       if (!ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
+                                 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500))
+               goto clear_redunt;
+
+       mci->bt_state = MCI_BT_AWAKE;
+
+       /*
+        * we don't need to send more remote_reset at this moment.
+        * If BT receive first remote_reset, then BT HW will
+        * be cleaned up and will be able to receive req_wake
+        * and BT HW will respond sys_waking.
+        * In this case, WLAN will receive BT's HW sys_waking.
+        * Otherwise, if BT SW missed initial remote_reset,
+        * that remote_reset will still clean up BT MCI RX,
+        * and the req_wake will wake BT up,
+        * and BT SW will respond this req_wake with a remote_reset and
+        * sys_waking. In this case, WLAN will receive BT's SW
+        * sys_waking. In either case, BT's RX is cleaned up. So we
+        * don't need to reply BT's remote_reset now, if any.
+        * Similarly, if in any case, WLAN can receive BT's sys_waking,
+        * that means WLAN's RX is also fine.
+        */
+       ar9003_mci_send_sys_waking(ah, true);
+       udelay(10);
+
+       /*
+        * Set BT priority interrupt value to be 0xff to
+        * avoid having too many BT PRIORITY interrupts.
+        */
+       REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF);
+       REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF);
+       REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF);
+       REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF);
+       REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF);
+
+       /*
+        * A contention reset will be received after send out
+        * sys_waking. Also BT priority interrupt bits will be set.
+        * Clear those bits before the next step.
+        */
+
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
+                 AR_MCI_INTERRUPT_RX_MSG_CONT_RST);
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI);
+
+       if (mci->is_2g) {
+               ar9003_mci_send_lna_transfer(ah, true);
+               udelay(5);
+       }
+
+       if ((mci->is_2g && !mci->update_2g5g)) {
+               if (ar9003_mci_wait_for_interrupt(ah,
+                                       AR_MCI_INTERRUPT_RX_MSG_RAW,
+                                       AR_MCI_INTERRUPT_RX_MSG_LNA_INFO,
+                                       mci_timeout))
+                       ath_dbg(common, MCI,
+                               "MCI WLAN has control over the LNA & BT obeys it\n");
+               else
+                       ath_dbg(common, MCI,
+                               "MCI BT didn't respond to LNA_TRANS\n");
+       }
+
+clear_redunt:
+       /* Clear the extra redundant SYS_WAKING from BT */
+       if ((mci->bt_state == MCI_BT_AWAKE) &&
+           (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
+                           AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) &&
+           (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
+                           AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) {
+               REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
+                         AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING);
+               REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
+                         AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);
+       }
+
+       REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
+}
+
+void ar9003_mci_set_full_sleep(struct ath_hw *ah)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+       if (ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_ENABLE) &&
+           (mci->bt_state != MCI_BT_SLEEP) &&
+           !mci->halted_bt_gpm) {
+               ar9003_mci_send_coex_halt_bt_gpm(ah, true, true);
+       }
+
+       mci->ready = false;
+}
+
+static void ar9003_mci_disable_interrupt(struct ath_hw *ah)
+{
+       REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
+}
+
+static void ar9003_mci_enable_interrupt(struct ath_hw *ah)
+{
+       REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT);
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
+                 AR_MCI_INTERRUPT_RX_MSG_DEFAULT);
+}
+
+static bool ar9003_mci_check_int(struct ath_hw *ah, u32 ints)
+{
+       u32 intr;
+
+       intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
+       return ((intr & ints) == ints);
+}
+
+void ath9k_btcoex_ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
+                             u32 *rx_msg_intr)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+       *raw_intr = mci->raw_intr;
+       *rx_msg_intr = mci->rx_msg_intr;
+
+       /* Clean int bits after the values are read. */
+       mci->raw_intr = 0;
+       mci->rx_msg_intr = 0;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_mci_get_interrupt);
+
+void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 raw_intr, rx_msg_intr;
+
+       rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
+       raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW);
+
+       if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef)) {
+               ath_dbg(common, MCI,
+                       "MCI gets 0xdeadbeef during int processing\n");
+       } else {
+               mci->rx_msg_intr |= rx_msg_intr;
+               mci->raw_intr |= raw_intr;
+               *masked |= ATH9K_INT_MCI;
+
+               if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO)
+                       mci->cont_status = REG_READ(ah, AR_MCI_CONT_STATUS);
+
+               REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr);
+               REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr);
+       }
+}
+
+static void ar9003_mci_2g5g_changed(struct ath_hw *ah, bool is_2g)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+       if (!mci->update_2g5g &&
+           (mci->is_2g != is_2g))
+               mci->update_2g5g = true;
+
+       mci->is_2g = is_2g;
+}
+
+static bool ar9003_mci_is_gpm_valid(struct ath_hw *ah, u32 msg_index)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 *payload;
+       u32 recv_type, offset;
+
+       if (msg_index == MCI_GPM_INVALID)
+               return false;
+
+       offset = msg_index << 4;
+
+       payload = (u32 *)(mci->gpm_buf + offset);
+       recv_type = MCI_GPM_TYPE(payload);
+
+       if (recv_type == MCI_GPM_RSVD_PATTERN)
+               return false;
+
+       return true;
+}
+
+static void ar9003_mci_observation_set_up(struct ath_hw *ah)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+       if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MCI) {
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA);
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK);
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
+       } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) {
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX);
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX);
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 5, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+       } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) {
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
+       } else
+               return;
+
+       REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
+
+       REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_GLB_DS_JTAG_DISABLE, 1);
+       REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_GLB_WLAN_UART_INTF_EN, 0);
+       REG_SET_BIT(ah, AR_GLB_GPIO_CONTROL, ATH_MCI_CONFIG_MCI_OBS_GPIO);
+
+       REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0);
+       REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1);
+       REG_WRITE(ah, AR_OBS, 0x4b);
+       REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03);
+       REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01);
+       REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02);
+       REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03);
+       REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS,
+                     AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07);
+}
+
+static bool ar9003_mci_send_coex_bt_flags(struct ath_hw *ah, bool wait_done,
+                                         u8 opcode, u32 bt_flags)
+{
+       u32 pld[4] = {0, 0, 0, 0};
+
+       MCI_GPM_SET_TYPE_OPCODE(pld, MCI_GPM_COEX_AGENT,
+                               MCI_GPM_COEX_BT_UPDATE_FLAGS);
+
+       *(((u8 *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP)  = opcode;
+       *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF;
+       *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) = (bt_flags >> 8) & 0xFF;
+       *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) = (bt_flags >> 16) & 0xFF;
+       *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) = (bt_flags >> 24) & 0xFF;
+
+       return ath9k_btcoex_ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16,
+                                      wait_done, true);
+}
+
+static void ar9003_mci_sync_bt_state(struct ath_hw *ah)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 cur_bt_state;
+
+       cur_bt_state = ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP);
+
+       if (mci->bt_state != cur_bt_state)
+               mci->bt_state = cur_bt_state;
+
+       if (mci->bt_state != MCI_BT_SLEEP) {
+
+               ar9003_mci_send_coex_version_query(ah, true);
+               ar9003_mci_send_coex_wlan_channels(ah, true);
+
+               if (mci->unhalt_bt_gpm == true)
+                       ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);
+       }
+}
+
+void ar9003_mci_check_bt(struct ath_hw *ah)
+{
+       struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
+
+       if (!mci_hw->ready)
+               return;
+
+       /*
+        * check BT state again to make
+        * sure it's not changed.
+        */
+       ar9003_mci_sync_bt_state(ah);
+       ar9003_mci_2g5g_switch(ah, true);
+
+       if ((mci_hw->bt_state == MCI_BT_AWAKE) &&
+           (mci_hw->query_bt == true)) {
+               mci_hw->need_flush_btinfo = true;
+       }
+}
+
+static void ar9003_mci_process_gpm_extra(struct ath_hw *ah, u8 gpm_type,
+                                        u8 gpm_opcode, u32 *p_gpm)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u8 *p_data = (u8 *) p_gpm;
+
+       if (gpm_type != MCI_GPM_COEX_AGENT)
+               return;
+
+       switch (gpm_opcode) {
+       case MCI_GPM_COEX_VERSION_QUERY:
+               ath_dbg(common, MCI, "MCI Recv GPM COEX Version Query\n");
+               ar9003_mci_send_coex_version_response(ah, true);
+               break;
+       case MCI_GPM_COEX_VERSION_RESPONSE:
+               ath_dbg(common, MCI, "MCI Recv GPM COEX Version Response\n");
+               mci->bt_ver_major =
+                       *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION);
+               mci->bt_ver_minor =
+                       *(p_data + MCI_GPM_COEX_B_MINOR_VERSION);
+               mci->bt_version_known = true;
+               ath_dbg(common, MCI, "MCI BT Coex version: %d.%d\n",
+                       mci->bt_ver_major, mci->bt_ver_minor);
+               break;
+       case MCI_GPM_COEX_STATUS_QUERY:
+               ath_dbg(common, MCI,
+                       "MCI Recv GPM COEX Status Query = 0x%02X\n",
+                       *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP));
+               mci->wlan_channels_update = true;
+               ar9003_mci_send_coex_wlan_channels(ah, true);
+               break;
+       case MCI_GPM_COEX_BT_PROFILE_INFO:
+               mci->query_bt = true;
+               ath_dbg(common, MCI, "MCI Recv GPM COEX BT_Profile_Info\n");
+               break;
+       case MCI_GPM_COEX_BT_STATUS_UPDATE:
+               mci->query_bt = true;
+               ath_dbg(common, MCI,
+                       "MCI Recv GPM COEX BT_Status_Update SEQ=%d (drop&query)\n",
+                       *(p_gpm + 3));
+               break;
+       default:
+               break;
+       }
+}
+
+static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
+                                  u8 gpm_opcode, int time_out)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 *p_gpm = NULL, mismatch = 0, more_data;
+       u32 offset;
+       u8 recv_type = 0, recv_opcode = 0;
+       bool b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE);
+
+       more_data = time_out ? MCI_GPM_NOMORE : MCI_GPM_MORE;
+
+       while (time_out > 0) {
+               if (p_gpm) {
+                       MCI_GPM_RECYCLE(p_gpm);
+                       p_gpm = NULL;
+               }
+
+               if (more_data != MCI_GPM_MORE)
+                       time_out = ar9003_mci_wait_for_interrupt(ah,
+                                       AR_MCI_INTERRUPT_RX_MSG_RAW,
+                                       AR_MCI_INTERRUPT_RX_MSG_GPM,
+                                       time_out);
+
+               if (!time_out)
+                       break;
+
+               offset = ath9k_btcoex_ar9003_mci_get_next_gpm_offset(ah, false, &more_data);
+
+               if (offset == MCI_GPM_INVALID)
+                       continue;
+
+               p_gpm = (u32 *) (mci->gpm_buf + offset);
+               recv_type = MCI_GPM_TYPE(p_gpm);
+               recv_opcode = MCI_GPM_OPCODE(p_gpm);
+
+               if (MCI_GPM_IS_CAL_TYPE(recv_type)) {
+                       if (recv_type == gpm_type) {
+                               if ((gpm_type == MCI_GPM_BT_CAL_DONE) &&
+                                   !b_is_bt_cal_done) {
+                                       gpm_type = MCI_GPM_BT_CAL_GRANT;
+                                       continue;
+                               }
+                               break;
+                       }
+               } else if ((recv_type == gpm_type) &&
+                          (recv_opcode == gpm_opcode))
+                       break;
+
+               /*
+                * check if it's cal_grant
+                *
+                * When we're waiting for cal_grant in reset routine,
+                * it's possible that BT sends out cal_request at the
+                * same time. Since BT's calibration doesn't happen
+                * that often, we'll let BT completes calibration then
+                * we continue to wait for cal_grant from BT.
+                * Orginal: Wait BT_CAL_GRANT.
+                * New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT->wait
+                * BT_CAL_DONE -> Wait BT_CAL_GRANT.
+                */
+
+               if ((gpm_type == MCI_GPM_BT_CAL_GRANT) &&
+                   (recv_type == MCI_GPM_BT_CAL_REQ)) {
+
+                       u32 payload[4] = {0, 0, 0, 0};
+
+                       gpm_type = MCI_GPM_BT_CAL_DONE;
+                       MCI_GPM_SET_CAL_TYPE(payload,
+                                            MCI_GPM_WLAN_CAL_GRANT);
+                       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16,
+                                               false, false);
+                       continue;
+               } else {
+                       ath_dbg(common, MCI, "MCI GPM subtype not match 0x%x\n",
+                               *(p_gpm + 1));
+                       mismatch++;
+                       ar9003_mci_process_gpm_extra(ah, recv_type,
+                                                    recv_opcode, p_gpm);
+               }
+       }
+
+       if (p_gpm) {
+               MCI_GPM_RECYCLE(p_gpm);
+               p_gpm = NULL;
+       }
+
+       if (time_out <= 0)
+               time_out = 0;
+
+       while (more_data == MCI_GPM_MORE) {
+               offset = ath9k_btcoex_ar9003_mci_get_next_gpm_offset(ah, false, &more_data);
+               if (offset == MCI_GPM_INVALID)
+                       break;
+
+               p_gpm = (u32 *) (mci->gpm_buf + offset);
+               recv_type = MCI_GPM_TYPE(p_gpm);
+               recv_opcode = MCI_GPM_OPCODE(p_gpm);
+
+               if (!MCI_GPM_IS_CAL_TYPE(recv_type))
+                       ar9003_mci_process_gpm_extra(ah, recv_type,
+                                                    recv_opcode, p_gpm);
+
+               MCI_GPM_RECYCLE(p_gpm);
+       }
+
+       return time_out;
+}
+
+bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
+       u32 payload[4] = {0, 0, 0, 0};
+
+       ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan));
+
+       if (mci_hw->bt_state != MCI_BT_CAL_START)
+               return false;
+
+       mci_hw->bt_state = MCI_BT_CAL;
+
+       /*
+        * MCI FIX: disable mci interrupt here. This is to avoid
+        * SW_MSG_DONE or RX_MSG bits to trigger MCI_INT and
+        * lead to mci_intr reentry.
+        */
+       ar9003_mci_disable_interrupt(ah);
+
+       MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_GPM, 0, payload,
+                               16, true, false);
+
+       /* Wait BT calibration to be completed for 25ms */
+
+       if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE,
+                                   0, 25000))
+               ath_dbg(common, MCI, "MCI BT_CAL_DONE received\n");
+       else
+               ath_dbg(common, MCI,
+                       "MCI BT_CAL_DONE not received\n");
+
+       mci_hw->bt_state = MCI_BT_AWAKE;
+       /* MCI FIX: enable mci interrupt here */
+       ar9003_mci_enable_interrupt(ah);
+
+       return true;
+}
+
+int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+                        struct ath9k_hw_cal_data *caldata)
+{
+       struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
+
+       if (!mci_hw->ready)
+               return 0;
+
+       if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP))
+               goto exit;
+
+       if (!ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) &&
+           !ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE))
+               goto exit;
+
+       /*
+        * BT is sleeping. Check if BT wakes up during
+        * WLAN calibration. If BT wakes up during
+        * WLAN calibration, need to go through all
+        * message exchanges again and recal.
+        */
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
+                 (AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET |
+                  AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE));
+
+       ar9003_mci_remote_reset(ah, true);
+       ar9003_mci_send_sys_waking(ah, true);
+       udelay(1);
+
+       if (IS_CHAN_2GHZ(chan))
+               ar9003_mci_send_lna_transfer(ah, true);
+
+       mci_hw->bt_state = MCI_BT_AWAKE;
+
+       if (caldata) {
+               caldata->done_txiqcal_once = false;
+               caldata->done_txclcal_once = false;
+               caldata->rtt_done = false;
+       }
+
+       if (!ath9k_hw_init_cal(ah, chan))
+               return -EIO;
+
+exit:
+       ar9003_mci_enable_interrupt(ah);
+       return 0;
+}
+
+static void ar9003_mci_mute_bt(struct ath_hw *ah)
+{
+       /* disable all MCI messages */
+       REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
+       REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+
+       /* wait pending HW messages to flush out */
+       udelay(10);
+
+       /*
+        * Send LNA_TAKE and SYS_SLEEPING when
+        * 1. reset not after resuming from full sleep
+        * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment
+        */
+       ar9003_mci_send_lna_take(ah, true);
+
+       udelay(5);
+
+       ar9003_mci_send_sys_sleeping(ah, true);
+}
+
+static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 thresh;
+
+       if (!enable) {
+               REG_CLR_BIT(ah, AR_BTCOEX_CTRL,
+                           AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+               return;
+       }
+       REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1);
+       REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2,
+                     AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);
+
+       if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) {
+               thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH);
+               REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
+                             AR_BTCOEX_CTRL_AGGR_THRESH, thresh);
+               REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
+                             AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1);
+       } else
+               REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
+                             AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0);
+
+       REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
+                     AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1);
+}
+
+void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
+                     bool is_full_sleep)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 regval;
+
+       ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n",
+               is_full_sleep, is_2g);
+
+       if (!mci->gpm_addr && !mci->sched_addr) {
+               ath_dbg(common, MCI,
+                       "MCI GPM and schedule buffers are not allocated\n");
+               return;
+       }
+
+       if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) {
+               ath_dbg(common, MCI, "BTCOEX control register is dead\n");
+               return;
+       }
+
+       /* Program MCI DMA related registers */
+       REG_WRITE(ah, AR_MCI_GPM_0, mci->gpm_addr);
+       REG_WRITE(ah, AR_MCI_GPM_1, mci->gpm_len);
+       REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, mci->sched_addr);
+
+       /*
+       * To avoid MCI state machine be affected by incoming remote MCI msgs,
+       * MCI mode will be enabled later, right before reset the MCI TX and RX.
+       */
+
+       regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |
+                SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
+                SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
+                SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
+                SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+                SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
+                SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
+                SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
+                SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+
+       REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
+
+       if (is_2g && !(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
+               ar9003_mci_osla_setup(ah, true);
+       else
+               ar9003_mci_osla_setup(ah, false);
+
+       REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,
+                   AR_BTCOEX_CTRL_SPDT_ENABLE);
+       REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,
+                     AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);
+
+       REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 1);
+       REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
+
+       regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV);
+       REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);
+       REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);
+
+       /* Resetting the Rx and Tx paths of MCI */
+       regval = REG_READ(ah, AR_MCI_COMMAND2);
+       regval |= SM(1, AR_MCI_COMMAND2_RESET_TX);
+       REG_WRITE(ah, AR_MCI_COMMAND2, regval);
+
+       udelay(1);
+
+       regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX);
+       REG_WRITE(ah, AR_MCI_COMMAND2, regval);
+
+       if (is_full_sleep) {
+               ar9003_mci_mute_bt(ah);
+               udelay(100);
+       }
+
+       /* Check pending GPM msg before MCI Reset Rx */
+       ar9003_mci_check_gpm_offset(ah);
+
+       regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);
+       REG_WRITE(ah, AR_MCI_COMMAND2, regval);
+       udelay(1);
+       regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX);
+       REG_WRITE(ah, AR_MCI_COMMAND2, regval);
+
+       ath9k_btcoex_ar9003_mci_get_next_gpm_offset(ah, true, NULL);
+
+       REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
+                 (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
+                  SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM)));
+
+       REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
+                   AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+
+       ar9003_mci_observation_set_up(ah);
+
+       mci->ready = true;
+       ar9003_mci_prep_interface(ah);
+
+       if (en_int)
+               ar9003_mci_enable_interrupt(ah);
+}
+
+void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep)
+{
+       struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
+
+       ar9003_mci_disable_interrupt(ah);
+
+       if (mci_hw->ready && !save_fullsleep) {
+               ar9003_mci_mute_bt(ah);
+               udelay(20);
+               REG_WRITE(ah, AR_BTCOEX_CTRL, 0);
+       }
+
+       mci_hw->bt_state = MCI_BT_SLEEP;
+       mci_hw->ready = false;
+}
+
+static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 new_flags, to_set, to_clear;
+
+       if (!mci->update_2g5g || (mci->bt_state == MCI_BT_SLEEP))
+               return;
+
+       if (mci->is_2g) {
+               new_flags = MCI_2G_FLAGS;
+               to_clear = MCI_2G_FLAGS_CLEAR_MASK;
+               to_set = MCI_2G_FLAGS_SET_MASK;
+       } else {
+               new_flags = MCI_5G_FLAGS;
+               to_clear = MCI_5G_FLAGS_CLEAR_MASK;
+               to_set = MCI_5G_FLAGS_SET_MASK;
+       }
+
+       if (to_clear)
+               ar9003_mci_send_coex_bt_flags(ah, wait_done,
+                                             MCI_GPM_COEX_BT_FLAGS_CLEAR,
+                                             to_clear);
+       if (to_set)
+               ar9003_mci_send_coex_bt_flags(ah, wait_done,
+                                             MCI_GPM_COEX_BT_FLAGS_SET,
+                                             to_set);
+}
+
+static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,
+                                       u32 *payload, bool queue)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u8 type, opcode;
+
+       /* check if the message is to be queued */
+       if (header != MCI_GPM)
+               return;
+
+       type = MCI_GPM_TYPE(payload);
+       opcode = MCI_GPM_OPCODE(payload);
+
+       if (type != MCI_GPM_COEX_AGENT)
+               return;
+
+       switch (opcode) {
+       case MCI_GPM_COEX_BT_UPDATE_FLAGS:
+               if (*(((u8 *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) ==
+                   MCI_GPM_COEX_BT_FLAGS_READ)
+                       break;
+
+               mci->update_2g5g = queue;
+
+               break;
+       case MCI_GPM_COEX_WLAN_CHANNELS:
+               mci->wlan_channels_update = queue;
+               break;
+       case MCI_GPM_COEX_HALT_BT_GPM:
+               if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
+                   MCI_GPM_COEX_BT_GPM_UNHALT) {
+                       mci->unhalt_bt_gpm = queue;
+
+                       if (!queue)
+                               mci->halted_bt_gpm = false;
+               }
+
+               if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
+                               MCI_GPM_COEX_BT_GPM_HALT) {
+
+                       mci->halted_bt_gpm = !queue;
+               }
+
+               break;
+       default:
+               break;
+       }
+}
+
+void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+       if (!mci->update_2g5g && !force)
+               return;
+
+       if (mci->is_2g) {
+               ar9003_mci_send_2g5g_status(ah, true);
+               ar9003_mci_send_lna_transfer(ah, true);
+               udelay(5);
+
+               REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
+                           AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+               REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL,
+                           AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
+
+               if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
+                       ar9003_mci_osla_setup(ah, true);
+       } else {
+               ar9003_mci_send_lna_take(ah, true);
+               udelay(5);
+
+               REG_SET_BIT(ah, AR_MCI_TX_CTRL,
+                           AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+               REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,
+                           AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
+
+               ar9003_mci_osla_setup(ah, false);
+               ar9003_mci_send_2g5g_status(ah, true);
+       }
+}
+
+bool ath9k_btcoex_ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag,
+                            u32 *payload, u8 len, bool wait_done,
+                            bool check_bt)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       bool msg_sent = false;
+       u32 regval;
+       u32 saved_mci_int_en;
+       int i;
+
+       saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN);
+       regval = REG_READ(ah, AR_BTCOEX_CTRL);
+
+       if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) {
+               ath_dbg(common, MCI,
+                       "MCI Not sending 0x%x. MCI is not enabled. full_sleep = %d\n",
+                       header, (ah->power_mode == ATH9K_PM_FULL_SLEEP) ? 1 : 0);
+               ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
+               return false;
+       } else if (check_bt && (mci->bt_state == MCI_BT_SLEEP)) {
+               ath_dbg(common, MCI,
+                       "MCI Don't send message 0x%x. BT is in sleep state\n",
+                       header);
+               ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
+               return false;
+       }
+
+       if (wait_done)
+               REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
+
+       /* Need to clear SW_MSG_DONE raw bit before wait */
+
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
+                 (AR_MCI_INTERRUPT_SW_MSG_DONE |
+                  AR_MCI_INTERRUPT_MSG_FAIL_MASK));
+
+       if (payload) {
+               for (i = 0; (i * 4) < len; i++)
+                       REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i * 4),
+                                 *(payload + i));
+       }
+
+       REG_WRITE(ah, AR_MCI_COMMAND0,
+                 (SM((flag & MCI_FLAG_DISABLE_TIMESTAMP),
+                     AR_MCI_COMMAND0_DISABLE_TIMESTAMP) |
+                  SM(len, AR_MCI_COMMAND0_LEN) |
+                  SM(header, AR_MCI_COMMAND0_HEADER)));
+
+       if (wait_done &&
+           !(ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW,
+                                           AR_MCI_INTERRUPT_SW_MSG_DONE, 500)))
+               ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
+       else {
+               ar9003_mci_queue_unsent_gpm(ah, header, payload, false);
+               msg_sent = true;
+       }
+
+       if (wait_done)
+               REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
+
+       return msg_sent;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_mci_send_message);
+
+void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
+       u32 pld[4] = {0, 0, 0, 0};
+
+       if ((mci_hw->bt_state != MCI_BT_AWAKE) ||
+           (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL))
+               return;
+
+       MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_REQ);
+       pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_seq++;
+
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false);
+
+       if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) {
+               ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n");
+       } else {
+               *is_reusable = false;
+               ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n");
+       }
+}
+
+void ar9003_mci_init_cal_done(struct ath_hw *ah)
+{
+       struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
+       u32 pld[4] = {0, 0, 0, 0};
+
+       if ((mci_hw->bt_state != MCI_BT_AWAKE) ||
+           (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL))
+               return;
+
+       MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_DONE);
+       pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_done++;
+       ath9k_btcoex_ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false);
+}
+
+void ath9k_btcoex_ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
+                     u16 len, u32 sched_addr)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+       mci->gpm_addr = gpm_addr;
+       mci->gpm_buf = gpm_buf;
+       mci->gpm_len = len;
+       mci->sched_addr = sched_addr;
+
+       ar9003_mci_reset(ah, true, true, true);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_mci_setup);
+
+void ath9k_btcoex_ar9003_mci_cleanup(struct ath_hw *ah)
+{
+       /* Turn off MCI and Jupiter mode. */
+       REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00);
+       ar9003_mci_disable_interrupt(ah);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_mci_cleanup);
+
+u32 ath9k_btcoex_ar9003_mci_state(struct ath_hw *ah, u32 state_type)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 value = 0;
+       u8 query_type;
+
+       switch (state_type) {
+       case MCI_STATE_ENABLE:
+               if (mci->ready) {
+                       value = REG_READ(ah, AR_BTCOEX_CTRL);
+
+                       if ((value == 0xdeadbeef) || (value == 0xffffffff))
+                               value = 0;
+               }
+               value &= AR_BTCOEX_CTRL_MCI_MODE_EN;
+               break;
+       case MCI_STATE_LAST_SCHD_MSG_OFFSET:
+               value = MS(REG_READ(ah, AR_MCI_RX_STATUS),
+                                   AR_MCI_RX_LAST_SCHD_MSG_INDEX);
+               /* Make it in bytes */
+               value <<= 4;
+               break;
+       case MCI_STATE_REMOTE_SLEEP:
+               value = MS(REG_READ(ah, AR_MCI_RX_STATUS),
+                          AR_MCI_RX_REMOTE_SLEEP) ?
+                       MCI_BT_SLEEP : MCI_BT_AWAKE;
+               break;
+       case MCI_STATE_SET_BT_AWAKE:
+               mci->bt_state = MCI_BT_AWAKE;
+               ar9003_mci_send_coex_version_query(ah, true);
+               ar9003_mci_send_coex_wlan_channels(ah, true);
+
+               if (mci->unhalt_bt_gpm)
+                       ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);
+
+               ar9003_mci_2g5g_switch(ah, false);
+               break;
+       case MCI_STATE_SET_BT_CAL_START:
+               mci->bt_state = MCI_BT_CAL_START;
+               break;
+       case MCI_STATE_SET_BT_CAL:
+               mci->bt_state = MCI_BT_CAL;
+               break;
+       case MCI_STATE_RESET_REQ_WAKE:
+               ar9003_mci_reset_req_wakeup(ah);
+               mci->update_2g5g = true;
+
+               if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MASK) {
+                       /* Check if we still have control of the GPIOs */
+                       if ((REG_READ(ah, AR_GLB_GPIO_CONTROL) &
+                            ATH_MCI_CONFIG_MCI_OBS_GPIO) !=
+                           ATH_MCI_CONFIG_MCI_OBS_GPIO) {
+                               ar9003_mci_observation_set_up(ah);
+                       }
+               }
+               break;
+       case MCI_STATE_SEND_WLAN_COEX_VERSION:
+               ar9003_mci_send_coex_version_response(ah, true);
+               break;
+       case MCI_STATE_SEND_VERSION_QUERY:
+               ar9003_mci_send_coex_version_query(ah, true);
+               break;
+       case MCI_STATE_SEND_STATUS_QUERY:
+               query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY;
+               ar9003_mci_send_coex_bt_status_query(ah, true, query_type);
+               break;
+       case MCI_STATE_RECOVER_RX:
+               ar9003_mci_prep_interface(ah);
+               mci->query_bt = true;
+               mci->need_flush_btinfo = true;
+               ar9003_mci_send_coex_wlan_channels(ah, true);
+               ar9003_mci_2g5g_switch(ah, false);
+               break;
+       case MCI_STATE_NEED_FTP_STOMP:
+               value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP);
+               break;
+       default:
+               break;
+       }
+
+       return value;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_mci_state);
+
+void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+       ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n");
+
+       ar9003_mci_send_lna_take(ah, true);
+       udelay(50);
+
+       REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
+       mci->is_2g = false;
+       mci->update_2g5g = true;
+       ar9003_mci_send_2g5g_status(ah, true);
+
+       /* Force another 2g5g update at next scanning */
+       mci->update_2g5g = true;
+}
+
+void ar9003_mci_set_power_awake(struct ath_hw *ah)
+{
+       u32 btcoex_ctrl2, diag_sw;
+       int i;
+       u8 lna_ctrl, bt_sleep;
+
+       for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
+               btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2);
+               if (btcoex_ctrl2 != 0xdeadbeef)
+                       break;
+               udelay(AH_TIME_QUANTUM);
+       }
+       REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23)));
+
+       for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
+               diag_sw = REG_READ(ah, AR_DIAG_SW);
+               if (diag_sw != 0xdeadbeef)
+                       break;
+               udelay(AH_TIME_QUANTUM);
+       }
+       REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18)));
+       lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3;
+       bt_sleep = REG_READ(ah, AR_MCI_RX_STATUS) & AR_MCI_RX_REMOTE_SLEEP;
+
+       REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2);
+       REG_WRITE(ah, AR_DIAG_SW, diag_sw);
+
+       if (bt_sleep && (lna_ctrl == 2)) {
+               REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1);
+               REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1);
+               udelay(50);
+       }
+}
+
+void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 offset;
+
+       /*
+        * This should only be called before "MAC Warm Reset" or "MCI Reset Rx".
+        */
+       offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
+       if (mci->gpm_idx == offset)
+               return;
+       ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n",
+               mci->gpm_idx, offset);
+       mci->query_bt = true;
+       mci->need_flush_btinfo = true;
+       mci->gpm_idx = 0;
+}
+
+u32 ath9k_btcoex_ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 offset, more_gpm = 0, gpm_ptr;
+
+       if (first) {
+               gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
+               mci->gpm_idx = gpm_ptr;
+               return gpm_ptr;
+       }
+
+       /*
+        * This could be useful to avoid new GPM message interrupt which
+        * may lead to spurious interrupt after power sleep, or multiple
+        * entry of ath_mci_intr().
+        * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
+        * alleviate this effect, but clearing GPM RX interrupt bit is
+        * safe, because whether this is called from hw or driver code
+        * there must be an interrupt bit set/triggered initially
+        */
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
+                       AR_MCI_INTERRUPT_RX_MSG_GPM);
+
+       gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
+       offset = gpm_ptr;
+
+       if (!offset)
+               offset = mci->gpm_len - 1;
+       else if (offset >= mci->gpm_len) {
+               if (offset != 0xFFFF)
+                       offset = 0;
+       } else {
+               offset--;
+       }
+
+       if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) {
+               offset = MCI_GPM_INVALID;
+               more_gpm = MCI_GPM_NOMORE;
+               goto out;
+       }
+       for (;;) {
+               u32 temp_index;
+
+               /* skip reserved GPM if any */
+
+               if (offset != mci->gpm_idx)
+                       more_gpm = MCI_GPM_MORE;
+               else
+                       more_gpm = MCI_GPM_NOMORE;
+
+               temp_index = mci->gpm_idx;
+               mci->gpm_idx++;
+
+               if (mci->gpm_idx >= mci->gpm_len)
+                       mci->gpm_idx = 0;
+
+               if (ar9003_mci_is_gpm_valid(ah, temp_index)) {
+                       offset = temp_index;
+                       break;
+               }
+
+               if (more_gpm == MCI_GPM_NOMORE) {
+                       offset = MCI_GPM_INVALID;
+                       break;
+               }
+       }
+
+       if (offset != MCI_GPM_INVALID)
+               offset <<= 4;
+out:
+       if (more)
+               *more = more_gpm;
+
+       return offset;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_mci_get_next_gpm_offset);
+
+void ath9k_btcoex_ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+       mci->bt_ver_major = major;
+       mci->bt_ver_minor = minor;
+       mci->bt_version_known = true;
+       ath_dbg(ath9k_hw_common(ah), MCI, "MCI BT version set: %d.%d\n",
+               mci->bt_ver_major, mci->bt_ver_minor);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_mci_set_bt_version);
+
+void ath9k_btcoex_ar9003_mci_send_wlan_channels(struct ath_hw *ah)
+{
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+       mci->wlan_channels_update = true;
+       ar9003_mci_send_coex_wlan_channels(ah, true);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_mci_send_wlan_channels);
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_mci.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_mci.h
new file mode 100644 (file)
index 0000000..2376575
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef AR9003_MCI_H
+#define AR9003_MCI_H
+
+#define MCI_FLAG_DISABLE_TIMESTAMP      0x00000001      /* Disable time stamp */
+
+/* Default remote BT device MCI COEX version */
+#define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT  3
+#define MCI_GPM_COEX_MINOR_VERSION_DEFAULT  0
+
+/* Local WLAN MCI COEX version */
+#define MCI_GPM_COEX_MAJOR_VERSION_WLAN     3
+#define MCI_GPM_COEX_MINOR_VERSION_WLAN     0
+
+enum mci_gpm_coex_query_type {
+       MCI_GPM_COEX_QUERY_BT_ALL_INFO      = BIT(0),
+       MCI_GPM_COEX_QUERY_BT_TOPOLOGY      = BIT(1),
+       MCI_GPM_COEX_QUERY_BT_DEBUG         = BIT(2),
+};
+
+enum mci_gpm_coex_halt_bt_gpm {
+       MCI_GPM_COEX_BT_GPM_UNHALT,
+       MCI_GPM_COEX_BT_GPM_HALT
+};
+
+enum mci_gpm_coex_bt_update_flags_op {
+       MCI_GPM_COEX_BT_FLAGS_READ,
+       MCI_GPM_COEX_BT_FLAGS_SET,
+       MCI_GPM_COEX_BT_FLAGS_CLEAR
+};
+
+#define MCI_NUM_BT_CHANNELS     79
+
+#define MCI_BT_MCI_FLAGS_UPDATE_CORR          0x00000002
+#define MCI_BT_MCI_FLAGS_UPDATE_HDR           0x00000004
+#define MCI_BT_MCI_FLAGS_UPDATE_PLD           0x00000008
+#define MCI_BT_MCI_FLAGS_LNA_CTRL             0x00000010
+#define MCI_BT_MCI_FLAGS_DEBUG                0x00000020
+#define MCI_BT_MCI_FLAGS_SCHED_MSG            0x00000040
+#define MCI_BT_MCI_FLAGS_CONT_MSG             0x00000080
+#define MCI_BT_MCI_FLAGS_COEX_GPM             0x00000100
+#define MCI_BT_MCI_FLAGS_CPU_INT_MSG          0x00000200
+#define MCI_BT_MCI_FLAGS_MCI_MODE             0x00000400
+#define MCI_BT_MCI_FLAGS_AR9462_MODE          0x00001000
+#define MCI_BT_MCI_FLAGS_OTHER                0x00010000
+
+#define MCI_DEFAULT_BT_MCI_FLAGS              0x00011dde
+
+#define MCI_TOGGLE_BT_MCI_FLAGS  (MCI_BT_MCI_FLAGS_UPDATE_CORR | \
+                                 MCI_BT_MCI_FLAGS_UPDATE_HDR  | \
+                                 MCI_BT_MCI_FLAGS_UPDATE_PLD  | \
+                                 MCI_BT_MCI_FLAGS_MCI_MODE)
+
+#define MCI_2G_FLAGS_CLEAR_MASK   0x00000000
+#define MCI_2G_FLAGS_SET_MASK     MCI_TOGGLE_BT_MCI_FLAGS
+#define MCI_2G_FLAGS              MCI_DEFAULT_BT_MCI_FLAGS
+
+#define MCI_5G_FLAGS_CLEAR_MASK   MCI_TOGGLE_BT_MCI_FLAGS
+#define MCI_5G_FLAGS_SET_MASK     0x00000000
+#define MCI_5G_FLAGS              (MCI_DEFAULT_BT_MCI_FLAGS & \
+                                  ~MCI_TOGGLE_BT_MCI_FLAGS)
+
+/*
+ * Default value for AR9462 is 0x00002201
+ */
+#define ATH_MCI_CONFIG_CONCUR_TX            0x00000003
+#define ATH_MCI_CONFIG_MCI_OBS_MCI          0x00000004
+#define ATH_MCI_CONFIG_MCI_OBS_TXRX         0x00000008
+#define ATH_MCI_CONFIG_MCI_OBS_BT           0x00000010
+#define ATH_MCI_CONFIG_DISABLE_MCI_CAL      0x00000020
+#define ATH_MCI_CONFIG_DISABLE_OSLA         0x00000040
+#define ATH_MCI_CONFIG_DISABLE_FTP_STOMP    0x00000080
+#define ATH_MCI_CONFIG_AGGR_THRESH          0x00000700
+#define ATH_MCI_CONFIG_AGGR_THRESH_S        8
+#define ATH_MCI_CONFIG_DISABLE_AGGR_THRESH  0x00000800
+#define ATH_MCI_CONFIG_CLK_DIV              0x00003000
+#define ATH_MCI_CONFIG_CLK_DIV_S            12
+#define ATH_MCI_CONFIG_DISABLE_TUNING       0x00004000
+#define ATH_MCI_CONFIG_MCI_WEIGHT_DBG       0x40000000
+#define ATH_MCI_CONFIG_DISABLE_MCI          0x80000000
+
+#define ATH_MCI_CONFIG_MCI_OBS_MASK     (ATH_MCI_CONFIG_MCI_OBS_MCI  | \
+                                        ATH_MCI_CONFIG_MCI_OBS_TXRX | \
+                                        ATH_MCI_CONFIG_MCI_OBS_BT)
+#define ATH_MCI_CONFIG_MCI_OBS_GPIO     0x0000002F
+
+enum mci_message_header {              /* length of payload */
+       MCI_LNA_CTRL     = 0x10,        /* len = 0 */
+       MCI_CONT_NACK    = 0x20,        /* len = 0 */
+       MCI_CONT_INFO    = 0x30,        /* len = 4 */
+       MCI_CONT_RST     = 0x40,        /* len = 0 */
+       MCI_SCHD_INFO    = 0x50,        /* len = 16 */
+       MCI_CPU_INT      = 0x60,        /* len = 4 */
+       MCI_SYS_WAKING   = 0x70,        /* len = 0 */
+       MCI_GPM          = 0x80,        /* len = 16 */
+       MCI_LNA_INFO     = 0x90,        /* len = 1 */
+       MCI_LNA_STATE    = 0x94,
+       MCI_LNA_TAKE     = 0x98,
+       MCI_LNA_TRANS    = 0x9c,
+       MCI_SYS_SLEEPING = 0xa0,        /* len = 0 */
+       MCI_REQ_WAKE     = 0xc0,        /* len = 0 */
+       MCI_DEBUG_16     = 0xfe,        /* len = 2 */
+       MCI_REMOTE_RESET = 0xff         /* len = 16 */
+};
+
+enum ath_mci_gpm_coex_profile_type {
+       MCI_GPM_COEX_PROFILE_UNKNOWN,
+       MCI_GPM_COEX_PROFILE_RFCOMM,
+       MCI_GPM_COEX_PROFILE_A2DP,
+       MCI_GPM_COEX_PROFILE_HID,
+       MCI_GPM_COEX_PROFILE_BNEP,
+       MCI_GPM_COEX_PROFILE_VOICE,
+       MCI_GPM_COEX_PROFILE_MAX
+};
+
+/* MCI GPM/Coex opcode/type definitions */
+enum {
+       MCI_GPM_COEX_W_GPM_PAYLOAD      = 1,
+       MCI_GPM_COEX_B_GPM_TYPE         = 4,
+       MCI_GPM_COEX_B_GPM_OPCODE       = 5,
+       /* MCI_GPM_WLAN_CAL_REQ, MCI_GPM_WLAN_CAL_DONE */
+       MCI_GPM_WLAN_CAL_W_SEQUENCE     = 2,
+
+       /* MCI_GPM_COEX_VERSION_QUERY */
+       /* MCI_GPM_COEX_VERSION_RESPONSE */
+       MCI_GPM_COEX_B_MAJOR_VERSION    = 6,
+       MCI_GPM_COEX_B_MINOR_VERSION    = 7,
+       /* MCI_GPM_COEX_STATUS_QUERY */
+       MCI_GPM_COEX_B_BT_BITMAP        = 6,
+       MCI_GPM_COEX_B_WLAN_BITMAP      = 7,
+       /* MCI_GPM_COEX_HALT_BT_GPM */
+       MCI_GPM_COEX_B_HALT_STATE       = 6,
+       /* MCI_GPM_COEX_WLAN_CHANNELS */
+       MCI_GPM_COEX_B_CHANNEL_MAP      = 6,
+       /* MCI_GPM_COEX_BT_PROFILE_INFO */
+       MCI_GPM_COEX_B_PROFILE_TYPE     = 6,
+       MCI_GPM_COEX_B_PROFILE_LINKID   = 7,
+       MCI_GPM_COEX_B_PROFILE_STATE    = 8,
+       MCI_GPM_COEX_B_PROFILE_ROLE     = 9,
+       MCI_GPM_COEX_B_PROFILE_RATE     = 10,
+       MCI_GPM_COEX_B_PROFILE_VOTYPE   = 11,
+       MCI_GPM_COEX_H_PROFILE_T        = 12,
+       MCI_GPM_COEX_B_PROFILE_W        = 14,
+       MCI_GPM_COEX_B_PROFILE_A        = 15,
+       /* MCI_GPM_COEX_BT_STATUS_UPDATE */
+       MCI_GPM_COEX_B_STATUS_TYPE      = 6,
+       MCI_GPM_COEX_B_STATUS_LINKID    = 7,
+       MCI_GPM_COEX_B_STATUS_STATE     = 8,
+       /* MCI_GPM_COEX_BT_UPDATE_FLAGS */
+       MCI_GPM_COEX_W_BT_FLAGS         = 6,
+       MCI_GPM_COEX_B_BT_FLAGS_OP      = 10
+};
+
+enum mci_gpm_subtype {
+       MCI_GPM_BT_CAL_REQ      = 0,
+       MCI_GPM_BT_CAL_GRANT    = 1,
+       MCI_GPM_BT_CAL_DONE     = 2,
+       MCI_GPM_WLAN_CAL_REQ    = 3,
+       MCI_GPM_WLAN_CAL_GRANT  = 4,
+       MCI_GPM_WLAN_CAL_DONE   = 5,
+       MCI_GPM_COEX_AGENT      = 0x0c,
+       MCI_GPM_RSVD_PATTERN    = 0xfe,
+       MCI_GPM_RSVD_PATTERN32  = 0xfefefefe,
+       MCI_GPM_BT_DEBUG        = 0xff
+};
+
+enum mci_bt_state {
+       MCI_BT_SLEEP,
+       MCI_BT_AWAKE,
+       MCI_BT_CAL_START,
+       MCI_BT_CAL
+};
+
+/* Type of state query */
+enum mci_state_type {
+       MCI_STATE_ENABLE,
+       MCI_STATE_SET_BT_AWAKE,
+       MCI_STATE_SET_BT_CAL_START,
+       MCI_STATE_SET_BT_CAL,
+       MCI_STATE_LAST_SCHD_MSG_OFFSET,
+       MCI_STATE_REMOTE_SLEEP,
+       MCI_STATE_RESET_REQ_WAKE,
+       MCI_STATE_SEND_WLAN_COEX_VERSION,
+       MCI_STATE_SEND_VERSION_QUERY,
+       MCI_STATE_SEND_STATUS_QUERY,
+       MCI_STATE_SET_CONCUR_TX_PRI,
+       MCI_STATE_RECOVER_RX,
+       MCI_STATE_NEED_FTP_STOMP,
+       MCI_STATE_DEBUG,
+       MCI_STATE_MAX
+};
+
+enum mci_gpm_coex_opcode {
+       MCI_GPM_COEX_VERSION_QUERY,
+       MCI_GPM_COEX_VERSION_RESPONSE,
+       MCI_GPM_COEX_STATUS_QUERY,
+       MCI_GPM_COEX_HALT_BT_GPM,
+       MCI_GPM_COEX_WLAN_CHANNELS,
+       MCI_GPM_COEX_BT_PROFILE_INFO,
+       MCI_GPM_COEX_BT_STATUS_UPDATE,
+       MCI_GPM_COEX_BT_UPDATE_FLAGS
+};
+
+#define MCI_GPM_NOMORE  0
+#define MCI_GPM_MORE    1
+#define MCI_GPM_INVALID 0xffffffff
+
+#define MCI_GPM_RECYCLE(_p_gpm)        do {                      \
+       *(((u32 *)_p_gpm) + MCI_GPM_COEX_W_GPM_PAYLOAD) = \
+                               MCI_GPM_RSVD_PATTERN32;   \
+} while (0)
+
+#define MCI_GPM_TYPE(_p_gpm)   \
+       (*(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) & 0xff)
+
+#define MCI_GPM_OPCODE(_p_gpm) \
+       (*(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) & 0xff)
+
+#define MCI_GPM_SET_CAL_TYPE(_p_gpm, _cal_type)        do {                       \
+       *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_cal_type) & 0xff;\
+} while (0)
+
+#define MCI_GPM_SET_TYPE_OPCODE(_p_gpm, _type, _opcode) do {              \
+       *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_type) & 0xff;    \
+       *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) = (_opcode) & 0xff;\
+} while (0)
+
+#define MCI_GPM_IS_CAL_TYPE(_type) ((_type) <= MCI_GPM_WLAN_CAL_DONE)
+
+/*
+ * Functions that are available to the MCI driver core.
+ */
+bool ath9k_btcoex_ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag,
+                            u32 *payload, u8 len, bool wait_done,
+                            bool check_bt);
+u32 ath9k_btcoex_ar9003_mci_state(struct ath_hw *ah, u32 state_type);
+void ath9k_btcoex_ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
+                     u16 len, u32 sched_addr);
+void ath9k_btcoex_ar9003_mci_cleanup(struct ath_hw *ah);
+void ath9k_btcoex_ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
+                             u32 *rx_msg_intr);
+u32 ath9k_btcoex_ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more);
+void ath9k_btcoex_ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor);
+void ath9k_btcoex_ar9003_mci_send_wlan_channels(struct ath_hw *ah);
+/*
+ * These functions are used by ath9k_hw.
+ */
+
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+
+void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep);
+void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable);
+void ar9003_mci_init_cal_done(struct ath_hw *ah);
+void ar9003_mci_set_full_sleep(struct ath_hw *ah);
+void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force);
+void ar9003_mci_check_bt(struct ath_hw *ah);
+bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan);
+int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+                        struct ath9k_hw_cal_data *caldata);
+void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
+                     bool is_full_sleep);
+void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked);
+void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
+void ar9003_mci_set_power_awake(struct ath_hw *ah);
+void ar9003_mci_check_gpm_offset(struct ath_hw *ah);
+
+#else
+
+static inline void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep)
+{
+}
+static inline void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable)
+{
+}
+static inline void ar9003_mci_init_cal_done(struct ath_hw *ah)
+{
+}
+static inline void ar9003_mci_set_full_sleep(struct ath_hw *ah)
+{
+}
+static inline void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done)
+{
+}
+static inline void ar9003_mci_check_bt(struct ath_hw *ah)
+{
+}
+static inline bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       return false;
+}
+static inline int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+                                      struct ath9k_hw_cal_data *caldata)
+{
+       return 0;
+}
+static inline void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
+                                   bool is_full_sleep)
+{
+}
+static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
+{
+}
+static inline void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
+{
+}
+static inline void ar9003_mci_set_power_awake(struct ath_hw *ah)
+{
+}
+static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
+{
+}
+#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
+
+#endif
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_paprd.c
new file mode 100644 (file)
index 0000000..7ec0edd
--- /dev/null
@@ -0,0 +1,866 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/export.h>
+#include "hw.h"
+#include "ar9003_phy.h"
+
+void ath9k_btcoex_ar9003_paprd_enable(struct ath_hw *ah, bool val)
+{
+       struct ath9k_channel *chan = ah->curchan;
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+       /*
+        * 3 bits for modalHeader5G.papdRateMaskHt20
+        * is used for sub-band disabling of PAPRD.
+        * 5G band is divided into 3 sub-bands -- upper,
+        * middle, lower.
+        * if bit 30 of modalHeader5G.papdRateMaskHt20 is set
+        * -- disable PAPRD for upper band 5GHz
+        * if bit 29 of modalHeader5G.papdRateMaskHt20 is set
+        * -- disable PAPRD for middle band 5GHz
+        * if bit 28 of modalHeader5G.papdRateMaskHt20 is set
+        * -- disable PAPRD for lower band 5GHz
+        */
+
+       if (IS_CHAN_5GHZ(chan)) {
+               if (chan->channel >= UPPER_5G_SUB_BAND_START) {
+                       if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+                                                                 & BIT(30))
+                               val = false;
+               } else if (chan->channel >= MID_5G_SUB_BAND_START) {
+                       if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+                                                                 & BIT(29))
+                               val = false;
+               } else {
+                       if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+                                                                 & BIT(28))
+                               val = false;
+               }
+       }
+
+       if (val) {
+               ah->paprd_table_write_done = true;
+               ath9k_hw_apply_txpower(ah, chan, false);
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
+                     AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
+       if (ah->caps.tx_chainmask & BIT(1))
+               REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1,
+                             AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
+       if (ah->caps.tx_chainmask & BIT(2))
+               REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2,
+                             AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_paprd_enable);
+
+static int ar9003_get_training_power_2g(struct ath_hw *ah)
+{
+       struct ath9k_channel *chan = ah->curchan;
+       unsigned int power, scale, delta;
+
+       scale = ar9003_get_paprd_scale_factor(ah, chan);
+       power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
+                              AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
+
+       delta = abs((int) ah->paprd_target_power - (int) power);
+       if (delta > scale)
+               return -1;
+
+       if (delta < 4)
+               power -= 4 - delta;
+
+       return power;
+}
+
+static int ar9003_get_training_power_5g(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_channel *chan = ah->curchan;
+       unsigned int power, scale, delta;
+
+       scale = ar9003_get_paprd_scale_factor(ah, chan);
+
+       if (IS_CHAN_HT40(chan))
+               power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8,
+                       AR_PHY_POWERTX_RATE8_POWERTXHT40_5);
+       else
+               power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE6,
+                       AR_PHY_POWERTX_RATE6_POWERTXHT20_5);
+
+       power += scale;
+       delta = abs((int) ah->paprd_target_power - (int) power);
+       if (delta > scale)
+               return -1;
+
+       switch (get_streams(ah->txchainmask)) {
+       case 1:
+               delta = 6;
+               break;
+       case 2:
+               delta = 4;
+               break;
+       case 3:
+               delta = 2;
+               break;
+       default:
+               delta = 0;
+               ath_dbg(common, CALIBRATE, "Invalid tx-chainmask: %u\n",
+                       ah->txchainmask);
+       }
+
+       power += delta;
+       return power;
+}
+
+static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       static const u32 ctrl0[3] = {
+               AR_PHY_PAPRD_CTRL0_B0,
+               AR_PHY_PAPRD_CTRL0_B1,
+               AR_PHY_PAPRD_CTRL0_B2
+       };
+       static const u32 ctrl1[3] = {
+               AR_PHY_PAPRD_CTRL1_B0,
+               AR_PHY_PAPRD_CTRL1_B1,
+               AR_PHY_PAPRD_CTRL1_B2
+       };
+       int training_power;
+       int i, val;
+
+       if (IS_CHAN_2GHZ(ah->curchan))
+               training_power = ar9003_get_training_power_2g(ah);
+       else
+               training_power = ar9003_get_training_power_5g(ah);
+
+       ath_dbg(common, CALIBRATE, "Training power: %d, Target power: %d\n",
+               training_power, ah->paprd_target_power);
+
+       if (training_power < 0) {
+               ath_dbg(common, CALIBRATE,
+                       "PAPRD target power delta out of range\n");
+               return -ERANGE;
+       }
+       ah->paprd_training_power = training_power;
+
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
+                     ah->paprd_ratemask);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK,
+                     ah->paprd_ratemask);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,
+                     ah->paprd_ratemask_ht40);
+
+       for (i = 0; i < ah->caps.max_txchains; i++) {
+               REG_RMW_FIELD(ah, ctrl0[i],
+                             AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1);
+               REG_RMW_FIELD(ah, ctrl1[i],
+                             AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE, 1);
+               REG_RMW_FIELD(ah, ctrl1[i],
+                             AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE, 1);
+               REG_RMW_FIELD(ah, ctrl1[i],
+                             AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0);
+               REG_RMW_FIELD(ah, ctrl1[i],
+                             AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK, 181);
+               REG_RMW_FIELD(ah, ctrl1[i],
+                             AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT, 361);
+               REG_RMW_FIELD(ah, ctrl1[i],
+                             AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0);
+               REG_RMW_FIELD(ah, ctrl0[i],
+                             AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH, 3);
+       }
+
+       ath9k_btcoex_ar9003_paprd_enable(ah, false);
+
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
+                     AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP, 0x30);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
+                     AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE, 1);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
+                     AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE, 1);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
+                     AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE, 0);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
+                     AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE, 0);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
+                     AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
+                     AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1);
+       val = AR_SREV_9462(ah) ? 0x91 : 147;
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2,
+                     AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, val);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                     AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                     AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN, 4);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                     AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                     AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);
+       if (AR_SREV_9485(ah) || AR_SREV_9462(ah))
+               REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                             AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
+                             -3);
+       else
+               REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                             AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
+                             -6);
+       val = AR_SREV_9462(ah) ? -10 : -15;
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                     AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE,
+                     val);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                     AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4,
+                     AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA, 0);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4,
+                     AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR, 400);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4,
+                     AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES,
+                     100);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_0_B0,
+                     AR_PHY_PAPRD_PRE_POST_SCALING, 261376);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_1_B0,
+                     AR_PHY_PAPRD_PRE_POST_SCALING, 248079);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_2_B0,
+                     AR_PHY_PAPRD_PRE_POST_SCALING, 233759);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_3_B0,
+                     AR_PHY_PAPRD_PRE_POST_SCALING, 220464);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_4_B0,
+                     AR_PHY_PAPRD_PRE_POST_SCALING, 208194);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_5_B0,
+                     AR_PHY_PAPRD_PRE_POST_SCALING, 196949);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_6_B0,
+                     AR_PHY_PAPRD_PRE_POST_SCALING, 185706);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0,
+                     AR_PHY_PAPRD_PRE_POST_SCALING, 175487);
+       return 0;
+}
+
+static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
+{
+       u32 *entry = ah->paprd_gain_table_entries;
+       u8 *index = ah->paprd_gain_table_index;
+       u32 reg = AR_PHY_TXGAIN_TABLE;
+       int i;
+
+       memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
+       memset(index, 0, sizeof(ah->paprd_gain_table_index));
+
+       for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
+               entry[i] = REG_READ(ah, reg);
+               index[i] = (entry[i] >> 24) & 0xff;
+               reg += 4;
+       }
+}
+
+static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
+                                           int target_power)
+{
+       int olpc_gain_delta = 0, cl_gain_mod;
+       int alpha_therm, alpha_volt;
+       int therm_cal_value, volt_cal_value;
+       int therm_value, volt_value;
+       int thermal_gain_corr, voltage_gain_corr;
+       int desired_scale, desired_gain = 0;
+       u32 reg_olpc  = 0, reg_cl_gain  = 0;
+
+       REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+                   AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+       desired_scale = REG_READ_FIELD(ah, AR_PHY_TPC_12,
+                                      AR_PHY_TPC_12_DESIRED_SCALE_HT40_5);
+       alpha_therm = REG_READ_FIELD(ah, AR_PHY_TPC_19,
+                                    AR_PHY_TPC_19_ALPHA_THERM);
+       alpha_volt = REG_READ_FIELD(ah, AR_PHY_TPC_19,
+                                   AR_PHY_TPC_19_ALPHA_VOLT);
+       therm_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18,
+                                        AR_PHY_TPC_18_THERM_CAL_VALUE);
+       volt_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18,
+                                       AR_PHY_TPC_18_VOLT_CAL_VALUE);
+       therm_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
+                                    AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE);
+       volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
+                                   AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE);
+
+       switch (chain) {
+       case 0:
+               reg_olpc = AR_PHY_TPC_11_B0;
+               reg_cl_gain = AR_PHY_CL_TAB_0;
+               break;
+       case 1:
+               reg_olpc = AR_PHY_TPC_11_B1;
+               reg_cl_gain = AR_PHY_CL_TAB_1;
+               break;
+       case 2:
+               reg_olpc = AR_PHY_TPC_11_B2;
+               reg_cl_gain = AR_PHY_CL_TAB_2;
+               break;
+       default:
+               ath_dbg(ath9k_hw_common(ah), CALIBRATE,
+                       "Invalid chainmask: %d\n", chain);
+               break;
+       }
+
+       olpc_gain_delta = REG_READ_FIELD(ah, reg_olpc,
+                                        AR_PHY_TPC_11_OLPC_GAIN_DELTA);
+       cl_gain_mod = REG_READ_FIELD(ah, reg_cl_gain,
+                                        AR_PHY_CL_TAB_CL_GAIN_MOD);
+
+       if (olpc_gain_delta >= 128)
+               olpc_gain_delta = olpc_gain_delta - 256;
+
+       thermal_gain_corr = (alpha_therm * (therm_value - therm_cal_value) +
+                            (256 / 2)) / 256;
+       voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +
+                            (128 / 2)) / 128;
+       desired_gain = target_power - olpc_gain_delta - thermal_gain_corr -
+           voltage_gain_corr + desired_scale + cl_gain_mod;
+
+       return desired_gain;
+}
+
+static void ar9003_tx_force_gain(struct ath_hw *ah, unsigned int gain_index)
+{
+       int selected_gain_entry, txbb1dbgain, txbb6dbgain, txmxrgain;
+       int padrvgnA, padrvgnB, padrvgnC, padrvgnD;
+       u32 *gain_table_entries = ah->paprd_gain_table_entries;
+
+       selected_gain_entry = gain_table_entries[gain_index];
+       txbb1dbgain = selected_gain_entry & 0x7;
+       txbb6dbgain = (selected_gain_entry >> 3) & 0x3;
+       txmxrgain = (selected_gain_entry >> 5) & 0xf;
+       padrvgnA = (selected_gain_entry >> 9) & 0xf;
+       padrvgnB = (selected_gain_entry >> 13) & 0xf;
+       padrvgnC = (selected_gain_entry >> 17) & 0xf;
+       padrvgnD = (selected_gain_entry >> 21) & 0x3;
+
+       REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                     AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN, txbb1dbgain);
+       REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                     AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN, txbb6dbgain);
+       REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                     AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN, txmxrgain);
+       REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                     AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA, padrvgnA);
+       REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                     AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB, padrvgnB);
+       REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                     AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC, padrvgnC);
+       REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                     AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND, padrvgnD);
+       REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                     AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL, 0);
+       REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+                     AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN, 0);
+       REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCED_DAC_GAIN, 0);
+       REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCE_DAC_GAIN, 0);
+}
+
+static inline int find_expn(int num)
+{
+       return fls(num) - 1;
+}
+
+static inline int find_proper_scale(int expn, int N)
+{
+       return (expn > N) ? expn - 10 : 0;
+}
+
+#define NUM_BIN 23
+
+static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain)
+{
+       unsigned int thresh_accum_cnt;
+       int x_est[NUM_BIN + 1], Y[NUM_BIN + 1], theta[NUM_BIN + 1];
+       int PA_in[NUM_BIN + 1];
+       int B1_tmp[NUM_BIN + 1], B2_tmp[NUM_BIN + 1];
+       unsigned int B1_abs_max, B2_abs_max;
+       int max_index, scale_factor;
+       int y_est[NUM_BIN + 1];
+       int x_est_fxp1_nonlin, x_tilde[NUM_BIN + 1];
+       unsigned int x_tilde_abs;
+       int G_fxp, Y_intercept, order_x_by_y, M, I, L, sum_y_sqr, sum_y_quad;
+       int Q_x, Q_B1, Q_B2, beta_raw, alpha_raw, scale_B;
+       int Q_scale_B, Q_beta, Q_alpha, alpha, beta, order_1, order_2;
+       int order1_5x, order2_3x, order1_5x_rem, order2_3x_rem;
+       int y5, y3, tmp;
+       int theta_low_bin = 0;
+       int i;
+
+       /* disregard any bin that contains <= 16 samples */
+       thresh_accum_cnt = 16;
+       scale_factor = 5;
+       max_index = 0;
+       memset(theta, 0, sizeof(theta));
+       memset(x_est, 0, sizeof(x_est));
+       memset(Y, 0, sizeof(Y));
+       memset(y_est, 0, sizeof(y_est));
+       memset(x_tilde, 0, sizeof(x_tilde));
+
+       for (i = 0; i < NUM_BIN; i++) {
+               s32 accum_cnt, accum_tx, accum_rx, accum_ang;
+
+               /* number of samples */
+               accum_cnt = data_L[i] & 0xffff;
+
+               if (accum_cnt <= thresh_accum_cnt)
+                       continue;
+
+               /* sum(tx amplitude) */
+               accum_tx = ((data_L[i] >> 16) & 0xffff) |
+                   ((data_U[i] & 0x7ff) << 16);
+
+               /* sum(rx amplitude distance to lower bin edge) */
+               accum_rx = ((data_U[i] >> 11) & 0x1f) |
+                   ((data_L[i + 23] & 0xffff) << 5);
+
+               /* sum(angles) */
+               accum_ang = ((data_L[i + 23] >> 16) & 0xffff) |
+                   ((data_U[i + 23] & 0x7ff) << 16);
+
+               accum_tx <<= scale_factor;
+               accum_rx <<= scale_factor;
+               x_est[i + 1] = (((accum_tx + accum_cnt) / accum_cnt) + 32) >>
+                   scale_factor;
+
+               Y[i + 1] = ((((accum_rx + accum_cnt) / accum_cnt) + 32) >>
+                           scale_factor) +
+                           (1 << scale_factor) * max_index + 16;
+
+               if (accum_ang >= (1 << 26))
+                       accum_ang -= 1 << 27;
+
+               theta[i + 1] = ((accum_ang * (1 << scale_factor)) + accum_cnt) /
+                   accum_cnt;
+
+               max_index++;
+       }
+
+       /*
+        * Find average theta of first 5 bin and all of those to same value.
+        * Curve is linear at that range.
+        */
+       for (i = 1; i < 6; i++)
+               theta_low_bin += theta[i];
+
+       theta_low_bin = theta_low_bin / 5;
+       for (i = 1; i < 6; i++)
+               theta[i] = theta_low_bin;
+
+       /* Set values at origin */
+       theta[0] = theta_low_bin;
+       for (i = 0; i <= max_index; i++)
+               theta[i] -= theta_low_bin;
+
+       x_est[0] = 0;
+       Y[0] = 0;
+       scale_factor = 8;
+
+       /* low signal gain */
+       if (x_est[6] == x_est[3])
+               return false;
+
+       G_fxp =
+           (((Y[6] - Y[3]) * 1 << scale_factor) +
+            (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]);
+
+       /* prevent division by zero */
+       if (G_fxp == 0)
+               return false;
+
+       Y_intercept =
+           (G_fxp * (x_est[0] - x_est[3]) +
+            (1 << scale_factor)) / (1 << scale_factor) + Y[3];
+
+       for (i = 0; i <= max_index; i++)
+               y_est[i] = Y[i] - Y_intercept;
+
+       for (i = 0; i <= 3; i++) {
+               y_est[i] = i * 32;
+               x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp;
+       }
+
+       if (y_est[max_index] == 0)
+               return false;
+
+       x_est_fxp1_nonlin =
+           x_est[max_index] - ((1 << scale_factor) * y_est[max_index] +
+                               G_fxp) / G_fxp;
+
+       order_x_by_y =
+           (x_est_fxp1_nonlin + y_est[max_index]) / y_est[max_index];
+
+       if (order_x_by_y == 0)
+               M = 10;
+       else if (order_x_by_y == 1)
+               M = 9;
+       else
+               M = 8;
+
+       I = (max_index > 15) ? 7 : max_index >> 1;
+       L = max_index - I;
+       scale_factor = 8;
+       sum_y_sqr = 0;
+       sum_y_quad = 0;
+       x_tilde_abs = 0;
+
+       for (i = 0; i <= L; i++) {
+               unsigned int y_sqr;
+               unsigned int y_quad;
+               unsigned int tmp_abs;
+
+               /* prevent division by zero */
+               if (y_est[i + I] == 0)
+                       return false;
+
+               x_est_fxp1_nonlin =
+                   x_est[i + I] - ((1 << scale_factor) * y_est[i + I] +
+                                   G_fxp) / G_fxp;
+
+               x_tilde[i] =
+                   (x_est_fxp1_nonlin * (1 << M) + y_est[i + I]) / y_est[i +
+                                                                         I];
+               x_tilde[i] =
+                   (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I];
+               x_tilde[i] =
+                   (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I];
+               y_sqr =
+                   (y_est[i + I] * y_est[i + I] +
+                    (scale_factor * scale_factor)) / (scale_factor *
+                                                      scale_factor);
+               tmp_abs = abs(x_tilde[i]);
+               if (tmp_abs > x_tilde_abs)
+                       x_tilde_abs = tmp_abs;
+
+               y_quad = y_sqr * y_sqr;
+               sum_y_sqr = sum_y_sqr + y_sqr;
+               sum_y_quad = sum_y_quad + y_quad;
+               B1_tmp[i] = y_sqr * (L + 1);
+               B2_tmp[i] = y_sqr;
+       }
+
+       B1_abs_max = 0;
+       B2_abs_max = 0;
+       for (i = 0; i <= L; i++) {
+               int abs_val;
+
+               B1_tmp[i] -= sum_y_sqr;
+               B2_tmp[i] = sum_y_quad - sum_y_sqr * B2_tmp[i];
+
+               abs_val = abs(B1_tmp[i]);
+               if (abs_val > B1_abs_max)
+                       B1_abs_max = abs_val;
+
+               abs_val = abs(B2_tmp[i]);
+               if (abs_val > B2_abs_max)
+                       B2_abs_max = abs_val;
+       }
+
+       Q_x = find_proper_scale(find_expn(x_tilde_abs), 10);
+       Q_B1 = find_proper_scale(find_expn(B1_abs_max), 10);
+       Q_B2 = find_proper_scale(find_expn(B2_abs_max), 10);
+
+       beta_raw = 0;
+       alpha_raw = 0;
+       for (i = 0; i <= L; i++) {
+               x_tilde[i] = x_tilde[i] / (1 << Q_x);
+               B1_tmp[i] = B1_tmp[i] / (1 << Q_B1);
+               B2_tmp[i] = B2_tmp[i] / (1 << Q_B2);
+               beta_raw = beta_raw + B1_tmp[i] * x_tilde[i];
+               alpha_raw = alpha_raw + B2_tmp[i] * x_tilde[i];
+       }
+
+       scale_B =
+           ((sum_y_quad / scale_factor) * (L + 1) -
+            (sum_y_sqr / scale_factor) * sum_y_sqr) * scale_factor;
+
+       Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10);
+       scale_B = scale_B / (1 << Q_scale_B);
+       if (scale_B == 0)
+               return false;
+       Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10);
+       Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10);
+       beta_raw = beta_raw / (1 << Q_beta);
+       alpha_raw = alpha_raw / (1 << Q_alpha);
+       alpha = (alpha_raw << 10) / scale_B;
+       beta = (beta_raw << 10) / scale_B;
+       order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B;
+       order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B;
+       order1_5x = order_1 / 5;
+       order2_3x = order_2 / 3;
+       order1_5x_rem = order_1 - 5 * order1_5x;
+       order2_3x_rem = order_2 - 3 * order2_3x;
+
+       for (i = 0; i < PAPRD_TABLE_SZ; i++) {
+               tmp = i * 32;
+               y5 = ((beta * tmp) >> 6) >> order1_5x;
+               y5 = (y5 * tmp) >> order1_5x;
+               y5 = (y5 * tmp) >> order1_5x;
+               y5 = (y5 * tmp) >> order1_5x;
+               y5 = (y5 * tmp) >> order1_5x;
+               y5 = y5 >> order1_5x_rem;
+               y3 = (alpha * tmp) >> order2_3x;
+               y3 = (y3 * tmp) >> order2_3x;
+               y3 = (y3 * tmp) >> order2_3x;
+               y3 = y3 >> order2_3x_rem;
+               PA_in[i] = y5 + y3 + (256 * tmp) / G_fxp;
+
+               if (i >= 2) {
+                       tmp = PA_in[i] - PA_in[i - 1];
+                       if (tmp < 0)
+                               PA_in[i] =
+                                   PA_in[i - 1] + (PA_in[i - 1] -
+                                                   PA_in[i - 2]);
+               }
+
+               PA_in[i] = (PA_in[i] < 1400) ? PA_in[i] : 1400;
+       }
+
+       beta_raw = 0;
+       alpha_raw = 0;
+
+       for (i = 0; i <= L; i++) {
+               int theta_tilde =
+                   ((theta[i + I] << M) + y_est[i + I]) / y_est[i + I];
+               theta_tilde =
+                   ((theta_tilde << M) + y_est[i + I]) / y_est[i + I];
+               theta_tilde =
+                   ((theta_tilde << M) + y_est[i + I]) / y_est[i + I];
+               beta_raw = beta_raw + B1_tmp[i] * theta_tilde;
+               alpha_raw = alpha_raw + B2_tmp[i] * theta_tilde;
+       }
+
+       Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10);
+       Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10);
+       beta_raw = beta_raw / (1 << Q_beta);
+       alpha_raw = alpha_raw / (1 << Q_alpha);
+
+       alpha = (alpha_raw << 10) / scale_B;
+       beta = (beta_raw << 10) / scale_B;
+       order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B + 5;
+       order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B + 5;
+       order1_5x = order_1 / 5;
+       order2_3x = order_2 / 3;
+       order1_5x_rem = order_1 - 5 * order1_5x;
+       order2_3x_rem = order_2 - 3 * order2_3x;
+
+       for (i = 0; i < PAPRD_TABLE_SZ; i++) {
+               int PA_angle;
+
+               /* pa_table[4] is calculated from PA_angle for i=5 */
+               if (i == 4)
+                       continue;
+
+               tmp = i * 32;
+               if (beta > 0)
+                       y5 = (((beta * tmp - 64) >> 6) -
+                             (1 << order1_5x)) / (1 << order1_5x);
+               else
+                       y5 = ((((beta * tmp - 64) >> 6) +
+                              (1 << order1_5x)) / (1 << order1_5x));
+
+               y5 = (y5 * tmp) / (1 << order1_5x);
+               y5 = (y5 * tmp) / (1 << order1_5x);
+               y5 = (y5 * tmp) / (1 << order1_5x);
+               y5 = (y5 * tmp) / (1 << order1_5x);
+               y5 = y5 / (1 << order1_5x_rem);
+
+               if (beta > 0)
+                       y3 = (alpha * tmp -
+                             (1 << order2_3x)) / (1 << order2_3x);
+               else
+                       y3 = (alpha * tmp +
+                             (1 << order2_3x)) / (1 << order2_3x);
+               y3 = (y3 * tmp) / (1 << order2_3x);
+               y3 = (y3 * tmp) / (1 << order2_3x);
+               y3 = y3 / (1 << order2_3x_rem);
+
+               if (i < 4) {
+                       PA_angle = 0;
+               } else {
+                       PA_angle = y5 + y3;
+                       if (PA_angle < -150)
+                               PA_angle = -150;
+                       else if (PA_angle > 150)
+                               PA_angle = 150;
+               }
+
+               pa_table[i] = ((PA_in[i] & 0x7ff) << 11) + (PA_angle & 0x7ff);
+               if (i == 5) {
+                       PA_angle = (PA_angle + 2) >> 1;
+                       pa_table[i - 1] = ((PA_in[i - 1] & 0x7ff) << 11) +
+                           (PA_angle & 0x7ff);
+               }
+       }
+
+       *gain = G_fxp;
+       return true;
+}
+
+void ath9k_btcoex_ar9003_paprd_populate_single_table(struct ath_hw *ah,
+                                       struct ath9k_hw_cal_data *caldata,
+                                       int chain)
+{
+       u32 *paprd_table_val = caldata->pa_table[chain];
+       u32 small_signal_gain = caldata->small_signal_gain[chain];
+       u32 training_power = ah->paprd_training_power;
+       u32 reg = 0;
+       int i;
+
+       if (chain == 0)
+               reg = AR_PHY_PAPRD_MEM_TAB_B0;
+       else if (chain == 1)
+               reg = AR_PHY_PAPRD_MEM_TAB_B1;
+       else if (chain == 2)
+               reg = AR_PHY_PAPRD_MEM_TAB_B2;
+
+       for (i = 0; i < PAPRD_TABLE_SZ; i++) {
+               REG_WRITE(ah, reg, paprd_table_val[i]);
+               reg = reg + 4;
+       }
+
+       if (chain == 0)
+               reg = AR_PHY_PA_GAIN123_B0;
+       else if (chain == 1)
+               reg = AR_PHY_PA_GAIN123_B1;
+       else
+               reg = AR_PHY_PA_GAIN123_B2;
+
+       REG_RMW_FIELD(ah, reg, AR_PHY_PA_GAIN123_PA_GAIN1, small_signal_gain);
+
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B0,
+                     AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
+                     training_power);
+
+       if (ah->caps.tx_chainmask & BIT(1))
+               REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1,
+                             AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
+                             training_power);
+
+       if (ah->caps.tx_chainmask & BIT(2))
+               /* val AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL correct? */
+               REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2,
+                             AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
+                             training_power);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_paprd_populate_single_table);
+
+int ath9k_btcoex_ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
+{
+       unsigned int i, desired_gain, gain_index;
+       unsigned int train_power = ah->paprd_training_power;
+
+       desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
+
+       gain_index = 0;
+       for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
+               if (ah->paprd_gain_table_index[i] >= desired_gain)
+                       break;
+               gain_index++;
+       }
+
+       ar9003_tx_force_gain(ah, gain_index);
+
+       REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+                       AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+
+       return 0;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_paprd_setup_gain_table);
+
+int ath9k_btcoex_ar9003_paprd_create_curve(struct ath_hw *ah,
+                             struct ath9k_hw_cal_data *caldata, int chain)
+{
+       u16 *small_signal_gain = &caldata->small_signal_gain[chain];
+       u32 *pa_table = caldata->pa_table[chain];
+       u32 *data_L, *data_U;
+       int i, status = 0;
+       u32 *buf;
+       u32 reg;
+
+       memset(caldata->pa_table[chain], 0, sizeof(caldata->pa_table[chain]));
+
+       buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC);
+       if (!buf)
+               return -ENOMEM;
+
+       data_L = &buf[0];
+       data_U = &buf[48];
+
+       REG_CLR_BIT(ah, AR_PHY_CHAN_INFO_MEMORY,
+                   AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ);
+
+       reg = AR_PHY_CHAN_INFO_TAB_0;
+       for (i = 0; i < 48; i++)
+               data_L[i] = REG_READ(ah, reg + (i << 2));
+
+       REG_SET_BIT(ah, AR_PHY_CHAN_INFO_MEMORY,
+                   AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ);
+
+       for (i = 0; i < 48; i++)
+               data_U[i] = REG_READ(ah, reg + (i << 2));
+
+       if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))
+               status = -2;
+
+       REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+                   AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+
+       kfree(buf);
+
+       return status;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_paprd_create_curve);
+
+int ath9k_btcoex_ar9003_paprd_init_table(struct ath_hw *ah)
+{
+       int ret;
+
+       ret = ar9003_paprd_setup_single_table(ah);
+       if (ret < 0)
+           return ret;
+
+       ar9003_paprd_get_gain_table(ah);
+       return 0;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_paprd_init_table);
+
+bool ath9k_btcoex_ar9003_paprd_is_done(struct ath_hw *ah)
+{
+       int paprd_done, agc2_pwr;
+       paprd_done = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+                               AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+
+       if (paprd_done == 0x1) {
+               agc2_pwr = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+                               AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);
+
+               ath_dbg(ath9k_hw_common(ah), CALIBRATE,
+                       "AGC2_PWR = 0x%x training done = 0x%x\n",
+                       agc2_pwr, paprd_done);
+       /*
+        * agc2_pwr range should not be less than 'IDEAL_AGC2_PWR_CHANGE'
+        * when the training is completely done, otherwise retraining is
+        * done to make sure the value is in ideal range
+        */
+               if (agc2_pwr <= PAPRD_IDEAL_AGC2_PWR_RANGE)
+                       paprd_done = 0;
+       }
+
+       return !!paprd_done;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_paprd_is_done);
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_phy.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_phy.c
new file mode 100644 (file)
index 0000000..108d783
--- /dev/null
@@ -0,0 +1,1503 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/export.h>
+#include "hw.h"
+#include "ar9003_phy.h"
+
+static const int firstep_table[] =
+/* level:  0   1   2   3   4   5   6   7   8  */
+       { -4, -2,  0,  2,  4,  6,  8, 10, 12 }; /* lvl 0-8, default 2 */
+
+static const int cycpwrThr1_table[] =
+/* level:  0   1   2   3   4   5   6   7   8  */
+       { -6, -4, -2,  0,  2,  4,  6,  8 };     /* lvl 0-7, default 3 */
+
+/*
+ * register values to turn OFDM weak signal detection OFF
+ */
+static const int m1ThreshLow_off = 127;
+static const int m2ThreshLow_off = 127;
+static const int m1Thresh_off = 127;
+static const int m2Thresh_off = 127;
+static const int m2CountThr_off =  31;
+static const int m2CountThrLow_off =  63;
+static const int m1ThreshLowExt_off = 127;
+static const int m2ThreshLowExt_off = 127;
+static const int m1ThreshExt_off = 127;
+static const int m2ThreshExt_off = 127;
+
+/**
+ * ar9003_hw_set_channel - set channel on single-chip device
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * This is the function to change channel on single-chip devices, that is
+ * for AR9300 family of chipsets.
+ *
+ * This function takes the channel value in MHz and sets
+ * hardware channel value. Assumes writes have been enabled to analog bus.
+ *
+ * Actual Expression,
+ *
+ * For 2GHz channel,
+ * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
+ * (freq_ref = 40MHz)
+ *
+ * For 5GHz channel,
+ * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
+ * (freq_ref = 40MHz/(24>>amodeRefSel))
+ *
+ * For 5GHz channels which are 5MHz spaced,
+ * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
+ * (freq_ref = 40MHz)
+ */
+static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       u16 bMode, fracMode = 0, aModeRefSel = 0;
+       u32 freq, channelSel = 0, reg32 = 0;
+       struct chan_centers centers;
+       int loadSynthChannel;
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       freq = centers.synth_center;
+
+       if (freq < 4800) {     /* 2 GHz, fractional mode */
+               if (AR_SREV_9330(ah)) {
+                       u32 chan_frac;
+                       u32 div;
+
+                       if (ah->is_clk_25mhz)
+                               div = 75;
+                       else
+                               div = 120;
+
+                       channelSel = (freq * 4) / div;
+                       chan_frac = (((freq * 4) % div) * 0x20000) / div;
+                       channelSel = (channelSel << 17) | chan_frac;
+               } else if (AR_SREV_9485(ah)) {
+                       u32 chan_frac;
+
+                       /*
+                        * freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0
+                        * ndiv = ((chan_mhz * 4) / 3) / freq_ref;
+                        * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000
+                        */
+                       channelSel = (freq * 4) / 120;
+                       chan_frac = (((freq * 4) % 120) * 0x20000) / 120;
+                       channelSel = (channelSel << 17) | chan_frac;
+               } else if (AR_SREV_9340(ah)) {
+                       if (ah->is_clk_25mhz) {
+                               u32 chan_frac;
+
+                               channelSel = (freq * 2) / 75;
+                               chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
+                               channelSel = (channelSel << 17) | chan_frac;
+                       } else
+                               channelSel = CHANSEL_2G(freq) >> 1;
+               } else
+                       channelSel = CHANSEL_2G(freq);
+               /* Set to 2G mode */
+               bMode = 1;
+       } else {
+               if (AR_SREV_9340(ah) && ah->is_clk_25mhz) {
+                       u32 chan_frac;
+
+                       channelSel = (freq * 2) / 75;
+                       chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
+                       channelSel = (channelSel << 17) | chan_frac;
+               } else {
+                       channelSel = CHANSEL_5G(freq);
+                       /* Doubler is ON, so, divide channelSel by 2. */
+                       channelSel >>= 1;
+               }
+               /* Set to 5G mode */
+               bMode = 0;
+       }
+
+       /* Enable fractional mode for all channels */
+       fracMode = 1;
+       aModeRefSel = 0;
+       loadSynthChannel = 0;
+
+       reg32 = (bMode << 29);
+       REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
+
+       /* Enable Long shift Select for Synthesizer */
+       REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH4,
+                     AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1);
+
+       /* Program Synth. setting */
+       reg32 = (channelSel << 2) | (fracMode << 30) |
+               (aModeRefSel << 28) | (loadSynthChannel << 31);
+       REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);
+
+       /* Toggle Load Synth channel bit */
+       loadSynthChannel = 1;
+       reg32 = (channelSel << 2) | (fracMode << 30) |
+               (aModeRefSel << 28) | (loadSynthChannel << 31);
+       REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);
+
+       ah->curchan = chan;
+       ah->curchan_rad_index = -1;
+
+       return 0;
+}
+
+/**
+ * ar9003_hw_spur_mitigate_mrc_cck - convert baseband spur frequency
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For single-chip solutions. Converts to baseband spur frequency given the
+ * input channel frequency and compute register settings below.
+ *
+ * Spur mitigation for MRC CCK
+ */
+static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
+                                           struct ath9k_channel *chan)
+{
+       static const u32 spur_freq[4] = { 2420, 2440, 2464, 2480 };
+       int cur_bb_spur, negative = 0, cck_spur_freq;
+       int i;
+       int range, max_spur_cnts, synth_freq;
+       u8 *spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, IS_CHAN_2GHZ(chan));
+
+       /*
+        * Need to verify range +/- 10 MHz in control channel, otherwise spur
+        * is out-of-band and can be ignored.
+        */
+
+       if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {
+               if (spur_fbin_ptr[0] == 0) /* No spur */
+                       return;
+               max_spur_cnts = 5;
+               if (IS_CHAN_HT40(chan)) {
+                       range = 19;
+                       if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
+                                          AR_PHY_GC_DYN2040_PRI_CH) == 0)
+                               synth_freq = chan->channel + 10;
+                       else
+                               synth_freq = chan->channel - 10;
+               } else {
+                       range = 10;
+                       synth_freq = chan->channel;
+               }
+       } else {
+               range = AR_SREV_9462(ah) ? 5 : 10;
+               max_spur_cnts = 4;
+               synth_freq = chan->channel;
+       }
+
+       for (i = 0; i < max_spur_cnts; i++) {
+               if (AR_SREV_9462(ah) && (i == 0 || i == 3))
+                       continue;
+               negative = 0;
+               if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
+                       cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
+                                       IS_CHAN_2GHZ(chan)) - synth_freq;
+               else
+                       cur_bb_spur = spur_freq[i] - synth_freq;
+
+               if (cur_bb_spur < 0) {
+                       negative = 1;
+                       cur_bb_spur = -cur_bb_spur;
+               }
+               if (cur_bb_spur < range) {
+                       cck_spur_freq = (int)((cur_bb_spur << 19) / 11);
+
+                       if (negative == 1)
+                               cck_spur_freq = -cck_spur_freq;
+
+                       cck_spur_freq = cck_spur_freq & 0xfffff;
+
+                       REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL,
+                                     AR_PHY_AGC_CONTROL_YCOK_MAX, 0x7);
+                       REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+                                     AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR, 0x7f);
+                       REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+                                     AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE,
+                                     0x2);
+                       REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+                                     AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT,
+                                     0x1);
+                       REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+                                     AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ,
+                                     cck_spur_freq);
+
+                       return;
+               }
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL,
+                     AR_PHY_AGC_CONTROL_YCOK_MAX, 0x5);
+       REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+                     AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, 0x0);
+       REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
+                     AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, 0x0);
+}
+
+/* Clean all spur register fields */
+static void ar9003_hw_spur_ofdm_clear(struct ath_hw *ah)
+{
+       REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+                     AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+                     AR_PHY_TIMING11_SPUR_FREQ_SD, 0);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+                     AR_PHY_TIMING11_SPUR_DELTA_PHASE, 0);
+       REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                     AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, 0);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+                     AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+                     AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+                     AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0);
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+                     AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 0);
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+                     AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 0);
+
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+                     AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+                     AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+                     AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0);
+       REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
+                     AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, 0);
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
+                     AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, 0);
+       REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
+                     AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, 0);
+       REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
+                     AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0);
+       REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
+                     AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0);
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
+                     AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0);
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+                     AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0);
+}
+
+static void ar9003_hw_spur_ofdm(struct ath_hw *ah,
+                               int freq_offset,
+                               int spur_freq_sd,
+                               int spur_delta_phase,
+                               int spur_subchannel_sd)
+{
+       int mask_index = 0;
+
+       /* OFDM Spur mitigation */
+       REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+                AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0x1);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+                     AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+                     AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase);
+       REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                     AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, spur_subchannel_sd);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+                     AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0x1);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING11,
+                     AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0x1);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+                     AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1);
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+                     AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, 34);
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+                     AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1);
+
+       if (REG_READ_FIELD(ah, AR_PHY_MODE,
+                          AR_PHY_MODE_DYNAMIC) == 0x1)
+               REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+                             AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1);
+
+       mask_index = (freq_offset << 4) / 5;
+       if (mask_index < 0)
+               mask_index = mask_index - 1;
+
+       mask_index = mask_index & 0x7f;
+
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+                     AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0x1);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+                     AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0x1);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING4,
+                     AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0x1);
+       REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
+                     AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, mask_index);
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
+                     AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, mask_index);
+       REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
+                     AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, mask_index);
+       REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
+                     AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0xc);
+       REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
+                     AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0xc);
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
+                     AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0);
+       REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
+                     AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff);
+}
+
+static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
+                                    struct ath9k_channel *chan,
+                                    int freq_offset)
+{
+       int spur_freq_sd = 0;
+       int spur_subchannel_sd = 0;
+       int spur_delta_phase = 0;
+
+       if (IS_CHAN_HT40(chan)) {
+               if (freq_offset < 0) {
+                       if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
+                                          AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
+                               spur_subchannel_sd = 1;
+                       else
+                               spur_subchannel_sd = 0;
+
+                       spur_freq_sd = ((freq_offset + 10) << 9) / 11;
+
+               } else {
+                       if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
+                           AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
+                               spur_subchannel_sd = 0;
+                       else
+                               spur_subchannel_sd = 1;
+
+                       spur_freq_sd = ((freq_offset - 10) << 9) / 11;
+
+               }
+
+               spur_delta_phase = (freq_offset << 17) / 5;
+
+       } else {
+               spur_subchannel_sd = 0;
+               spur_freq_sd = (freq_offset << 9) /11;
+               spur_delta_phase = (freq_offset << 18) / 5;
+       }
+
+       spur_freq_sd = spur_freq_sd & 0x3ff;
+       spur_delta_phase = spur_delta_phase & 0xfffff;
+
+       ar9003_hw_spur_ofdm(ah,
+                           freq_offset,
+                           spur_freq_sd,
+                           spur_delta_phase,
+                           spur_subchannel_sd);
+}
+
+/* Spur mitigation for OFDM */
+static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah,
+                                        struct ath9k_channel *chan)
+{
+       int synth_freq;
+       int range = 10;
+       int freq_offset = 0;
+       int mode;
+       u8* spurChansPtr;
+       unsigned int i;
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+       if (IS_CHAN_5GHZ(chan)) {
+               spurChansPtr = &(eep->modalHeader5G.spurChans[0]);
+               mode = 0;
+       }
+       else {
+               spurChansPtr = &(eep->modalHeader2G.spurChans[0]);
+               mode = 1;
+       }
+
+       if (spurChansPtr[0] == 0)
+               return; /* No spur in the mode */
+
+       if (IS_CHAN_HT40(chan)) {
+               range = 19;
+               if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
+                                  AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
+                       synth_freq = chan->channel - 10;
+               else
+                       synth_freq = chan->channel + 10;
+       } else {
+               range = 10;
+               synth_freq = chan->channel;
+       }
+
+       ar9003_hw_spur_ofdm_clear(ah);
+
+       for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) {
+               freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq;
+               if (abs(freq_offset) < range) {
+                       ar9003_hw_spur_ofdm_work(ah, chan, freq_offset);
+                       break;
+               }
+       }
+}
+
+static void ar9003_hw_spur_mitigate(struct ath_hw *ah,
+                                   struct ath9k_channel *chan)
+{
+       ar9003_hw_spur_mitigate_mrc_cck(ah, chan);
+       ar9003_hw_spur_mitigate_ofdm(ah, chan);
+}
+
+static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah,
+                                        struct ath9k_channel *chan)
+{
+       u32 pll;
+
+       pll = SM(0x5, AR_RTC_9300_PLL_REFDIV);
+
+       if (chan && IS_CHAN_HALF_RATE(chan))
+               pll |= SM(0x1, AR_RTC_9300_PLL_CLKSEL);
+       else if (chan && IS_CHAN_QUARTER_RATE(chan))
+               pll |= SM(0x2, AR_RTC_9300_PLL_CLKSEL);
+
+       pll |= SM(0x2c, AR_RTC_9300_PLL_DIV);
+
+       return pll;
+}
+
+static void ar9003_hw_set_channel_regs(struct ath_hw *ah,
+                                      struct ath9k_channel *chan)
+{
+       u32 phymode;
+       u32 enableDacFifo = 0;
+
+       enableDacFifo =
+               (REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO);
+
+       /* Enable 11n HT, 20 MHz */
+       phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 |
+                 AR_PHY_GC_SHORT_GI_40 | enableDacFifo;
+
+       /* Configure baseband for dynamic 20/40 operation */
+       if (IS_CHAN_HT40(chan)) {
+               phymode |= AR_PHY_GC_DYN2040_EN;
+               /* Configure control (primary) channel at +-10MHz */
+               if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+                   (chan->chanmode == CHANNEL_G_HT40PLUS))
+                       phymode |= AR_PHY_GC_DYN2040_PRI_CH;
+
+       }
+
+       /* make sure we preserve INI settings */
+       phymode |= REG_READ(ah, AR_PHY_GEN_CTRL);
+       /* turn off Green Field detection for STA for now */
+       phymode &= ~AR_PHY_GC_GF_DETECT_EN;
+
+       REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode);
+
+       /* Configure MAC for 20/40 operation */
+       ath9k_hw_set11nmac2040(ah);
+
+       /* global transmit timeout (25 TUs default)*/
+       REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
+       /* carrier sense timeout */
+       REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
+}
+
+static void ar9003_hw_init_bb(struct ath_hw *ah,
+                             struct ath9k_channel *chan)
+{
+       u32 synthDelay;
+
+       /*
+        * Wait for the frequency synth to settle (synth goes on
+        * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
+        * Value is in 100ns increments.
+        */
+       synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_B(chan))
+               synthDelay = (4 * synthDelay) / 22;
+       else
+               synthDelay /= 10;
+
+       /* Activate the PHY (includes baseband activate + synthesizer on) */
+       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+       /*
+        * There is an issue if the AP starts the calibration before
+        * the base band timeout completes.  This could result in the
+        * rx_clear false triggering.  As a workaround we add delay an
+        * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
+        * does not happen.
+        */
+       udelay(synthDelay + BASE_ACTIVATE_DELAY);
+}
+
+static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
+{
+       switch (rx) {
+       case 0x5:
+               REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+                           AR_PHY_SWAP_ALT_CHAIN);
+       case 0x3:
+       case 0x1:
+       case 0x2:
+       case 0x7:
+               REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
+               REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
+               break;
+       default:
+               break;
+       }
+
+       if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
+               REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
+       else if (AR_SREV_9462(ah))
+               /* xxx only when MCI support is enabled */
+               REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
+       else
+               REG_WRITE(ah, AR_SELFGEN_MASK, tx);
+
+       if (tx == 0x5) {
+               REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+                           AR_PHY_SWAP_ALT_CHAIN);
+       }
+}
+
+/*
+ * Override INI values with chip specific configuration.
+ */
+static void ar9003_hw_override_ini(struct ath_hw *ah)
+{
+       u32 val;
+
+       /*
+        * Set the RX_ABORT and RX_DIS and clear it only after
+        * RXE is set for MAC. This prevents frames with
+        * corrupted descriptor status.
+        */
+       REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+       /*
+        * For AR9280 and above, there is a new feature that allows
+        * Multicast search based on both MAC Address and Key ID. By default,
+        * this feature is enabled. But since the driver is not using this
+        * feature, we switch it off; otherwise multicast search based on
+        * MAC addr only will fail.
+        */
+       val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
+       REG_WRITE(ah, AR_PCU_MISC_MODE2,
+                 val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
+
+       REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
+                   AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+}
+
+static void ar9003_hw_prog_ini(struct ath_hw *ah,
+                              struct ar5416IniArray *iniArr,
+                              int column)
+{
+       unsigned int i, regWrites = 0;
+
+       /* New INI format: Array may be undefined (pre, core, post arrays) */
+       if (!iniArr->ia_array)
+               return;
+
+       /*
+        * New INI format: Pre, core, and post arrays for a given subsystem
+        * may be modal (> 2 columns) or non-modal (2 columns). Determine if
+        * the array is non-modal and force the column to 1.
+        */
+       if (column >= iniArr->ia_columns)
+               column = 1;
+
+       for (i = 0; i < iniArr->ia_rows; i++) {
+               u32 reg = INI_RA(iniArr, i, 0);
+               u32 val = INI_RA(iniArr, i, column);
+
+               REG_WRITE(ah, reg, val);
+
+               DO_DELAY(regWrites);
+       }
+}
+
+static int ar9003_hw_process_ini(struct ath_hw *ah,
+                                struct ath9k_channel *chan)
+{
+       unsigned int regWrites = 0, i;
+       u32 modesIndex;
+
+       switch (chan->chanmode) {
+       case CHANNEL_A:
+       case CHANNEL_A_HT20:
+               modesIndex = 1;
+               break;
+       case CHANNEL_A_HT40PLUS:
+       case CHANNEL_A_HT40MINUS:
+               modesIndex = 2;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_G_HT20:
+       case CHANNEL_B:
+               modesIndex = 4;
+               break;
+       case CHANNEL_G_HT40PLUS:
+       case CHANNEL_G_HT40MINUS:
+               modesIndex = 3;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ATH_INI_NUM_SPLIT; i++) {
+               ar9003_hw_prog_ini(ah, &ah->iniSOC[i], modesIndex);
+               ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex);
+               ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex);
+               ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex);
+               if (i == ATH_INI_POST && AR_SREV_9462_20(ah))
+                       ar9003_hw_prog_ini(ah,
+                                          &ah->ini_radio_post_sys2ant,
+                                          modesIndex);
+       }
+
+       REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
+       REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+
+       /*
+        * For 5GHz channels requiring Fast Clock, apply
+        * different modal values.
+        */
+       if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+               REG_WRITE_ARRAY(&ah->iniModesFastClock,
+                               modesIndex, regWrites);
+
+       REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
+
+       if (chan->channel == 2484)
+               ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1);
+
+       if (AR_SREV_9462(ah))
+               REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
+                         AR_GLB_SWREG_DISCONT_EN_BT_WLAN);
+
+       ah->modes_index = modesIndex;
+       ar9003_hw_override_ini(ah);
+       ar9003_hw_set_channel_regs(ah, chan);
+       ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+       ath9k_hw_apply_txpower(ah, chan, false);
+
+       if (AR_SREV_9462(ah)) {
+               if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+                               AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
+                       ah->enabled_cals |= TX_IQ_CAL;
+               else
+                       ah->enabled_cals &= ~TX_IQ_CAL;
+
+               if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
+                       ah->enabled_cals |= TX_CL_CAL;
+               else
+                       ah->enabled_cals &= ~TX_CL_CAL;
+       }
+
+       return 0;
+}
+
+static void ar9003_hw_set_rfmode(struct ath_hw *ah,
+                                struct ath9k_channel *chan)
+{
+       u32 rfMode = 0;
+
+       if (chan == NULL)
+               return;
+
+       rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
+               ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+
+       if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+               rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
+
+       REG_WRITE(ah, AR_PHY_MODE, rfMode);
+}
+
+static void ar9003_hw_mark_phy_inactive(struct ath_hw *ah)
+{
+       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+}
+
+static void ar9003_hw_set_delta_slope(struct ath_hw *ah,
+                                     struct ath9k_channel *chan)
+{
+       u32 coef_scaled, ds_coef_exp, ds_coef_man;
+       u32 clockMhzScaled = 0x64000000;
+       struct chan_centers centers;
+
+       /*
+        * half and quarter rate can divide the scaled clock by 2 or 4
+        * scale for selected channel bandwidth
+        */
+       if (IS_CHAN_HALF_RATE(chan))
+               clockMhzScaled = clockMhzScaled >> 1;
+       else if (IS_CHAN_QUARTER_RATE(chan))
+               clockMhzScaled = clockMhzScaled >> 2;
+
+       /*
+        * ALGO -> coef = 1e8/fcarrier*fclock/40;
+        * scaled coef to provide precision for this floating calculation
+        */
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       coef_scaled = clockMhzScaled / centers.synth_center;
+
+       ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+                                     &ds_coef_exp);
+
+       REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+                     AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
+       REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+                     AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
+
+       /*
+        * For Short GI,
+        * scaled coeff is 9/10 that of normal coeff
+        */
+       coef_scaled = (9 * coef_scaled) / 10;
+
+       ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+                                     &ds_coef_exp);
+
+       /* for short gi */
+       REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA,
+                     AR_PHY_SGI_DSC_MAN, ds_coef_man);
+       REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA,
+                     AR_PHY_SGI_DSC_EXP, ds_coef_exp);
+}
+
+static bool ar9003_hw_rfbus_req(struct ath_hw *ah)
+{
+       REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
+       return ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
+                            AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT);
+}
+
+/*
+ * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN).
+ * Read the phy active delay register. Value is in 100ns increments.
+ */
+static void ar9003_hw_rfbus_done(struct ath_hw *ah)
+{
+       u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_B(ah->curchan))
+               synthDelay = (4 * synthDelay) / 22;
+       else
+               synthDelay /= 10;
+
+       udelay(synthDelay + BASE_ACTIVATE_DELAY);
+
+       REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+}
+
+static bool ar9003_hw_ani_control(struct ath_hw *ah,
+                                 enum ath9k_ani_cmd cmd, int param)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_channel *chan = ah->curchan;
+       struct ar5416AniState *aniState = &chan->ani;
+       s32 value, value2;
+
+       switch (cmd & ah->ani_function) {
+       case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+               /*
+                * on == 1 means ofdm weak signal detection is ON
+                * on == 1 is the default, for less noise immunity
+                *
+                * on == 0 means ofdm weak signal detection is OFF
+                * on == 0 means more noise imm
+                */
+               u32 on = param ? 1 : 0;
+               if (on)
+                       REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+                                   AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+               else
+                       REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+                                   AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+               if (on != aniState->ofdmWeakSigDetect) {
+                       ath_dbg(common, ANI,
+                               "** ch %d: ofdm weak signal: %s=>%s\n",
+                               chan->channel,
+                               aniState->ofdmWeakSigDetect ?
+                               "on" : "off",
+                               on ? "on" : "off");
+                       if (on)
+                               ah->stats.ast_ani_ofdmon++;
+                       else
+                               ah->stats.ast_ani_ofdmoff++;
+                       aniState->ofdmWeakSigDetect = on;
+               }
+               break;
+       }
+       case ATH9K_ANI_FIRSTEP_LEVEL:{
+               u32 level = param;
+
+               if (level >= ARRAY_SIZE(firstep_table)) {
+                       ath_dbg(common, ANI,
+                               "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n",
+                               level, ARRAY_SIZE(firstep_table));
+                       return false;
+               }
+
+               /*
+                * make register setting relative to default
+                * from INI file & cap value
+                */
+               value = firstep_table[level] -
+                       firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
+                       aniState->iniDef.firstep;
+               if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+                       value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+               if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+                       value = ATH9K_SIG_FIRSTEP_SETTING_MAX;
+               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                             AR_PHY_FIND_SIG_FIRSTEP,
+                             value);
+               /*
+                * we need to set first step low register too
+                * make register setting relative to default
+                * from INI file & cap value
+                */
+               value2 = firstep_table[level] -
+                        firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
+                        aniState->iniDef.firstepLow;
+               if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+                       value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+               if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+                       value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX;
+
+               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
+                             AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2);
+
+               if (level != aniState->firstepLevel) {
+                       ath_dbg(common, ANI,
+                               "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",
+                               chan->channel,
+                               aniState->firstepLevel,
+                               level,
+                               ATH9K_ANI_FIRSTEP_LVL,
+                               value,
+                               aniState->iniDef.firstep);
+                       ath_dbg(common, ANI,
+                               "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n",
+                               chan->channel,
+                               aniState->firstepLevel,
+                               level,
+                               ATH9K_ANI_FIRSTEP_LVL,
+                               value2,
+                               aniState->iniDef.firstepLow);
+                       if (level > aniState->firstepLevel)
+                               ah->stats.ast_ani_stepup++;
+                       else if (level < aniState->firstepLevel)
+                               ah->stats.ast_ani_stepdown++;
+                       aniState->firstepLevel = level;
+               }
+               break;
+       }
+       case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+               u32 level = param;
+
+               if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
+                       ath_dbg(common, ANI,
+                               "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n",
+                               level, ARRAY_SIZE(cycpwrThr1_table));
+                       return false;
+               }
+               /*
+                * make register setting relative to default
+                * from INI file & cap value
+                */
+               value = cycpwrThr1_table[level] -
+                       cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
+                       aniState->iniDef.cycpwrThr1;
+               if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+                       value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+               if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+                       value = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
+               REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+                             AR_PHY_TIMING5_CYCPWR_THR1,
+                             value);
+
+               /*
+                * set AR_PHY_EXT_CCA for extension channel
+                * make register setting relative to default
+                * from INI file & cap value
+                */
+               value2 = cycpwrThr1_table[level] -
+                        cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
+                        aniState->iniDef.cycpwrThr1Ext;
+               if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+                       value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+               if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+                       value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
+               REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+                             AR_PHY_EXT_CYCPWR_THR1, value2);
+
+               if (level != aniState->spurImmunityLevel) {
+                       ath_dbg(common, ANI,
+                               "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n",
+                               chan->channel,
+                               aniState->spurImmunityLevel,
+                               level,
+                               ATH9K_ANI_SPUR_IMMUNE_LVL,
+                               value,
+                               aniState->iniDef.cycpwrThr1);
+                       ath_dbg(common, ANI,
+                               "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n",
+                               chan->channel,
+                               aniState->spurImmunityLevel,
+                               level,
+                               ATH9K_ANI_SPUR_IMMUNE_LVL,
+                               value2,
+                               aniState->iniDef.cycpwrThr1Ext);
+                       if (level > aniState->spurImmunityLevel)
+                               ah->stats.ast_ani_spurup++;
+                       else if (level < aniState->spurImmunityLevel)
+                               ah->stats.ast_ani_spurdown++;
+                       aniState->spurImmunityLevel = level;
+               }
+               break;
+       }
+       case ATH9K_ANI_MRC_CCK:{
+               /*
+                * is_on == 1 means MRC CCK ON (default, less noise imm)
+                * is_on == 0 means MRC CCK is OFF (more noise imm)
+                */
+               bool is_on = param ? 1 : 0;
+               REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
+                             AR_PHY_MRC_CCK_ENABLE, is_on);
+               REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
+                             AR_PHY_MRC_CCK_MUX_REG, is_on);
+               if (is_on != aniState->mrcCCK) {
+                       ath_dbg(common, ANI, "** ch %d: MRC CCK: %s=>%s\n",
+                               chan->channel,
+                               aniState->mrcCCK ? "on" : "off",
+                               is_on ? "on" : "off");
+               if (is_on)
+                       ah->stats.ast_ani_ccklow++;
+               else
+                       ah->stats.ast_ani_cckhigh++;
+               aniState->mrcCCK = is_on;
+               }
+       break;
+       }
+       case ATH9K_ANI_PRESENT:
+               break;
+       default:
+               ath_dbg(common, ANI, "invalid cmd %u\n", cmd);
+               return false;
+       }
+
+       ath_dbg(common, ANI,
+               "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
+               aniState->spurImmunityLevel,
+               aniState->ofdmWeakSigDetect ? "on" : "off",
+               aniState->firstepLevel,
+               aniState->mrcCCK ? "on" : "off",
+               aniState->listenTime,
+               aniState->ofdmPhyErrCount,
+               aniState->cckPhyErrCount);
+       return true;
+}
+
+static void ar9003_hw_do_getnf(struct ath_hw *ah,
+                             int16_t nfarray[NUM_NF_READINGS])
+{
+#define AR_PHY_CH_MINCCA_PWR   0x1FF00000
+#define AR_PHY_CH_MINCCA_PWR_S 20
+#define AR_PHY_CH_EXT_MINCCA_PWR 0x01FF0000
+#define AR_PHY_CH_EXT_MINCCA_PWR_S 16
+
+       int16_t nf;
+       int i;
+
+       for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+               if (ah->rxchainmask & BIT(i)) {
+                       nf = MS(REG_READ(ah, ah->nf_regs[i]),
+                                        AR_PHY_CH_MINCCA_PWR);
+                       nfarray[i] = sign_extend32(nf, 8);
+
+                       if (IS_CHAN_HT40(ah->curchan)) {
+                               u8 ext_idx = AR9300_MAX_CHAINS + i;
+
+                               nf = MS(REG_READ(ah, ah->nf_regs[ext_idx]),
+                                                AR_PHY_CH_EXT_MINCCA_PWR);
+                               nfarray[ext_idx] = sign_extend32(nf, 8);
+                       }
+               }
+       }
+}
+
+static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
+{
+       ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ;
+       ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ;
+       ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
+       ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ;
+       ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ;
+       ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ;
+
+       if (AR_SREV_9330(ah))
+               ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9330_2GHZ;
+
+       if (AR_SREV_9462(ah)) {
+               ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9462_2GHZ;
+               ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9462_2GHZ;
+               ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9462_5GHZ;
+               ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9462_5GHZ;
+       }
+}
+
+/*
+ * Initialize the ANI register values with default (ini) values.
+ * This routine is called during a (full) hardware reset after
+ * all the registers are initialised from the INI.
+ */
+static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
+{
+       struct ar5416AniState *aniState;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_channel *chan = ah->curchan;
+       struct ath9k_ani_default *iniDef;
+       u32 val;
+
+       aniState = &ah->curchan->ani;
+       iniDef = &aniState->iniDef;
+
+       ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
+               ah->hw_version.macVersion,
+               ah->hw_version.macRev,
+               ah->opmode,
+               chan->channel,
+               chan->channelFlags);
+
+       val = REG_READ(ah, AR_PHY_SFCORR);
+       iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
+       iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH);
+       iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR);
+
+       val = REG_READ(ah, AR_PHY_SFCORR_LOW);
+       iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW);
+       iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW);
+       iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW);
+
+       val = REG_READ(ah, AR_PHY_SFCORR_EXT);
+       iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH);
+       iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH);
+       iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW);
+       iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW);
+       iniDef->firstep = REG_READ_FIELD(ah,
+                                        AR_PHY_FIND_SIG,
+                                        AR_PHY_FIND_SIG_FIRSTEP);
+       iniDef->firstepLow = REG_READ_FIELD(ah,
+                                           AR_PHY_FIND_SIG_LOW,
+                                           AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW);
+       iniDef->cycpwrThr1 = REG_READ_FIELD(ah,
+                                           AR_PHY_TIMING5,
+                                           AR_PHY_TIMING5_CYCPWR_THR1);
+       iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah,
+                                              AR_PHY_EXT_CCA,
+                                              AR_PHY_EXT_CYCPWR_THR1);
+
+       /* these levels just got reset to defaults by the INI */
+       aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
+       aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
+       aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
+       aniState->mrcCCK = true;
+}
+
+static void ar9003_hw_set_radar_params(struct ath_hw *ah,
+                                      struct ath_hw_radar_conf *conf)
+{
+       u32 radar_0 = 0, radar_1 = 0;
+
+       if (!conf) {
+               REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
+               return;
+       }
+
+       radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA;
+       radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR);
+       radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI);
+       radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT);
+       radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
+       radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
+
+       radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
+       radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
+       radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
+       radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH);
+       radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH);
+
+       REG_WRITE(ah, AR_PHY_RADAR_0, radar_0);
+       REG_WRITE(ah, AR_PHY_RADAR_1, radar_1);
+       if (conf->ext_channel)
+               REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+       else
+               REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+}
+
+static void ar9003_hw_set_radar_conf(struct ath_hw *ah)
+{
+       struct ath_hw_radar_conf *conf = &ah->radar_conf;
+
+       conf->fir_power = -28;
+       conf->radar_rssi = 0;
+       conf->pulse_height = 10;
+       conf->pulse_rssi = 24;
+       conf->pulse_inband = 8;
+       conf->pulse_maxlen = 255;
+       conf->pulse_inband_step = 12;
+       conf->radar_inband = 8;
+}
+
+static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+                                  struct ath_hw_antcomb_conf *antconf)
+{
+       u32 regval;
+
+       regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+       antconf->main_lna_conf = (regval & AR_PHY_9485_ANT_DIV_MAIN_LNACONF) >>
+                                 AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S;
+       antconf->alt_lna_conf = (regval & AR_PHY_9485_ANT_DIV_ALT_LNACONF) >>
+                                AR_PHY_9485_ANT_DIV_ALT_LNACONF_S;
+       antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >>
+                                 AR_PHY_9485_ANT_FAST_DIV_BIAS_S;
+
+       if (AR_SREV_9330_11(ah)) {
+               antconf->lna1_lna2_delta = -9;
+               antconf->div_group = 1;
+       } else if (AR_SREV_9485(ah)) {
+               antconf->lna1_lna2_delta = -9;
+               antconf->div_group = 2;
+       } else {
+               antconf->lna1_lna2_delta = -3;
+               antconf->div_group = 0;
+       }
+}
+
+static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
+                                  struct ath_hw_antcomb_conf *antconf)
+{
+       u32 regval;
+
+       regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+       regval &= ~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF |
+                   AR_PHY_9485_ANT_DIV_ALT_LNACONF |
+                   AR_PHY_9485_ANT_FAST_DIV_BIAS |
+                   AR_PHY_9485_ANT_DIV_MAIN_GAINTB |
+                   AR_PHY_9485_ANT_DIV_ALT_GAINTB);
+       regval |= ((antconf->main_lna_conf <<
+                                       AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S)
+                  & AR_PHY_9485_ANT_DIV_MAIN_LNACONF);
+       regval |= ((antconf->alt_lna_conf << AR_PHY_9485_ANT_DIV_ALT_LNACONF_S)
+                  & AR_PHY_9485_ANT_DIV_ALT_LNACONF);
+       regval |= ((antconf->fast_div_bias << AR_PHY_9485_ANT_FAST_DIV_BIAS_S)
+                  & AR_PHY_9485_ANT_FAST_DIV_BIAS);
+       regval |= ((antconf->main_gaintb << AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S)
+                  & AR_PHY_9485_ANT_DIV_MAIN_GAINTB);
+       regval |= ((antconf->alt_gaintb << AR_PHY_9485_ANT_DIV_ALT_GAINTB_S)
+                  & AR_PHY_9485_ANT_DIV_ALT_GAINTB);
+
+       REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+}
+
+static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
+                                     struct ath9k_channel *chan,
+                                     u8 *ini_reloaded)
+{
+       unsigned int regWrites = 0;
+       u32 modesIndex;
+
+       switch (chan->chanmode) {
+       case CHANNEL_A:
+       case CHANNEL_A_HT20:
+               modesIndex = 1;
+               break;
+       case CHANNEL_A_HT40PLUS:
+       case CHANNEL_A_HT40MINUS:
+               modesIndex = 2;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_G_HT20:
+       case CHANNEL_B:
+               modesIndex = 4;
+               break;
+       case CHANNEL_G_HT40PLUS:
+       case CHANNEL_G_HT40MINUS:
+               modesIndex = 3;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if (modesIndex == ah->modes_index) {
+               *ini_reloaded = false;
+               goto set_rfmode;
+       }
+
+       ar9003_hw_prog_ini(ah, &ah->iniSOC[ATH_INI_POST], modesIndex);
+       ar9003_hw_prog_ini(ah, &ah->iniMac[ATH_INI_POST], modesIndex);
+       ar9003_hw_prog_ini(ah, &ah->iniBB[ATH_INI_POST], modesIndex);
+       ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex);
+       if (AR_SREV_9462_20(ah))
+               ar9003_hw_prog_ini(ah,
+                               &ah->ini_radio_post_sys2ant,
+                               modesIndex);
+
+       REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+
+       /*
+        * For 5GHz channels requiring Fast Clock, apply
+        * different modal values.
+        */
+       if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+               REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex, regWrites);
+
+       REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
+
+       ah->modes_index = modesIndex;
+       *ini_reloaded = true;
+
+set_rfmode:
+       ar9003_hw_set_rfmode(ah, chan);
+       return 0;
+}
+
+void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
+{
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+       struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+       static const u32 ar9300_cca_regs[6] = {
+               AR_PHY_CCA_0,
+               AR_PHY_CCA_1,
+               AR_PHY_CCA_2,
+               AR_PHY_EXT_CCA,
+               AR_PHY_EXT_CCA_1,
+               AR_PHY_EXT_CCA_2,
+       };
+
+       priv_ops->rf_set_freq = ar9003_hw_set_channel;
+       priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate;
+       priv_ops->compute_pll_control = ar9003_hw_compute_pll_control;
+       priv_ops->set_channel_regs = ar9003_hw_set_channel_regs;
+       priv_ops->init_bb = ar9003_hw_init_bb;
+       priv_ops->process_ini = ar9003_hw_process_ini;
+       priv_ops->set_rfmode = ar9003_hw_set_rfmode;
+       priv_ops->mark_phy_inactive = ar9003_hw_mark_phy_inactive;
+       priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
+       priv_ops->rfbus_req = ar9003_hw_rfbus_req;
+       priv_ops->rfbus_done = ar9003_hw_rfbus_done;
+       priv_ops->ani_control = ar9003_hw_ani_control;
+       priv_ops->do_getnf = ar9003_hw_do_getnf;
+       priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
+       priv_ops->set_radar_params = ar9003_hw_set_radar_params;
+       priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
+
+       ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
+       ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
+
+       ar9003_hw_set_nf_limits(ah);
+       ar9003_hw_set_radar_conf(ah);
+       memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs));
+}
+
+void ar9003_hw_bb_watchdog_config(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 idle_tmo_ms = ah->bb_watchdog_timeout_ms;
+       u32 val, idle_count;
+
+       if (!idle_tmo_ms) {
+               /* disable IRQ, disable chip-reset for BB panic */
+               REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_2,
+                         REG_READ(ah, AR_PHY_WATCHDOG_CTL_2) &
+                         ~(AR_PHY_WATCHDOG_RST_ENABLE |
+                           AR_PHY_WATCHDOG_IRQ_ENABLE));
+
+               /* disable watchdog in non-IDLE mode, disable in IDLE mode */
+               REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_1,
+                         REG_READ(ah, AR_PHY_WATCHDOG_CTL_1) &
+                         ~(AR_PHY_WATCHDOG_NON_IDLE_ENABLE |
+                           AR_PHY_WATCHDOG_IDLE_ENABLE));
+
+               ath_dbg(common, RESET, "Disabled BB Watchdog\n");
+               return;
+       }
+
+       /* enable IRQ, disable chip-reset for BB watchdog */
+       val = REG_READ(ah, AR_PHY_WATCHDOG_CTL_2) & AR_PHY_WATCHDOG_CNTL2_MASK;
+       REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_2,
+                 (val | AR_PHY_WATCHDOG_IRQ_ENABLE) &
+                 ~AR_PHY_WATCHDOG_RST_ENABLE);
+
+       /* bound limit to 10 secs */
+       if (idle_tmo_ms > 10000)
+               idle_tmo_ms = 10000;
+
+       /*
+        * The time unit for watchdog event is 2^15 44/88MHz cycles.
+        *
+        * For HT20 we have a time unit of 2^15/44 MHz = .74 ms per tick
+        * For HT40 we have a time unit of 2^15/88 MHz = .37 ms per tick
+        *
+        * Given we use fast clock now in 5 GHz, these time units should
+        * be common for both 2 GHz and 5 GHz.
+        */
+       idle_count = (100 * idle_tmo_ms) / 74;
+       if (ah->curchan && IS_CHAN_HT40(ah->curchan))
+               idle_count = (100 * idle_tmo_ms) / 37;
+
+       /*
+        * enable watchdog in non-IDLE mode, disable in IDLE mode,
+        * set idle time-out.
+        */
+       REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_1,
+                 AR_PHY_WATCHDOG_NON_IDLE_ENABLE |
+                 AR_PHY_WATCHDOG_IDLE_MASK |
+                 (AR_PHY_WATCHDOG_NON_IDLE_MASK & (idle_count << 2)));
+
+       ath_dbg(common, RESET, "Enabled BB Watchdog timeout (%u ms)\n",
+               idle_tmo_ms);
+}
+
+void ar9003_hw_bb_watchdog_read(struct ath_hw *ah)
+{
+       /*
+        * we want to avoid printing in ISR context so we save the
+        * watchdog status to be printed later in bottom half context.
+        */
+       ah->bb_watchdog_last_status = REG_READ(ah, AR_PHY_WATCHDOG_STATUS);
+
+       /*
+        * the watchdog timer should reset on status read but to be sure
+        * sure we write 0 to the watchdog status bit.
+        */
+       REG_WRITE(ah, AR_PHY_WATCHDOG_STATUS,
+                 ah->bb_watchdog_last_status & ~AR_PHY_WATCHDOG_STATUS_CLR);
+}
+
+void ath9k_btcoex_ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 status;
+
+       if (likely(!(common->debug_mask & ATH_DBG_RESET)))
+               return;
+
+       status = ah->bb_watchdog_last_status;
+       ath_dbg(common, RESET,
+               "\n==== BB update: BB status=0x%08x ====\n", status);
+       ath_dbg(common, RESET,
+               "** BB state: wd=%u det=%u rdar=%u rOFDM=%d rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n",
+               MS(status, AR_PHY_WATCHDOG_INFO),
+               MS(status, AR_PHY_WATCHDOG_DET_HANG),
+               MS(status, AR_PHY_WATCHDOG_RADAR_SM),
+               MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM),
+               MS(status, AR_PHY_WATCHDOG_RX_CCK_SM),
+               MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM),
+               MS(status, AR_PHY_WATCHDOG_TX_CCK_SM),
+               MS(status, AR_PHY_WATCHDOG_AGC_SM),
+               MS(status, AR_PHY_WATCHDOG_SRCH_SM));
+
+       ath_dbg(common, RESET, "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n",
+               REG_READ(ah, AR_PHY_WATCHDOG_CTL_1),
+               REG_READ(ah, AR_PHY_WATCHDOG_CTL_2));
+       ath_dbg(common, RESET, "** BB mode: BB_gen_controls=0x%08x **\n",
+               REG_READ(ah, AR_PHY_GEN_CTRL));
+
+#define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles)
+       if (common->cc_survey.cycles)
+               ath_dbg(common, RESET,
+                       "** BB busy times: rx_clear=%d%%, rx_frame=%d%%, tx_frame=%d%% **\n",
+                       PCT(rx_busy), PCT(rx_frame), PCT(tx_frame));
+
+       ath_dbg(common, RESET, "==== BB update: done ====\n\n");
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_hw_bb_watchdog_dbg_info);
+
+void ath9k_btcoex_ar9003_hw_disable_phy_restart(struct ath_hw *ah)
+{
+       u32 val;
+
+       /* While receiving unsupported rate frame rx state machine
+        * gets into a state 0xb and if phy_restart happens in that
+        * state, BB would go hang. If RXSM is in 0xb state after
+        * first bb panic, ensure to disable the phy_restart.
+        */
+       if (!((MS(ah->bb_watchdog_last_status,
+                 AR_PHY_WATCHDOG_RX_OFDM_SM) == 0xb) ||
+           ah->bb_hang_rx_ofdm))
+               return;
+
+       ah->bb_hang_rx_ofdm = true;
+       val = REG_READ(ah, AR_PHY_RESTART);
+       val &= ~AR_PHY_RESTART_ENA;
+
+       REG_WRITE(ah, AR_PHY_RESTART, val);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_hw_disable_phy_restart);
+
+void ath9k_btcoex_ar9003_hw_dump_ani_reg(struct ath_hw *ah)
+{
+       u32 reg;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       reg = REG_READ(ah, AR_PHY_FIND_SIG_LOW);
+       ath_dbg(common, RX_STUCK, "FIRStep Low = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW),
+                       MS(reg, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW));
+       reg = REG_READ(ah, AR_PHY_DESIRED_SZ);
+       ath_dbg(common, RX_STUCK, "Total Desired = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_DESIRED_SZ_TOT_DES),
+                       MS(reg, AR_PHY_DESIRED_SZ_TOT_DES));
+       ath_dbg(common, RX_STUCK, "ADC Desired = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_DESIRED_SZ_ADC),
+                       MS(reg, AR_PHY_DESIRED_SZ_ADC));
+       reg = REG_READ(ah, AR_PHY_FIND_SIG);
+       ath_dbg(common, RX_STUCK, "FIRStep = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_FIND_SIG_FIRSTEP),
+                       MS(reg, AR_PHY_FIND_SIG_FIRSTEP));
+       reg = REG_READ(ah, AR_PHY_AGC);
+       ath_dbg(common, RX_STUCK, "Coarse High = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_AGC_COARSE_HIGH),
+                       MS(reg, AR_PHY_AGC_COARSE_HIGH));
+       ath_dbg(common, RX_STUCK, "Coarse Low = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_AGC_COARSE_LOW),
+                       MS(reg, AR_PHY_AGC_COARSE_LOW));
+       ath_dbg(common, RX_STUCK, "Coarse Power Constant = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_AGC_COARSE_PWR_CONST),
+                       MS(reg, AR_PHY_AGC_COARSE_PWR_CONST));
+       reg = REG_READ(ah, AR_PHY_TIMING5);
+       ath_dbg(common, RX_STUCK, "Enable Cyclic Power Thresh = %d\n",
+                       MS(reg, AR_PHY_TIMING5_CYCPWR_THR1_ENABLE));
+       ath_dbg(common, RX_STUCK, "Cyclic Power Thresh = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_TIMING5_CYCPWR_THR1),
+                       MS(reg, AR_PHY_TIMING5_CYCPWR_THR1));
+       ath_dbg(common, RX_STUCK, "Cyclic Power Thresh 1A= 0x%x (%d)\n",
+                       MS(reg, AR_PHY_TIMING5_CYCPWR_THR1A),
+                       MS(reg, AR_PHY_TIMING5_CYCPWR_THR1A));
+       reg = REG_READ(ah, AR_PHY_DAG_CTRLCCK);
+       ath_dbg(common, RX_STUCK, "Barker RSSI Thresh Enable = %d\n",
+                       MS(reg, AR_PHY_DAG_CTRLCCK_EN_RSSI_THR));
+       ath_dbg(common, RX_STUCK, "Barker RSSI Thresh = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_DAG_CTRLCCK_RSSI_THR),
+                       MS(reg, AR_PHY_DAG_CTRLCCK_RSSI_THR));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_hw_dump_ani_reg);
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_phy.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_phy.h
new file mode 100644 (file)
index 0000000..d834d97
--- /dev/null
@@ -0,0 +1,1225 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef AR9003_PHY_H
+#define AR9003_PHY_H
+
+/*
+ * Channel Register Map
+ */
+#define AR_CHAN_BASE   0x9800
+
+#define AR_PHY_TIMING1      (AR_CHAN_BASE + 0x0)
+#define AR_PHY_TIMING2      (AR_CHAN_BASE + 0x4)
+#define AR_PHY_TIMING3      (AR_CHAN_BASE + 0x8)
+#define AR_PHY_TIMING4      (AR_CHAN_BASE + 0xc)
+#define AR_PHY_TIMING5      (AR_CHAN_BASE + 0x10)
+#define AR_PHY_TIMING6      (AR_CHAN_BASE + 0x14)
+#define AR_PHY_TIMING11     (AR_CHAN_BASE + 0x18)
+#define AR_PHY_SPUR_REG     (AR_CHAN_BASE + 0x1c)
+#define AR_PHY_RX_IQCAL_CORR_B0    (AR_CHAN_BASE + 0xdc)
+#define AR_PHY_TX_IQCAL_CONTROL_3  (AR_CHAN_BASE + 0xb0)
+
+#define AR_PHY_TIMING11_SPUR_FREQ_SD    0x3FF00000
+#define AR_PHY_TIMING11_SPUR_FREQ_SD_S  20
+
+#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF
+#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
+
+#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC 0x40000000
+#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC_S 30
+
+#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR 0x80000000
+#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR_S 31
+
+#define AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT         0x4000000
+#define AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT_S       26
+
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM                         0x20000     /* bins move with freq offset */
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM_S                       17
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH            0x000000FF
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S          0
+#define AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI                        0x00000100
+#define AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI_S                      8
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL                          0x03FC0000
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S                       18
+
+#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN   0x20000000
+#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN_S         29
+
+#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN   0x80000000
+#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN_S         31
+
+#define AR_PHY_FIND_SIG_LOW  (AR_CHAN_BASE + 0x20)
+
+#define AR_PHY_SFCORR           (AR_CHAN_BASE + 0x24)
+#define AR_PHY_SFCORR_LOW       (AR_CHAN_BASE + 0x28)
+#define AR_PHY_SFCORR_EXT       (AR_CHAN_BASE + 0x2c)
+
+#define AR_PHY_EXT_CCA              (AR_CHAN_BASE + 0x30)
+#define AR_PHY_RADAR_0              (AR_CHAN_BASE + 0x34)
+#define AR_PHY_RADAR_1              (AR_CHAN_BASE + 0x38)
+#define AR_PHY_RADAR_EXT            (AR_CHAN_BASE + 0x3c)
+#define AR_PHY_MULTICHAIN_CTRL      (AR_CHAN_BASE + 0x80)
+#define AR_PHY_PERCHAIN_CSD         (AR_CHAN_BASE + 0x84)
+
+#define AR_PHY_TX_PHASE_RAMP_0      (AR_CHAN_BASE + 0xd0)
+#define AR_PHY_ADC_GAIN_DC_CORR_0   (AR_CHAN_BASE + 0xd4)
+#define AR_PHY_IQ_ADC_MEAS_0_B0     (AR_CHAN_BASE + 0xc0)
+#define AR_PHY_IQ_ADC_MEAS_1_B0     (AR_CHAN_BASE + 0xc4)
+#define AR_PHY_IQ_ADC_MEAS_2_B0     (AR_CHAN_BASE + 0xc8)
+#define AR_PHY_IQ_ADC_MEAS_3_B0     (AR_CHAN_BASE + 0xcc)
+
+/* The following registers changed position from AR9300 1.0 to AR9300 2.0 */
+#define AR_PHY_TX_PHASE_RAMP_0_9300_10      (AR_CHAN_BASE + 0xd0 - 0x10)
+#define AR_PHY_ADC_GAIN_DC_CORR_0_9300_10   (AR_CHAN_BASE + 0xd4 - 0x10)
+#define AR_PHY_IQ_ADC_MEAS_0_B0_9300_10     (AR_CHAN_BASE + 0xc0 + 0x8)
+#define AR_PHY_IQ_ADC_MEAS_1_B0_9300_10     (AR_CHAN_BASE + 0xc4 + 0x8)
+#define AR_PHY_IQ_ADC_MEAS_2_B0_9300_10     (AR_CHAN_BASE + 0xc8 + 0x8)
+#define AR_PHY_IQ_ADC_MEAS_3_B0_9300_10     (AR_CHAN_BASE + 0xcc + 0x8)
+
+#define AR_PHY_TX_CRC               (AR_CHAN_BASE + 0xa0)
+#define AR_PHY_TST_DAC_CONST        (AR_CHAN_BASE + 0xa4)
+#define AR_PHY_SPUR_REPORT_0        (AR_CHAN_BASE + 0xa8)
+#define AR_PHY_CHAN_INFO_TAB_0      (AR_CHAN_BASE + 0x300)
+
+/*
+ * Channel Field Definitions
+ */
+#define AR_PHY_TIMING2_USE_FORCE_PPM    0x00001000
+#define AR_PHY_TIMING2_FORCE_PPM_VAL    0x00000fff
+#define AR_PHY_TIMING3_DSC_MAN      0xFFFE0000
+#define AR_PHY_TIMING3_DSC_MAN_S    17
+#define AR_PHY_TIMING3_DSC_EXP      0x0001E000
+#define AR_PHY_TIMING3_DSC_EXP_S    13
+#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX 0xF000
+#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX_S   12
+#define AR_PHY_TIMING4_DO_CAL    0x10000
+
+#define AR_PHY_TIMING4_ENABLE_PILOT_MASK        0x10000000
+#define AR_PHY_TIMING4_ENABLE_PILOT_MASK_S      28
+#define AR_PHY_TIMING4_ENABLE_CHAN_MASK         0x20000000
+#define AR_PHY_TIMING4_ENABLE_CHAN_MASK_S       29
+
+#define AR_PHY_TIMING4_ENABLE_SPUR_FILTER 0x40000000
+#define AR_PHY_TIMING4_ENABLE_SPUR_FILTER_S 30
+#define AR_PHY_TIMING4_ENABLE_SPUR_RSSI 0x80000000
+#define AR_PHY_TIMING4_ENABLE_SPUR_RSSI_S 31
+
+#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
+#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
+#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW  0x00000001
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW    0x00003F00
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S  8
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW      0x001FC000
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S    14
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW      0x0FE00000
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S    21
+#define AR_PHY_SFCORR_M2COUNT_THR    0x0000001F
+#define AR_PHY_SFCORR_M2COUNT_THR_S  0
+#define AR_PHY_SFCORR_M1_THRESH      0x00FE0000
+#define AR_PHY_SFCORR_M1_THRESH_S    17
+#define AR_PHY_SFCORR_M2_THRESH      0x7F000000
+#define AR_PHY_SFCORR_M2_THRESH_S    24
+#define AR_PHY_SFCORR_EXT_M1_THRESH       0x0000007F
+#define AR_PHY_SFCORR_EXT_M1_THRESH_S     0
+#define AR_PHY_SFCORR_EXT_M2_THRESH       0x00003F80
+#define AR_PHY_SFCORR_EXT_M2_THRESH_S     7
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW   0x001FC000
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW   0x0FE00000
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
+#define AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD 0x10000000
+#define AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD_S 28
+#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S   28
+#define AR_PHY_EXT_CCA_THRESH62 0x007F0000
+#define AR_PHY_EXT_CCA_THRESH62_S       16
+#define AR_PHY_EXT_MINCCA_PWR   0x01FF0000
+#define AR_PHY_EXT_MINCCA_PWR_S 16
+#define AR_PHY_EXT_CYCPWR_THR1 0x0000FE00L
+#define AR_PHY_EXT_CYCPWR_THR1_S 9
+#define AR_PHY_TIMING5_CYCPWR_THR1  0x000000FE
+#define AR_PHY_TIMING5_CYCPWR_THR1_S    1
+#define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE  0x00000001
+#define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE_S    0
+#define AR_PHY_TIMING5_CYCPWR_THR1A  0x007F0000
+#define AR_PHY_TIMING5_CYCPWR_THR1A_S    16
+#define AR_PHY_TIMING5_RSSI_THR1A     (0x7F << 16)
+#define AR_PHY_TIMING5_RSSI_THR1A_S   16
+#define AR_PHY_TIMING5_RSSI_THR1A_ENA (0x1 << 15)
+#define AR_PHY_RADAR_0_ENA  0x00000001
+#define AR_PHY_RADAR_0_FFT_ENA  0x80000000
+#define AR_PHY_RADAR_0_INBAND   0x0000003e
+#define AR_PHY_RADAR_0_INBAND_S 1
+#define AR_PHY_RADAR_0_PRSSI    0x00000FC0
+#define AR_PHY_RADAR_0_PRSSI_S  6
+#define AR_PHY_RADAR_0_HEIGHT   0x0003F000
+#define AR_PHY_RADAR_0_HEIGHT_S 12
+#define AR_PHY_RADAR_0_RRSSI    0x00FC0000
+#define AR_PHY_RADAR_0_RRSSI_S  18
+#define AR_PHY_RADAR_0_FIRPWR   0x7F000000
+#define AR_PHY_RADAR_0_FIRPWR_S 24
+#define AR_PHY_RADAR_1_RELPWR_ENA       0x00800000
+#define AR_PHY_RADAR_1_USE_FIR128       0x00400000
+#define AR_PHY_RADAR_1_RELPWR_THRESH    0x003F0000
+#define AR_PHY_RADAR_1_RELPWR_THRESH_S  16
+#define AR_PHY_RADAR_1_BLOCK_CHECK      0x00008000
+#define AR_PHY_RADAR_1_MAX_RRSSI        0x00004000
+#define AR_PHY_RADAR_1_RELSTEP_CHECK    0x00002000
+#define AR_PHY_RADAR_1_RELSTEP_THRESH   0x00001F00
+#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
+#define AR_PHY_RADAR_1_MAXLEN           0x000000FF
+#define AR_PHY_RADAR_1_MAXLEN_S         0
+#define AR_PHY_RADAR_EXT_ENA            0x00004000
+#define AR_PHY_RADAR_DC_PWR_THRESH      0x007f8000
+#define AR_PHY_RADAR_DC_PWR_THRESH_S    15
+#define AR_PHY_RADAR_LB_DC_CAP          0x7f800000
+#define AR_PHY_RADAR_LB_DC_CAP_S        23
+#define AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW (0x3f << 6)
+#define AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW_S   6
+#define AR_PHY_FIND_SIG_LOW_FIRPWR      (0x7f << 12)
+#define AR_PHY_FIND_SIG_LOW_FIRPWR_S    12
+#define AR_PHY_FIND_SIG_LOW_FIRPWR_SIGN_BIT 19
+#define AR_PHY_FIND_SIG_LOW_RELSTEP     0x1f
+#define AR_PHY_FIND_SIG_LOW_RELSTEP_S   0
+#define AR_PHY_FIND_SIG_LOW_RELSTEP_SIGN_BIT 5
+#define AR_PHY_CHAN_INFO_TAB_S2_READ    0x00000008
+#define AR_PHY_CHAN_INFO_TAB_S2_READ_S           3
+#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF 0x0000007F
+#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF_S   0
+#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF 0x00003F80
+#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF_S   7
+#define AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE   0x00004000
+#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF   0x003f8000
+#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF_S 15
+#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF   0x1fc00000
+#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF_S 22
+
+/*
+ * MRC Register Map
+ */
+#define AR_MRC_BASE    0x9c00
+
+#define AR_PHY_TIMING_3A       (AR_MRC_BASE + 0x0)
+#define AR_PHY_LDPC_CNTL1      (AR_MRC_BASE + 0x4)
+#define AR_PHY_LDPC_CNTL2      (AR_MRC_BASE + 0x8)
+#define AR_PHY_PILOT_SPUR_MASK (AR_MRC_BASE + 0xc)
+#define AR_PHY_CHAN_SPUR_MASK  (AR_MRC_BASE + 0x10)
+#define AR_PHY_SGI_DELTA       (AR_MRC_BASE + 0x14)
+#define AR_PHY_ML_CNTL_1       (AR_MRC_BASE + 0x18)
+#define AR_PHY_ML_CNTL_2       (AR_MRC_BASE + 0x1c)
+#define AR_PHY_TST_ADC         (AR_MRC_BASE + 0x20)
+
+#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A              0x00000FE0
+#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A_S    5
+#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A                  0x1F
+#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A_S                0
+
+#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A        0x00000FE0
+#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A_S      5
+#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A            0x1F
+#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A_S         0
+
+/*
+ * MRC Feild Definitions
+ */
+#define AR_PHY_SGI_DSC_MAN   0x0007FFF0
+#define AR_PHY_SGI_DSC_MAN_S 4
+#define AR_PHY_SGI_DSC_EXP   0x0000000F
+#define AR_PHY_SGI_DSC_EXP_S 0
+/*
+ * BBB Register Map
+ */
+#define AR_BBB_BASE    0x9d00
+
+/*
+ * AGC Register Map
+ */
+#define AR_AGC_BASE    0x9e00
+
+#define AR_PHY_SETTLING         (AR_AGC_BASE + 0x0)
+#define AR_PHY_FORCEMAX_GAINS_0 (AR_AGC_BASE + 0x4)
+#define AR_PHY_GAINS_MINOFF0    (AR_AGC_BASE + 0x8)
+#define AR_PHY_DESIRED_SZ       (AR_AGC_BASE + 0xc)
+#define AR_PHY_FIND_SIG         (AR_AGC_BASE + 0x10)
+#define AR_PHY_AGC              (AR_AGC_BASE + 0x14)
+#define AR_PHY_EXT_ATTEN_CTL_0  (AR_AGC_BASE + 0x18)
+#define AR_PHY_CCA_0            (AR_AGC_BASE + 0x1c)
+#define AR_PHY_EXT_CCA0         (AR_AGC_BASE + 0x20)
+#define AR_PHY_RESTART          (AR_AGC_BASE + 0x24)
+
+/*
+ * Antenna Diversity  settings
+ */
+#define AR_PHY_MC_GAIN_CTRL     (AR_AGC_BASE + 0x28)
+#define AR_ANT_DIV_CTRL_ALL    0x7e000000
+#define AR_ANT_DIV_CTRL_ALL_S  25
+#define AR_ANT_DIV_ENABLE      0x1000000
+#define AR_ANT_DIV_ENABLE_S    24
+
+
+#define AR_PHY_9485_ANT_FAST_DIV_BIAS                  0x00007e00
+#define AR_PHY_9485_ANT_FAST_DIV_BIAS_S                  9
+#define AR_PHY_9485_ANT_DIV_LNADIV                     0x01000000
+#define AR_PHY_9485_ANT_DIV_LNADIV_S                   24
+#define AR_PHY_9485_ANT_DIV_ALT_LNACONF                        0x06000000
+#define AR_PHY_9485_ANT_DIV_ALT_LNACONF_S              25
+#define AR_PHY_9485_ANT_DIV_MAIN_LNACONF               0x18000000
+#define AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S             27
+#define AR_PHY_9485_ANT_DIV_ALT_GAINTB                 0x20000000
+#define AR_PHY_9485_ANT_DIV_ALT_GAINTB_S               29
+#define AR_PHY_9485_ANT_DIV_MAIN_GAINTB                        0x40000000
+#define AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S              30
+
+#define AR_PHY_9485_ANT_DIV_LNA1_MINUS_LNA2            0x0
+#define AR_PHY_9485_ANT_DIV_LNA2                       0x1
+#define AR_PHY_9485_ANT_DIV_LNA1                       0x2
+#define AR_PHY_9485_ANT_DIV_LNA1_PLUS_LNA2             0x3
+
+#define AR_PHY_EXTCHN_PWRTHR1   (AR_AGC_BASE + 0x2c)
+#define AR_PHY_EXT_CHN_WIN      (AR_AGC_BASE + 0x30)
+#define AR_PHY_20_40_DET_THR    (AR_AGC_BASE + 0x34)
+#define AR_PHY_RIFS_SRCH        (AR_AGC_BASE + 0x38)
+#define AR_PHY_PEAK_DET_CTRL_1  (AR_AGC_BASE + 0x3c)
+#define AR_PHY_PEAK_DET_CTRL_2  (AR_AGC_BASE + 0x40)
+#define AR_PHY_RX_GAIN_BOUNDS_1 (AR_AGC_BASE + 0x44)
+#define AR_PHY_RX_GAIN_BOUNDS_2 (AR_AGC_BASE + 0x48)
+#define AR_PHY_RSSI_0           (AR_AGC_BASE + 0x180)
+#define AR_PHY_SPUR_CCK_REP0    (AR_AGC_BASE + 0x184)
+
+#define AR_PHY_CCK_DETECT       (AR_AGC_BASE + 0x1c0)
+#define AR_FAST_DIV_ENABLE     0x2000
+#define AR_FAST_DIV_ENABLE_S   13
+
+#define AR_PHY_DAG_CTRLCCK      (AR_AGC_BASE + 0x1c4)
+#define AR_PHY_IQCORR_CTRL_CCK  (AR_AGC_BASE + 0x1c8)
+
+#define AR_PHY_CCK_SPUR_MIT     (AR_AGC_BASE + 0x1cc)
+#define AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR                           0x000001fe
+#define AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR_S                                  1
+#define AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE                        0x60000000
+#define AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE_S                              29
+#define AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT                        0x00000001
+#define AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT_S                               0
+#define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ                           0x1ffffe00
+#define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ_S                                  9
+
+#define AR_PHY_MRC_CCK_CTRL         (AR_AGC_BASE + 0x1d0)
+#define AR_PHY_MRC_CCK_ENABLE       0x00000001
+#define AR_PHY_MRC_CCK_ENABLE_S              0
+#define AR_PHY_MRC_CCK_MUX_REG      0x00000002
+#define AR_PHY_MRC_CCK_MUX_REG_S             1
+
+#define AR_PHY_RX_OCGAIN        (AR_AGC_BASE + 0x200)
+
+#define AR_PHY_CCA_NOM_VAL_9300_2GHZ          -110
+#define AR_PHY_CCA_NOM_VAL_9300_5GHZ          -115
+#define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ     -125
+#define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ     -125
+#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -95
+#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -100
+
+#define AR_PHY_CCA_NOM_VAL_9462_2GHZ          -127
+#define AR_PHY_CCA_MIN_GOOD_VAL_9462_2GHZ     -127
+#define AR_PHY_CCA_NOM_VAL_9462_5GHZ          -127
+#define AR_PHY_CCA_MIN_GOOD_VAL_9462_5GHZ     -127
+
+#define AR_PHY_CCA_NOM_VAL_9330_2GHZ          -118
+
+/*
+ * AGC Field Definitions
+ */
+#define AR_PHY_EXT_ATTEN_CTL_RXTX_MARGIN    0x00FC0000
+#define AR_PHY_EXT_ATTEN_CTL_RXTX_MARGIN_S  18
+#define AR_PHY_EXT_ATTEN_CTL_BSW_MARGIN     0x00003C00
+#define AR_PHY_EXT_ATTEN_CTL_BSW_MARGIN_S   10
+#define AR_PHY_EXT_ATTEN_CTL_BSW_ATTEN      0x0000001F
+#define AR_PHY_EXT_ATTEN_CTL_BSW_ATTEN_S    0
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_MARGIN     0x003E0000
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_MARGIN_S   17
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN     0x0001F000
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN_S   12
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_DB         0x00000FC0
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_DB_S       6
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB         0x0000003F
+#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB_S       0
+#define AR_PHY_RXGAIN_TXRX_ATTEN    0x0003F000
+#define AR_PHY_RXGAIN_TXRX_ATTEN_S  12
+#define AR_PHY_RXGAIN_TXRX_RF_MAX   0x007C0000
+#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN    0x00003F80
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S  7
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN   0x001FC000
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
+#define AR_PHY_SETTLING_SWITCH  0x00003F80
+#define AR_PHY_SETTLING_SWITCH_S    7
+#define AR_PHY_DESIRED_SZ_ADC       0x000000FF
+#define AR_PHY_DESIRED_SZ_ADC_S     0
+#define AR_PHY_DESIRED_SZ_PGA       0x0000FF00
+#define AR_PHY_DESIRED_SZ_PGA_S     8
+#define AR_PHY_DESIRED_SZ_TOT_DES   0x0FF00000
+#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
+#define AR_PHY_MINCCA_PWR       0x1FF00000
+#define AR_PHY_MINCCA_PWR_S     20
+#define AR_PHY_CCA_THRESH62     0x0007F000
+#define AR_PHY_CCA_THRESH62_S   12
+#define AR9280_PHY_MINCCA_PWR       0x1FF00000
+#define AR9280_PHY_MINCCA_PWR_S     20
+#define AR9280_PHY_CCA_THRESH62     0x000FF000
+#define AR9280_PHY_CCA_THRESH62_S   12
+#define AR_PHY_EXT_CCA0_THRESH62    0x000000FF
+#define AR_PHY_EXT_CCA0_THRESH62_S  0
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK          0x0000003F
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S        0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME           0x00001FC0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S         6
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV    0x2000
+
+#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR  0x00000200
+#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR_S  9
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S   10
+
+#define AR_PHY_RIFS_INIT_DELAY         0x3ff0000
+#define AR_PHY_AGC_QUICK_DROP       0x03c00000
+#define AR_PHY_AGC_QUICK_DROP_S     22
+#define AR_PHY_AGC_COARSE_LOW       0x00007F80
+#define AR_PHY_AGC_COARSE_LOW_S     7
+#define AR_PHY_AGC_COARSE_HIGH      0x003F8000
+#define AR_PHY_AGC_COARSE_HIGH_S    15
+#define AR_PHY_AGC_COARSE_PWR_CONST 0x0000007F
+#define AR_PHY_AGC_COARSE_PWR_CONST_S   0
+#define AR_PHY_FIND_SIG_FIRSTEP  0x0003F000
+#define AR_PHY_FIND_SIG_FIRSTEP_S        12
+#define AR_PHY_FIND_SIG_FIRPWR   0x03FC0000
+#define AR_PHY_FIND_SIG_FIRPWR_S         18
+#define AR_PHY_FIND_SIG_FIRPWR_SIGN_BIT  25
+#define AR_PHY_FIND_SIG_RELPWR   (0x1f << 6)
+#define AR_PHY_FIND_SIG_RELPWR_S          6
+#define AR_PHY_FIND_SIG_RELPWR_SIGN_BIT  11
+#define AR_PHY_FIND_SIG_RELSTEP        0x1f
+#define AR_PHY_FIND_SIG_RELSTEP_S         0
+#define AR_PHY_FIND_SIG_RELSTEP_SIGN_BIT  5
+#define AR_PHY_RESTART_DIV_GC   0x001C0000
+#define AR_PHY_RESTART_DIV_GC_S 18
+#define AR_PHY_RESTART_ENA      0x01
+#define AR_PHY_DC_RESTART_DIS   0x40000000
+
+#define AR_PHY_TPC_OLPC_GAIN_DELTA_PAL_ON       0xFF000000
+#define AR_PHY_TPC_OLPC_GAIN_DELTA_PAL_ON_S     24
+#define AR_PHY_TPC_OLPC_GAIN_DELTA              0x00FF0000
+#define AR_PHY_TPC_OLPC_GAIN_DELTA_S            16
+
+#define AR_PHY_TPC_6_ERROR_EST_MODE             0x03000000
+#define AR_PHY_TPC_6_ERROR_EST_MODE_S           24
+
+/*
+ * SM Register Map
+ */
+#define AR_SM_BASE     0xa200
+
+#define AR_PHY_D2_CHIP_ID        (AR_SM_BASE + 0x0)
+#define AR_PHY_GEN_CTRL          (AR_SM_BASE + 0x4)
+#define AR_PHY_MODE              (AR_SM_BASE + 0x8)
+#define AR_PHY_ACTIVE            (AR_SM_BASE + 0xc)
+#define AR_PHY_SPUR_MASK_A       (AR_SM_BASE + 0x20)
+#define AR_PHY_SPUR_MASK_B       (AR_SM_BASE + 0x24)
+#define AR_PHY_SPECTRAL_SCAN     (AR_SM_BASE + 0x28)
+#define AR_PHY_RADAR_BW_FILTER   (AR_SM_BASE + 0x2c)
+#define AR_PHY_SEARCH_START_DELAY (AR_SM_BASE + 0x30)
+#define AR_PHY_MAX_RX_LEN        (AR_SM_BASE + 0x34)
+#define AR_PHY_FRAME_CTL         (AR_SM_BASE + 0x38)
+#define AR_PHY_RFBUS_REQ         (AR_SM_BASE + 0x3c)
+#define AR_PHY_RFBUS_GRANT       (AR_SM_BASE + 0x40)
+#define AR_PHY_RIFS              (AR_SM_BASE + 0x44)
+#define AR_PHY_RX_CLR_DELAY      (AR_SM_BASE + 0x50)
+#define AR_PHY_RX_DELAY          (AR_SM_BASE + 0x54)
+
+#define AR_PHY_XPA_TIMING_CTL    (AR_SM_BASE + 0x64)
+#define AR_PHY_MISC_PA_CTL       (AR_SM_BASE + 0x80)
+#define AR_PHY_SWITCH_CHAIN_0    (AR_SM_BASE + 0x84)
+#define AR_PHY_SWITCH_COM        (AR_SM_BASE + 0x88)
+#define AR_PHY_SWITCH_COM_2      (AR_SM_BASE + 0x8c)
+#define AR_PHY_RX_CHAINMASK      (AR_SM_BASE + 0xa0)
+#define AR_PHY_CAL_CHAINMASK     (AR_SM_BASE + 0xc0)
+#define AR_PHY_CALMODE           (AR_SM_BASE + 0xc8)
+#define AR_PHY_FCAL_1            (AR_SM_BASE + 0xcc)
+#define AR_PHY_FCAL_2_0          (AR_SM_BASE + 0xd0)
+#define AR_PHY_DFT_TONE_CTL_0    (AR_SM_BASE + 0xd4)
+#define AR_PHY_CL_CAL_CTL        (AR_SM_BASE + 0xd8)
+#define AR_PHY_CL_TAB_0          (AR_SM_BASE + 0x100)
+#define AR_PHY_SYNTH_CONTROL     (AR_SM_BASE + 0x140)
+#define AR_PHY_ADDAC_CLK_SEL     (AR_SM_BASE + 0x144)
+#define AR_PHY_PLL_CTL           (AR_SM_BASE + 0x148)
+#define AR_PHY_ANALOG_SWAP       (AR_SM_BASE + 0x14c)
+#define AR_PHY_ADDAC_PARA_CTL    (AR_SM_BASE + 0x150)
+#define AR_PHY_XPA_CFG           (AR_SM_BASE + 0x158)
+
+#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A           0x0001FC00
+#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A_S         10
+#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A                       0x3FF
+#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A_S                     0
+
+#define AR_PHY_TEST              (AR_SM_BASE + 0x160)
+
+#define AR_PHY_TEST_BBB_OBS_SEL       0x780000
+#define AR_PHY_TEST_BBB_OBS_SEL_S     19
+
+#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23
+#define AR_PHY_TEST_RX_OBS_SEL_BIT5   (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S)
+
+#define AR_PHY_TEST_CHAIN_SEL      0xC0000000
+#define AR_PHY_TEST_CHAIN_SEL_S    30
+
+#define AR_PHY_TEST_CTL_STATUS   (AR_SM_BASE + 0x164)
+#define AR_PHY_TEST_CTL_TSTDAC_EN         0x1
+#define AR_PHY_TEST_CTL_TSTDAC_EN_S       0
+#define AR_PHY_TEST_CTL_TX_OBS_SEL        0x1C
+#define AR_PHY_TEST_CTL_TX_OBS_SEL_S      2
+#define AR_PHY_TEST_CTL_TX_OBS_MUX_SEL    0x60
+#define AR_PHY_TEST_CTL_TX_OBS_MUX_SEL_S  5
+#define AR_PHY_TEST_CTL_TSTADC_EN         0x100
+#define AR_PHY_TEST_CTL_TSTADC_EN_S       8
+#define AR_PHY_TEST_CTL_RX_OBS_SEL        0x3C00
+#define AR_PHY_TEST_CTL_RX_OBS_SEL_S      10
+#define AR_PHY_TEST_CTL_DEBUGPORT_SEL    0xe0000000
+#define AR_PHY_TEST_CTL_DEBUGPORT_SEL_S          29
+
+
+#define AR_PHY_TSTDAC            (AR_SM_BASE + 0x168)
+
+#define AR_PHY_CHAN_STATUS       (AR_SM_BASE + 0x16c)
+
+#define AR_PHY_CHAN_INFO_MEMORY                                (AR_SM_BASE + 0x170)
+#define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ    0x00000008
+#define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ_S  3
+
+#define AR_PHY_CHNINFO_NOISEPWR  (AR_SM_BASE + 0x174)
+#define AR_PHY_CHNINFO_GAINDIFF  (AR_SM_BASE + 0x178)
+#define AR_PHY_CHNINFO_FINETIM   (AR_SM_BASE + 0x17c)
+#define AR_PHY_CHAN_INFO_GAIN_0  (AR_SM_BASE + 0x180)
+#define AR_PHY_SCRAMBLER_SEED    (AR_SM_BASE + 0x190)
+#define AR_PHY_CCK_TX_CTRL       (AR_SM_BASE + 0x194)
+
+#define AR_PHY_HEAVYCLIP_CTL     (AR_SM_BASE + 0x1a4)
+#define AR_PHY_HEAVYCLIP_20      (AR_SM_BASE + 0x1a8)
+#define AR_PHY_HEAVYCLIP_40      (AR_SM_BASE + 0x1ac)
+#define AR_PHY_ILLEGAL_TXRATE    (AR_SM_BASE + 0x1b0)
+
+#define AR_PHY_POWER_TX_RATE(_d) (AR_SM_BASE + 0x1c0 + ((_d) << 2))
+
+#define AR_PHY_PWRTX_MAX         (AR_SM_BASE + 0x1f0)
+#define AR_PHY_POWER_TX_SUB      (AR_SM_BASE + 0x1f4)
+
+#define AR_PHY_TPC_1                           (AR_SM_BASE + 0x1f8)
+#define AR_PHY_TPC_1_FORCED_DAC_GAIN           0x0000003e
+#define AR_PHY_TPC_1_FORCED_DAC_GAIN_S         1
+#define AR_PHY_TPC_1_FORCE_DAC_GAIN            0x00000001
+#define AR_PHY_TPC_1_FORCE_DAC_GAIN_S          0
+
+#define AR_PHY_TPC_4_B0                                (AR_SM_BASE + 0x204)
+#define AR_PHY_TPC_5_B0                                (AR_SM_BASE + 0x208)
+#define AR_PHY_TPC_6_B0                                (AR_SM_BASE + 0x20c)
+
+#define AR_PHY_TPC_11_B0                       (AR_SM_BASE + 0x220)
+#define AR_PHY_TPC_11_B1                       (AR_SM1_BASE + 0x220)
+#define AR_PHY_TPC_11_B2                       (AR_SM2_BASE + 0x220)
+#define AR_PHY_TPC_11_OLPC_GAIN_DELTA          0x00ff0000
+#define AR_PHY_TPC_11_OLPC_GAIN_DELTA_S                16
+
+#define AR_PHY_TPC_12                          (AR_SM_BASE + 0x224)
+#define AR_PHY_TPC_12_DESIRED_SCALE_HT40_5     0x3e000000
+#define AR_PHY_TPC_12_DESIRED_SCALE_HT40_5_S   25
+
+#define AR_PHY_TPC_18                          (AR_SM_BASE + 0x23c)
+#define AR_PHY_TPC_18_THERM_CAL_VALUE           0x000000ff
+#define AR_PHY_TPC_18_THERM_CAL_VALUE_S         0
+#define AR_PHY_TPC_18_VOLT_CAL_VALUE           0x0000ff00
+#define AR_PHY_TPC_18_VOLT_CAL_VALUE_S         8
+
+#define AR_PHY_TPC_19                          (AR_SM_BASE + 0x240)
+#define AR_PHY_TPC_19_ALPHA_VOLT               0x001f0000
+#define AR_PHY_TPC_19_ALPHA_VOLT_S             16
+#define AR_PHY_TPC_19_ALPHA_THERM              0xff
+#define AR_PHY_TPC_19_ALPHA_THERM_S            0
+
+#define AR_PHY_TX_FORCED_GAIN                          (AR_SM_BASE + 0x258)
+#define AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN            0x00000001
+#define AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN_S          0
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN       0x0000000e
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN_S     1
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN       0x00000030
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN_S     4
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN         0x000003c0
+#define AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN_S       6
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA          0x00003c00
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA_S                10
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB          0x0003c000
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB_S                14
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC          0x003c0000
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC_S                18
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND          0x00c00000
+#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND_S                22
+#define AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL                0x01000000
+#define AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL_S      24
+
+
+#define AR_PHY_PDADC_TAB_0       (AR_SM_BASE + 0x280)
+
+#define AR_PHY_TXGAIN_TABLE      (AR_SM_BASE + 0x300)
+
+#define AR_PHY_TX_IQCAL_CONTROL_0   (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+                                                0x3c4 : 0x444))
+#define AR_PHY_TX_IQCAL_CONTROL_1   (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+                                                0x3c8 : 0x448))
+#define AR_PHY_TX_IQCAL_START       (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+                                                0x3c4 : 0x440))
+#define AR_PHY_TX_IQCAL_STATUS_B0   (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+                                                0x3f0 : 0x48c))
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i)    (AR_SM_BASE + \
+                                            (AR_SREV_9485(ah) ? \
+                                             0x3d0 : 0x450) + ((_i) << 2))
+#define AR_PHY_RTT_CTRL                        (AR_SM_BASE + 0x380)
+
+#define AR_PHY_WATCHDOG_STATUS      (AR_SM_BASE + 0x5c0)
+#define AR_PHY_WATCHDOG_CTL_1       (AR_SM_BASE + 0x5c4)
+#define AR_PHY_WATCHDOG_CTL_2       (AR_SM_BASE + 0x5c8)
+#define AR_PHY_WATCHDOG_CTL         (AR_SM_BASE + 0x5cc)
+#define AR_PHY_ONLY_WARMRESET       (AR_SM_BASE + 0x5d0)
+#define AR_PHY_ONLY_CTL             (AR_SM_BASE + 0x5d4)
+#define AR_PHY_ECO_CTRL             (AR_SM_BASE + 0x5dc)
+
+#define AR_PHY_BB_THERM_ADC_1                          (AR_SM_BASE + 0x248)
+#define AR_PHY_BB_THERM_ADC_1_INIT_THERM               0x000000ff
+#define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S             0
+
+#define AR_PHY_BB_THERM_ADC_4                          (AR_SM_BASE + 0x254)
+#define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE       0x000000ff
+#define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE_S     0
+#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE                0x0000ff00
+#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S      8
+
+/* AIC Registers */
+#define AR_PHY_AIC_CTRL_0_B0   (AR_SM_BASE + 0x4b0)
+#define AR_PHY_AIC_CTRL_1_B0   (AR_SM_BASE + 0x4b4)
+#define AR_PHY_AIC_CTRL_2_B0   (AR_SM_BASE + 0x4b8)
+#define AR_PHY_AIC_CTRL_3_B0   (AR_SM_BASE + 0x4bc)
+#define AR_PHY_AIC_STAT_0_B0   (AR_SM_BASE + 0x4c4))
+#define AR_PHY_AIC_STAT_1_B0   (AR_SM_BASE + 0x4c8))
+#define AR_PHY_AIC_CTRL_4_B0   (AR_SM_BASE + 0x4c0)
+#define AR_PHY_AIC_STAT_2_B0   (AR_SM_BASE + 0x4cc)
+
+#define AR_PHY_65NM_CH0_SYNTH4      0x1608c
+#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)
+#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1)
+#define AR_PHY_65NM_CH0_SYNTH7      0x16098
+#define AR_PHY_65NM_CH0_BIAS1       0x160c0
+#define AR_PHY_65NM_CH0_BIAS2       0x160c4
+#define AR_PHY_65NM_CH0_BIAS4       0x160cc
+#define AR_PHY_65NM_CH0_RXTX4       0x1610c
+
+#define AR_CH0_TOP     (AR_SREV_9300(ah) ? 0x16288 : \
+                               ((AR_SREV_9462(ah) ? 0x1628c : 0x16280)))
+#define AR_CH0_TOP_XPABIASLVL (0x300)
+#define AR_CH0_TOP_XPABIASLVL_S (8)
+
+#define AR_CH0_THERM   (AR_SREV_9300(ah) ? 0x16290 : \
+                               ((AR_SREV_9485(ah) ? 0x1628c : 0x16294)))
+#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
+#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
+#define AR_CH0_THERM_XPASHORT2GND 0x4
+#define AR_CH0_THERM_XPASHORT2GND_S 2
+
+#define AR_SWITCH_TABLE_COM_ALL (0xffff)
+#define AR_SWITCH_TABLE_COM_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_AR9462_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM_AR9462_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000)
+#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0)
+#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4)
+
+#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM2_ALL_S (0)
+
+#define AR_SWITCH_TABLE_ALL (0xfff)
+#define AR_SWITCH_TABLE_ALL_S (0)
+
+#define AR_PHY_65NM_CH0_THERM       (AR_SREV_9300(ah) ? 0x16290 :\
+                                       (AR_SREV_9462(ah) ? 0x16294 : 0x1628c))
+
+#define AR_PHY_65NM_CH0_THERM_LOCAL   0x80000000
+#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
+#define AR_PHY_65NM_CH0_THERM_START   0x20000000
+#define AR_PHY_65NM_CH0_THERM_START_S 29
+#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT   0x0000ff00
+#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8
+
+#define AR_PHY_65NM_CH0_RXTX1       0x16100
+#define AR_PHY_65NM_CH0_RXTX2       0x16104
+#define AR_PHY_65NM_CH1_RXTX1       0x16500
+#define AR_PHY_65NM_CH1_RXTX2       0x16504
+#define AR_PHY_65NM_CH2_RXTX1       0x16900
+#define AR_PHY_65NM_CH2_RXTX2       0x16904
+
+#define AR_CH0_TOP2            (AR_SREV_9300(ah) ? 0x1628c : \
+                                       (AR_SREV_9462(ah) ? 0x16290 : 0x16284))
+#define AR_CH0_TOP2_XPABIASLVL         0xf000
+#define AR_CH0_TOP2_XPABIASLVL_S       12
+
+#define AR_CH0_XTAL            (AR_SREV_9300(ah) ? 0x16294 : \
+                                       (AR_SREV_9462(ah) ? 0x16298 : 0x16290))
+#define AR_CH0_XTAL_CAPINDAC   0x7f000000
+#define AR_CH0_XTAL_CAPINDAC_S 24
+#define AR_CH0_XTAL_CAPOUTDAC  0x00fe0000
+#define AR_CH0_XTAL_CAPOUTDAC_S        17
+
+#define AR_PHY_PMU1            (AR_SREV_9462(ah) ? 0x16340 : 0x16c40)
+#define AR_PHY_PMU1_PWD                0x1
+#define AR_PHY_PMU1_PWD_S      0
+
+#define AR_PHY_PMU2            (AR_SREV_9462(ah) ? 0x16344 : 0x16c44)
+#define AR_PHY_PMU2_PGM                0x00200000
+#define AR_PHY_PMU2_PGM_S      21
+
+#define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT         0x00380000
+#define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT_S       19
+#define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT         0x00c00000
+#define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT_S       22
+#define AR_PHY_LNAGAIN_LONG_SHIFT              0xe0000000
+#define AR_PHY_LNAGAIN_LONG_SHIFT_S            29
+#define AR_PHY_MXRGAIN_LONG_SHIFT              0x03000000
+#define AR_PHY_MXRGAIN_LONG_SHIFT_S            24
+#define AR_PHY_VGAGAIN_LONG_SHIFT              0x1c000000
+#define AR_PHY_VGAGAIN_LONG_SHIFT_S            26
+#define AR_PHY_SCFIR_GAIN_LONG_SHIFT           0x00000001
+#define AR_PHY_SCFIR_GAIN_LONG_SHIFT_S         0
+#define AR_PHY_MANRXGAIN_LONG_SHIFT            0x00000002
+#define AR_PHY_MANRXGAIN_LONG_SHIFT_S          1
+
+/*
+ * SM Field Definitions
+ */
+#define AR_PHY_CL_CAL_ENABLE          0x00000002
+#define AR_PHY_PARALLEL_CAL_ENABLE    0x00000001
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE   0x00400000
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
+
+#define AR_PHY_ADDAC_PARACTL_OFF_PWDADC 0x00008000
+
+#define AR_PHY_FCAL20_CAP_STATUS_0    0x01f00000
+#define AR_PHY_FCAL20_CAP_STATUS_0_S  20
+
+#define AR_PHY_RFBUS_REQ_EN     0x00000001  /* request for RF bus */
+#define AR_PHY_RFBUS_GRANT_EN   0x00000001  /* RF bus granted */
+#define AR_PHY_GC_TURBO_MODE       0x00000001  /* set turbo mode bits */
+#define AR_PHY_GC_TURBO_SHORT      0x00000002  /* set short symbols to turbo mode setting */
+#define AR_PHY_GC_DYN2040_EN       0x00000004  /* enable dyn 20/40 mode */
+#define AR_PHY_GC_DYN2040_PRI_ONLY 0x00000008  /* dyn 20/40 - primary only */
+#define AR_PHY_GC_DYN2040_PRI_CH   0x00000010  /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/
+#define AR_PHY_GC_DYN2040_PRI_CH_S 4
+#define AR_PHY_GC_DYN2040_EXT_CH   0x00000020  /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */
+#define AR_PHY_GC_HT_EN            0x00000040  /* ht enable */
+#define AR_PHY_GC_SHORT_GI_40      0x00000080  /* allow short GI for HT 40 */
+#define AR_PHY_GC_WALSH            0x00000100  /* walsh spatial spreading for 2 chains,2 streams TX */
+#define AR_PHY_GC_SINGLE_HT_LTF1   0x00000200  /* single length (4us) 1st HT long training symbol */
+#define AR_PHY_GC_GF_DETECT_EN     0x00000400  /* enable Green Field detection. Only affects rx, not tx */
+#define AR_PHY_GC_ENABLE_DAC_FIFO  0x00000800  /* fifo between bb and dac */
+#define AR_PHY_RX_DELAY_DELAY      0x00003FFF  /* delay from wakeup to rx ena */
+
+#define AR_PHY_CALMODE_IQ           0x00000000
+#define AR_PHY_CALMODE_ADC_GAIN     0x00000001
+#define AR_PHY_CALMODE_ADC_DC_PER   0x00000002
+#define AR_PHY_CALMODE_ADC_DC_INIT  0x00000003
+#define AR_PHY_SWAP_ALT_CHAIN       0x00000040
+#define AR_PHY_MODE_OFDM            0x00000000
+#define AR_PHY_MODE_CCK             0x00000001
+#define AR_PHY_MODE_DYNAMIC         0x00000004
+#define AR_PHY_MODE_DYNAMIC_S       2
+#define AR_PHY_MODE_HALF            0x00000020
+#define AR_PHY_MODE_QUARTER         0x00000040
+#define AR_PHY_MAC_CLK_MODE         0x00000080
+#define AR_PHY_MODE_DYN_CCK_DISABLE 0x00000100
+#define AR_PHY_MODE_SVD_HALF        0x00000200
+#define AR_PHY_ACTIVE_EN    0x00000001
+#define AR_PHY_ACTIVE_DIS   0x00000000
+#define AR_PHY_FORCE_XPA_CFG    0x000000001
+#define AR_PHY_FORCE_XPA_CFG_S  0
+#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF    0xFF000000
+#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF_S  24
+#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF    0x00FF0000
+#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF_S  16
+#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON      0x0000FF00
+#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON_S    8
+#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON      0x000000FF
+#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON_S    0
+#define AR_PHY_TX_END_TO_A2_RX_ON       0x00FF0000
+#define AR_PHY_TX_END_TO_A2_RX_ON_S     16
+#define AR_PHY_TX_END_DATA_START  0x000000FF
+#define AR_PHY_TX_END_DATA_START_S  0
+#define AR_PHY_TX_END_PA_ON       0x0000FF00
+#define AR_PHY_TX_END_PA_ON_S       8
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP   0x0000000F
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S     0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1    0x000003F0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S  4
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2    0x0000FC00
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S  10
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3    0x003F0000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S  16
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4    0x0FC00000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S  22
+#define AR_PHY_TPCRG1_NUM_PD_GAIN   0x0000c000
+#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
+#define AR_PHY_TPCRG1_PD_GAIN_1    0x00030000
+#define AR_PHY_TPCRG1_PD_GAIN_1_S  16
+#define AR_PHY_TPCRG1_PD_GAIN_2    0x000C0000
+#define AR_PHY_TPCRG1_PD_GAIN_2_S  18
+#define AR_PHY_TPCRG1_PD_GAIN_3    0x00300000
+#define AR_PHY_TPCRG1_PD_GAIN_3_S  20
+#define AR_PHY_TPCGR1_FORCED_DAC_GAIN   0x0000003e
+#define AR_PHY_TPCGR1_FORCED_DAC_GAIN_S 1
+#define AR_PHY_TPCGR1_FORCE_DAC_GAIN    0x00000001
+#define AR_PHY_TXGAIN_FORCE               0x00000001
+#define AR_PHY_TXGAIN_FORCE_S            0
+#define AR_PHY_TXGAIN_FORCED_PADVGNRA     0x00003c00
+#define AR_PHY_TXGAIN_FORCED_PADVGNRA_S   10
+#define AR_PHY_TXGAIN_FORCED_PADVGNRB     0x0003c000
+#define AR_PHY_TXGAIN_FORCED_PADVGNRB_S   14
+#define AR_PHY_TXGAIN_FORCED_PADVGNRD     0x00c00000
+#define AR_PHY_TXGAIN_FORCED_PADVGNRD_S   22
+#define AR_PHY_TXGAIN_FORCED_TXMXRGAIN    0x000003c0
+#define AR_PHY_TXGAIN_FORCED_TXMXRGAIN_S  6
+#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN  0x0000000e
+#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN_S 1
+
+#define AR_PHY_POWER_TX_RATE1   0x9934
+#define AR_PHY_POWER_TX_RATE2   0x9938
+#define AR_PHY_POWER_TX_RATE_MAX    0x993c
+#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
+#define PHY_AGC_CLR             0x10000000
+#define RFSILENT_BB             0x00002000
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_MASK          0xFFF
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_SIGNED_BIT    0x800
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT         320
+#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK         0x0001
+#define AR_PHY_RX_DELAY_DELAY   0x00003FFF
+#define AR_PHY_CCK_TX_CTRL_JAPAN    0x00000010
+#define AR_PHY_SPECTRAL_SCAN_ENABLE         0x00000001
+#define AR_PHY_SPECTRAL_SCAN_ENABLE_S       0
+#define AR_PHY_SPECTRAL_SCAN_ACTIVE         0x00000002
+#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S       1
+#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD     0x000000F0
+#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S   4
+#define AR_PHY_SPECTRAL_SCAN_PERIOD         0x0000FF00
+#define AR_PHY_SPECTRAL_SCAN_PERIOD_S       8
+#define AR_PHY_SPECTRAL_SCAN_COUNT          0x00FF0000
+#define AR_PHY_SPECTRAL_SCAN_COUNT_S        16
+#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT   0x01000000
+#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24
+#define AR_PHY_CHANNEL_STATUS_RX_CLEAR      0x00000004
+#define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION     0x00000001
+#define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION_S   0
+#define AR_PHY_RTT_CTRL_RESTORE_MASK            0x0000007E
+#define AR_PHY_RTT_CTRL_RESTORE_MASK_S          1
+#define AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE     0x00000080
+#define AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE_S   7
+#define AR_PHY_RTT_SW_RTT_TABLE_ACCESS          0x00000001
+#define AR_PHY_RTT_SW_RTT_TABLE_ACCESS_S        0
+#define AR_PHY_RTT_SW_RTT_TABLE_WRITE           0x00000002
+#define AR_PHY_RTT_SW_RTT_TABLE_WRITE_S         1
+#define AR_PHY_RTT_SW_RTT_TABLE_ADDR            0x0000001C
+#define AR_PHY_RTT_SW_RTT_TABLE_ADDR_S          2
+#define AR_PHY_RTT_SW_RTT_TABLE_DATA            0xFFFFFFF0
+#define AR_PHY_RTT_SW_RTT_TABLE_DATA_S          4
+#define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL                   0x80000000
+#define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL_S                         31
+#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT             0x01fc0000
+#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S                   18
+#define AR_PHY_TX_IQCAL_START_DO_CAL       0x00000001
+#define AR_PHY_TX_IQCAL_START_DO_CAL_S     0
+
+#define AR_PHY_TX_IQCAL_STATUS_FAILED    0x00000001
+#define AR_PHY_CALIBRATED_GAINS_0       0x3e
+#define AR_PHY_CALIBRATED_GAINS_0_S     1
+
+#define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE      0x00003fff
+#define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE_S    0
+#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE      0x0fffc000
+#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S    14
+
+#define AR_PHY_65NM_CH0_RXTX4_THERM_ON          0x10000000
+#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S        28
+
+/*
+ * Channel 1 Register Map
+ */
+#define AR_CHAN1_BASE  0xa800
+
+#define AR_PHY_EXT_CCA_1            (AR_CHAN1_BASE + 0x30)
+#define AR_PHY_TX_PHASE_RAMP_1      (AR_CHAN1_BASE + 0xd0)
+#define AR_PHY_ADC_GAIN_DC_CORR_1   (AR_CHAN1_BASE + 0xd4)
+
+#define AR_PHY_SPUR_REPORT_1        (AR_CHAN1_BASE + 0xa8)
+#define AR_PHY_CHAN_INFO_TAB_1      (AR_CHAN1_BASE + 0x300)
+#define AR_PHY_RX_IQCAL_CORR_B1     (AR_CHAN1_BASE + 0xdc)
+
+/*
+ * Channel 1 Field Definitions
+ */
+#define AR_PHY_CH1_EXT_MINCCA_PWR   0x01FF0000
+#define AR_PHY_CH1_EXT_MINCCA_PWR_S 16
+
+/*
+ * AGC 1 Register Map
+ */
+#define AR_AGC1_BASE   0xae00
+
+#define AR_PHY_FORCEMAX_GAINS_1      (AR_AGC1_BASE + 0x4)
+#define AR_PHY_EXT_ATTEN_CTL_1       (AR_AGC1_BASE + 0x18)
+#define AR_PHY_CCA_1                 (AR_AGC1_BASE + 0x1c)
+#define AR_PHY_CCA_CTRL_1            (AR_AGC1_BASE + 0x20)
+#define AR_PHY_RSSI_1                (AR_AGC1_BASE + 0x180)
+#define AR_PHY_SPUR_CCK_REP_1        (AR_AGC1_BASE + 0x184)
+#define AR_PHY_RX_OCGAIN_2           (AR_AGC1_BASE + 0x200)
+
+/*
+ * AGC 1 Field Definitions
+ */
+#define AR_PHY_CH1_MINCCA_PWR   0x1FF00000
+#define AR_PHY_CH1_MINCCA_PWR_S 20
+
+/*
+ * SM 1 Register Map
+ */
+#define AR_SM1_BASE    0xb200
+
+#define AR_PHY_SWITCH_CHAIN_1   (AR_SM1_BASE + 0x84)
+#define AR_PHY_FCAL_2_1         (AR_SM1_BASE + 0xd0)
+#define AR_PHY_DFT_TONE_CTL_1   (AR_SM1_BASE + 0xd4)
+#define AR_PHY_CL_TAB_1         (AR_SM1_BASE + 0x100)
+#define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180)
+#define AR_PHY_TPC_4_B1         (AR_SM1_BASE + 0x204)
+#define AR_PHY_TPC_5_B1         (AR_SM1_BASE + 0x208)
+#define AR_PHY_TPC_6_B1         (AR_SM1_BASE + 0x20c)
+#define AR_PHY_TPC_11_B1        (AR_SM1_BASE + 0x220)
+#define AR_PHY_PDADC_TAB_1     (AR_SM1_BASE + (AR_SREV_AR9462(ah) ? \
+                                       0x280 : 0x240))
+#define AR_PHY_TPC_19_B1       (AR_SM1_BASE + 0x240)
+#define AR_PHY_TPC_19_B1_ALPHA_THERM           0xff
+#define AR_PHY_TPC_19_B1_ALPHA_THERM_S         0
+#define AR_PHY_TX_IQCAL_STATUS_B1   (AR_SM1_BASE + 0x48c)
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i)    (AR_SM1_BASE + 0x450 + ((_i) << 2))
+
+/* SM 1 AIC Registers */
+
+#define AR_PHY_AIC_CTRL_0_B1   (AR_SM1_BASE + 0x4b0)
+#define AR_PHY_AIC_CTRL_1_B1   (AR_SM1_BASE + 0x4b4)
+#define AR_PHY_AIC_CTRL_2_B1   (AR_SM1_BASE + 0x4b8)
+#define AR_PHY_AIC_STAT_0_B1   (AR_SM1_BASE + (AR_SREV_9462_10(ah) ? \
+                                       0x4c0 : 0x4c4))
+#define AR_PHY_AIC_STAT_1_B1   (AR_SM1_BASE + (AR_SREV_9462_10(ah) ? \
+                                       0x4c4 : 0x4c8))
+#define AR_PHY_AIC_CTRL_4_B1   (AR_SM1_BASE + 0x4c0)
+#define AR_PHY_AIC_STAT_2_B1   (AR_SM1_BASE + 0x4cc)
+
+#define AR_PHY_AIC_SRAM_ADDR_B1        (AR_SM1_BASE + 0x5f0)
+#define AR_PHY_AIC_SRAM_DATA_B1        (AR_SM1_BASE + 0x5f4)
+
+#define AR_PHY_RTT_TABLE_SW_INTF_B(i)  (0x384 + ((i) ? \
+                                       AR_SM1_BASE : AR_SM_BASE))
+#define AR_PHY_RTT_TABLE_SW_INTF_1_B(i)        (0x388 + ((i) ? \
+                                       AR_SM1_BASE : AR_SM_BASE))
+/*
+ * Channel 2 Register Map
+ */
+#define AR_CHAN2_BASE  0xb800
+
+#define AR_PHY_EXT_CCA_2            (AR_CHAN2_BASE + 0x30)
+#define AR_PHY_TX_PHASE_RAMP_2      (AR_CHAN2_BASE + 0xd0)
+#define AR_PHY_ADC_GAIN_DC_CORR_2   (AR_CHAN2_BASE + 0xd4)
+
+#define AR_PHY_SPUR_REPORT_2        (AR_CHAN2_BASE + 0xa8)
+#define AR_PHY_CHAN_INFO_TAB_2      (AR_CHAN2_BASE + 0x300)
+#define AR_PHY_RX_IQCAL_CORR_B2     (AR_CHAN2_BASE + 0xdc)
+
+/*
+ * Channel 2 Field Definitions
+ */
+#define AR_PHY_CH2_EXT_MINCCA_PWR   0x01FF0000
+#define AR_PHY_CH2_EXT_MINCCA_PWR_S 16
+/*
+ * AGC 2 Register Map
+ */
+#define AR_AGC2_BASE   0xbe00
+
+#define AR_PHY_FORCEMAX_GAINS_2      (AR_AGC2_BASE + 0x4)
+#define AR_PHY_EXT_ATTEN_CTL_2       (AR_AGC2_BASE + 0x18)
+#define AR_PHY_CCA_2                 (AR_AGC2_BASE + 0x1c)
+#define AR_PHY_CCA_CTRL_2            (AR_AGC2_BASE + 0x20)
+#define AR_PHY_RSSI_2                (AR_AGC2_BASE + 0x180)
+
+/*
+ * AGC 2 Field Definitions
+ */
+#define AR_PHY_CH2_MINCCA_PWR   0x1FF00000
+#define AR_PHY_CH2_MINCCA_PWR_S 20
+
+/*
+ * SM 2 Register Map
+ */
+#define AR_SM2_BASE    0xc200
+
+#define AR_PHY_SWITCH_CHAIN_2    (AR_SM2_BASE + 0x84)
+#define AR_PHY_FCAL_2_2          (AR_SM2_BASE + 0xd0)
+#define AR_PHY_DFT_TONE_CTL_2    (AR_SM2_BASE + 0xd4)
+#define AR_PHY_CL_TAB_2          (AR_SM2_BASE + 0x100)
+#define AR_PHY_CHAN_INFO_GAIN_2  (AR_SM2_BASE + 0x180)
+#define AR_PHY_TPC_4_B2          (AR_SM2_BASE + 0x204)
+#define AR_PHY_TPC_5_B2          (AR_SM2_BASE + 0x208)
+#define AR_PHY_TPC_6_B2          (AR_SM2_BASE + 0x20c)
+#define AR_PHY_TPC_11_B2         (AR_SM2_BASE + 0x220)
+#define AR_PHY_PDADC_TAB_2       (AR_SM2_BASE + 0x240)
+#define AR_PHY_TX_IQCAL_STATUS_B2   (AR_SM2_BASE + 0x48c)
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B2(_i)    (AR_SM2_BASE + 0x450 + ((_i) << 2))
+
+#define AR_PHY_TX_IQCAL_STATUS_B2_FAILED    0x00000001
+
+/*
+ * AGC 3 Register Map
+ */
+#define AR_AGC3_BASE   0xce00
+
+#define AR_PHY_RSSI_3            (AR_AGC3_BASE + 0x180)
+
+/* GLB Registers */
+#define AR_GLB_BASE    0x20000
+#define AR_GLB_GPIO_CONTROL    (AR_GLB_BASE)
+#define AR_PHY_GLB_CONTROL     (AR_GLB_BASE + 0x44)
+#define AR_GLB_SCRATCH(_ah)    (AR_GLB_BASE + \
+                                       (AR_SREV_9462_20(_ah) ? 0x4c : 0x50))
+#define AR_GLB_STATUS          (AR_GLB_BASE + 0x48)
+
+/*
+ * Misc helper defines
+ */
+#define AR_PHY_CHAIN_OFFSET     (AR_CHAN1_BASE - AR_CHAN_BASE)
+
+#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (AR_PHY_ADC_GAIN_DC_CORR_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_NEW_ADC_DC_GAIN_CORR_9300_10(_i) (AR_PHY_ADC_GAIN_DC_CORR_0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_SWITCH_CHAIN(_i)     (AR_PHY_SWITCH_CHAIN_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_EXT_ATTEN_CTL(_i)    (AR_PHY_EXT_ATTEN_CTL_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+
+#define AR_PHY_RXGAIN(_i)           (AR_PHY_FORCEMAX_GAINS_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_TPCRG5(_i)           (AR_PHY_TPC_5_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_PDADC_TAB(_i)        (AR_PHY_PDADC_TAB_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+
+#define AR_PHY_CAL_MEAS_0(_i)       (AR_PHY_IQ_ADC_MEAS_0_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_1(_i)       (AR_PHY_IQ_ADC_MEAS_1_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_2(_i)       (AR_PHY_IQ_ADC_MEAS_2_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_3(_i)       (AR_PHY_IQ_ADC_MEAS_3_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_0_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_0_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_1_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_1_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
+#define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
+
+#define AR_PHY_WATCHDOG_NON_IDLE_ENABLE    0x00000001
+#define AR_PHY_WATCHDOG_IDLE_ENABLE        0x00000002
+#define AR_PHY_WATCHDOG_IDLE_MASK          0xFFFF0000
+#define AR_PHY_WATCHDOG_NON_IDLE_MASK      0x0000FFFC
+
+#define AR_PHY_WATCHDOG_RST_ENABLE         0x00000002
+#define AR_PHY_WATCHDOG_IRQ_ENABLE         0x00000004
+#define AR_PHY_WATCHDOG_CNTL2_MASK         0xFFFFFFF9
+
+#define AR_PHY_WATCHDOG_INFO               0x00000007
+#define AR_PHY_WATCHDOG_INFO_S             0
+#define AR_PHY_WATCHDOG_DET_HANG           0x00000008
+#define AR_PHY_WATCHDOG_DET_HANG_S         3
+#define AR_PHY_WATCHDOG_RADAR_SM           0x000000F0
+#define AR_PHY_WATCHDOG_RADAR_SM_S         4
+#define AR_PHY_WATCHDOG_RX_OFDM_SM         0x00000F00
+#define AR_PHY_WATCHDOG_RX_OFDM_SM_S       8
+#define AR_PHY_WATCHDOG_RX_CCK_SM          0x0000F000
+#define AR_PHY_WATCHDOG_RX_CCK_SM_S        12
+#define AR_PHY_WATCHDOG_TX_OFDM_SM         0x000F0000
+#define AR_PHY_WATCHDOG_TX_OFDM_SM_S       16
+#define AR_PHY_WATCHDOG_TX_CCK_SM          0x00F00000
+#define AR_PHY_WATCHDOG_TX_CCK_SM_S        20
+#define AR_PHY_WATCHDOG_AGC_SM             0x0F000000
+#define AR_PHY_WATCHDOG_AGC_SM_S           24
+#define AR_PHY_WATCHDOG_SRCH_SM            0xF0000000
+#define AR_PHY_WATCHDOG_SRCH_SM_S          28
+
+#define AR_PHY_WATCHDOG_STATUS_CLR         0x00000008
+
+/*
+ * PAPRD registers
+ */
+#define AR_PHY_XPA_TIMING_CTL          (AR_SM_BASE + 0x64)
+
+#define AR_PHY_PAPRD_AM2AM             (AR_CHAN_BASE + 0xe4)
+#define AR_PHY_PAPRD_AM2AM_MASK                0x01ffffff
+#define AR_PHY_PAPRD_AM2AM_MASK_S      0
+
+#define AR_PHY_PAPRD_AM2PM             (AR_CHAN_BASE + 0xe8)
+#define AR_PHY_PAPRD_AM2PM_MASK                0x01ffffff
+#define AR_PHY_PAPRD_AM2PM_MASK_S      0
+
+#define AR_PHY_PAPRD_HT40              (AR_CHAN_BASE + 0xec)
+#define AR_PHY_PAPRD_HT40_MASK         0x01ffffff
+#define AR_PHY_PAPRD_HT40_MASK_S       0
+
+#define AR_PHY_PAPRD_CTRL0_B0                          (AR_CHAN_BASE + 0xf0)
+#define AR_PHY_PAPRD_CTRL0_B1                          (AR_CHAN1_BASE + 0xf0)
+#define AR_PHY_PAPRD_CTRL0_B2                          (AR_CHAN2_BASE + 0xf0)
+#define AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE                        0x00000001
+#define AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE_S              0
+#define AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK       0x00000002
+#define AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK_S     1
+#define AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH             0xf8000000
+#define AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH_S           27
+
+#define AR_PHY_PAPRD_CTRL1_B0                          (AR_CHAN_BASE + 0xf4)
+#define AR_PHY_PAPRD_CTRL1_B1                          (AR_CHAN1_BASE + 0xf4)
+#define AR_PHY_PAPRD_CTRL1_B2                          (AR_CHAN2_BASE + 0xf4)
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA                0x00000001
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA_S      0
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE       0x00000002
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE_S     1
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE       0x00000004
+#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE_S     2
+#define AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL    0x000001f8
+#define AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL_S  3
+#define AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK     0x0001fe00
+#define AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK_S   9
+#define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT                0x0ffe0000
+#define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT_S      17
+
+#define AR_PHY_PAPRD_TRAINER_CNTL1                             (AR_SM_BASE + \
+                                                                (AR_SREV_9485(ah) ? \
+                                                                 0x580 : 0x490))
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE    0x00000001
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE_S  0
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING      0x0000007e
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING_S    1
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE      0x00000100
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE_S    8
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE   0x00000200
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE_S 9
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE      0x00000400
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE_S    10
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE          0x00000800
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE_S                11
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP            0x0003f000
+#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP_S          12
+
+#define AR_PHY_PAPRD_TRAINER_CNTL2                             (AR_SM_BASE + \
+                                                                (AR_SREV_9485(ah) ? \
+                                                                 0x584 : 0x494))
+#define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN    0xFFFFFFFF
+#define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN_S  0
+
+#define AR_PHY_PAPRD_TRAINER_CNTL3                             (AR_SM_BASE + \
+                                                                (AR_SREV_9485(ah) ? \
+                                                                 0x588 : 0x498))
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE   0x0000003f
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE_S 0
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP         0x00000fc0
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP_S       6
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL   0x0001f000
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL_S 12
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES    0x000e0000
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES_S  17
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN    0x00f00000
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN_S  20
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN      0x0f000000
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN_S    24
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE    0x20000000
+#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE_S  29
+
+#define AR_PHY_PAPRD_TRAINER_CNTL4                             (AR_SM_BASE + \
+                                                                (AR_SREV_9485(ah) ? \
+                                                                 0x58c : 0x49c))
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES  0x03ff0000
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES_S        16
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA       0x0000f000
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA_S     12
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR           0x00000fff
+#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR_S         0
+
+#define AR_PHY_PAPRD_PRE_POST_SCALE_0_B0                       (AR_CHAN_BASE + 0x100)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_1_B0                       (AR_CHAN_BASE + 0x104)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_2_B0                       (AR_CHAN_BASE + 0x108)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_3_B0                       (AR_CHAN_BASE + 0x10c)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_4_B0                       (AR_CHAN_BASE + 0x110)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_5_B0                       (AR_CHAN_BASE + 0x114)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_6_B0                       (AR_CHAN_BASE + 0x118)
+#define AR_PHY_PAPRD_PRE_POST_SCALE_7_B0                       (AR_CHAN_BASE + 0x11c)
+#define AR_PHY_PAPRD_PRE_POST_SCALING                          0x3FFFF
+#define AR_PHY_PAPRD_PRE_POST_SCALING_S                                0
+
+#define AR_PHY_PAPRD_TRAINER_STAT1                             (AR_SM_BASE + 0x4a0)
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE            0x00000001
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE_S          0
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE      0x00000002
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE_S    1
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR              0x00000004
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR_S            2
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE          0x00000008
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE_S                3
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX           0x000001f0
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX_S         4
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR              0x0001fe00
+#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR_S            9
+
+#define AR_PHY_PAPRD_TRAINER_STAT2                             (AR_SM_BASE + 0x4a4)
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL              0x0000ffff
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL_S            0
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX            0x001f0000
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX_S          16
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX              0x00600000
+#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX_S            21
+
+#define AR_PHY_PAPRD_TRAINER_STAT3                             (AR_SM_BASE + 0x4a8)
+#define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT     0x000fffff
+#define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT_S   0
+
+#define AR_PHY_PAPRD_MEM_TAB_B0                        (AR_CHAN_BASE + 0x120)
+#define AR_PHY_PAPRD_MEM_TAB_B1                        (AR_CHAN1_BASE + 0x120)
+#define AR_PHY_PAPRD_MEM_TAB_B2                        (AR_CHAN2_BASE + 0x120)
+
+#define AR_PHY_PA_GAIN123_B0                   (AR_CHAN_BASE + 0xf8)
+#define AR_PHY_PA_GAIN123_B1                   (AR_CHAN1_BASE + 0xf8)
+#define AR_PHY_PA_GAIN123_B2                   (AR_CHAN2_BASE + 0xf8)
+#define AR_PHY_PA_GAIN123_PA_GAIN1             0x3FF
+#define AR_PHY_PA_GAIN123_PA_GAIN1_S           0
+
+#define AR_PHY_POWERTX_RATE5                   (AR_SM_BASE + 0x1d0)
+#define AR_PHY_POWERTX_RATE5_POWERTXHT20_0     0x3F
+#define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S   0
+
+#define AR_PHY_POWERTX_RATE6                   (AR_SM_BASE + 0x1d4)
+#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5     0x3F00
+#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5_S   8
+
+#define AR_PHY_POWERTX_RATE8                   (AR_SM_BASE + 0x1dc)
+#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5     0x3F00
+#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S   8
+
+#define AR_PHY_CL_TAB_CL_GAIN_MOD              0x1f
+#define AR_PHY_CL_TAB_CL_GAIN_MOD_S            0
+
+#endif  /* AR9003_PHY_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_rtt.c b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_rtt.c
new file mode 100644 (file)
index 0000000..d9c3b3e
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "ar9003_phy.h"
+#include "ar9003_rtt.h"
+
+#define RTT_RESTORE_TIMEOUT          1000
+#define RTT_ACCESS_TIMEOUT           100
+#define RTT_BAD_VALUE                0x0bad0bad
+
+/*
+ * RTT (Radio Retention Table) hardware implementation information
+ *
+ * There is an internal table (i.e. the rtt) for each chain (or bank).
+ * Each table contains 6 entries and each entry is corresponding to
+ * a specific calibration parameter as depicted below.
+ *  0~2 - DC offset DAC calibration: loop, low, high (offsetI/Q_...)
+ *  3   - Filter cal (filterfc)
+ *  4   - RX gain settings
+ *  5   - Peak detector offset calibration (agc_caldac)
+ */
+
+void ar9003_hw_rtt_enable(struct ath_hw *ah)
+{
+       REG_WRITE(ah, AR_PHY_RTT_CTRL, 1);
+}
+
+void ar9003_hw_rtt_disable(struct ath_hw *ah)
+{
+       REG_WRITE(ah, AR_PHY_RTT_CTRL, 0);
+}
+
+void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask)
+{
+       REG_RMW_FIELD(ah, AR_PHY_RTT_CTRL,
+                     AR_PHY_RTT_CTRL_RESTORE_MASK, rtt_mask);
+}
+
+bool ar9003_hw_rtt_force_restore(struct ath_hw *ah)
+{
+       if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_RTT_CTRL,
+                          AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE,
+                          0, RTT_RESTORE_TIMEOUT))
+               return false;
+
+       REG_RMW_FIELD(ah, AR_PHY_RTT_CTRL,
+                     AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE, 1);
+
+       if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_RTT_CTRL,
+                          AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE,
+                          0, RTT_RESTORE_TIMEOUT))
+               return false;
+
+       return true;
+}
+
+static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain,
+                                         u32 index, u32 data28)
+{
+       u32 val;
+
+       val = SM(data28, AR_PHY_RTT_SW_RTT_TABLE_DATA);
+       REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain), val);
+
+       val = SM(0, AR_PHY_RTT_SW_RTT_TABLE_ACCESS) |
+             SM(1, AR_PHY_RTT_SW_RTT_TABLE_WRITE) |
+             SM(index, AR_PHY_RTT_SW_RTT_TABLE_ADDR);
+       REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val);
+       udelay(1);
+
+       val |= SM(1, AR_PHY_RTT_SW_RTT_TABLE_ACCESS);
+       REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val);
+       udelay(1);
+
+       if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain),
+                          AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0,
+                          RTT_ACCESS_TIMEOUT))
+               return;
+
+       val &= ~SM(1, AR_PHY_RTT_SW_RTT_TABLE_WRITE);
+       REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val);
+       udelay(1);
+
+       ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain),
+                     AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0,
+                     RTT_ACCESS_TIMEOUT);
+}
+
+void ar9003_hw_rtt_load_hist(struct ath_hw *ah)
+{
+       int chain, i;
+
+       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+               if (!(ah->rxchainmask & (1 << chain)))
+                       continue;
+               for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) {
+                       ar9003_hw_rtt_load_hist_entry(ah, chain, i,
+                                             ah->caldata->rtt_table[chain][i]);
+                       ath_dbg(ath9k_hw_common(ah), CALIBRATE,
+                               "Load RTT value at idx %d, chain %d: 0x%x\n",
+                               i, chain, ah->caldata->rtt_table[chain][i]);
+               }
+       }
+}
+
+static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index)
+{
+       u32 val;
+
+       val = SM(0, AR_PHY_RTT_SW_RTT_TABLE_ACCESS) |
+             SM(0, AR_PHY_RTT_SW_RTT_TABLE_WRITE) |
+             SM(index, AR_PHY_RTT_SW_RTT_TABLE_ADDR);
+
+       REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val);
+       udelay(1);
+
+       val |= SM(1, AR_PHY_RTT_SW_RTT_TABLE_ACCESS);
+       REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val);
+       udelay(1);
+
+       if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain),
+                          AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0,
+                          RTT_ACCESS_TIMEOUT))
+               return RTT_BAD_VALUE;
+
+       val = MS(REG_READ(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain)),
+                AR_PHY_RTT_SW_RTT_TABLE_DATA);
+
+
+       return val;
+}
+
+void ar9003_hw_rtt_fill_hist(struct ath_hw *ah)
+{
+       int chain, i;
+
+       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+               if (!(ah->rxchainmask & (1 << chain)))
+                       continue;
+               for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) {
+                       ah->caldata->rtt_table[chain][i] =
+                               ar9003_hw_rtt_fill_hist_entry(ah, chain, i);
+                       ath_dbg(ath9k_hw_common(ah), CALIBRATE,
+                               "RTT value at idx %d, chain %d is: 0x%x\n",
+                               i, chain, ah->caldata->rtt_table[chain][i]);
+               }
+       }
+
+       ah->caldata->rtt_done = true;
+}
+
+void ar9003_hw_rtt_clear_hist(struct ath_hw *ah)
+{
+       int chain, i;
+
+       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+               if (!(ah->rxchainmask & (1 << chain)))
+                       continue;
+               for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++)
+                       ar9003_hw_rtt_load_hist_entry(ah, chain, i, 0);
+       }
+
+       if (ah->caldata)
+               ah->caldata->rtt_done = false;
+}
+
+bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       bool restore;
+
+       if (!ah->caldata)
+               return false;
+
+       if (!ah->caldata->rtt_done)
+               return false;
+
+       ar9003_hw_rtt_enable(ah);
+       ar9003_hw_rtt_set_mask(ah, 0x10);
+
+       if (!ath9k_hw_rfbus_req(ah)) {
+               ath_err(ath9k_hw_common(ah), "Could not stop baseband\n");
+               restore = false;
+               goto fail;
+       }
+
+       ar9003_hw_rtt_load_hist(ah);
+       restore = ar9003_hw_rtt_force_restore(ah);
+
+fail:
+       ath9k_hw_rfbus_done(ah);
+       ar9003_hw_rtt_disable(ah);
+       return restore;
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9003_rtt.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9003_rtt.h
new file mode 100644 (file)
index 0000000..a43b30d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef AR9003_RTT_H
+#define AR9003_RTT_H
+
+void ar9003_hw_rtt_enable(struct ath_hw *ah);
+void ar9003_hw_rtt_disable(struct ath_hw *ah);
+void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask);
+bool ar9003_hw_rtt_force_restore(struct ath_hw *ah);
+void ar9003_hw_rtt_load_hist(struct ath_hw *ah);
+void ar9003_hw_rtt_fill_hist(struct ath_hw *ah);
+void ar9003_hw_rtt_clear_hist(struct ath_hw *ah);
+bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan);
+
+#endif
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9330_1p1_initvals.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9330_1p1_initvals.h
new file mode 100644 (file)
index 0000000..aa40b6a
--- /dev/null
@@ -0,0 +1,1098 @@
+/*
+ * Copyright (c) 2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9330_1P1_H
+#define INITVALS_9330_1P1_H
+
+static const u32 ar9331_1p1_baseband_postamble[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+       {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+       {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+       {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+       {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+       {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+       {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p1[][5] = {
+       /*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+       {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+       {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+       {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+       {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+       {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+       {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+       {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p1[][5] = {
+       /*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+       {0x0000a2dc, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52},
+       {0x0000a2e0, 0xffb31c84, 0xffb31c84, 0xffb31c84, 0xffb31c84},
+       {0x0000a2e4, 0xff43e000, 0xff43e000, 0xff43e000, 0xff43e000},
+       {0x0000a2e8, 0xfffc0000, 0xfffc0000, 0xfffc0000, 0xfffc0000},
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x3d001620, 0x3d001620},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x3f001621, 0x3f001621},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x42001640, 0x42001640},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x44001641, 0x44001641},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x46001642, 0x46001642},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49001644, 0x49001644},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x4c001a81, 0x4c001a81},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4f001a83, 0x4f001a83},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x52001c84, 0x52001c84},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001ce3, 0x55001ce3},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x59001ce5, 0x59001ce5},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5d001ce9, 0x5d001ce9},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x64001eec, 0x64001eec},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x64001eec, 0x64001eec},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+       {0x0000a624, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03},
+       {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a62c, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+};
+
+static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
+       /*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+       {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+       {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+       {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+       {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+       {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+       {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+       {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+#define ar9331_1p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
+
+static const u32 ar9331_1p1_xtal_25M[][2] = {
+       /* Addr      allmodes  */
+       {0x00007038, 0x000002f8},
+       {0x00008244, 0x0010f3d7},
+       {0x0000824c, 0x0001e7ae},
+       {0x0001609c, 0x0f508f29},
+};
+
+static const u32 ar9331_1p1_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73800000},
+       {0x0001600c, 0x00000000},
+       {0x00016040, 0x7f80fff8},
+       {0x00016044, 0x03db62db},
+       {0x00016048, 0x6c924268},
+       {0x0001604c, 0x000f0278},
+       {0x00016050, 0x4db6db8c},
+       {0x00016054, 0x6db60000},
+       {0x00016080, 0x00080000},
+       {0x00016084, 0x0e48048c},
+       {0x00016088, 0x14214514},
+       {0x0001608c, 0x119f081c},
+       {0x00016090, 0x24926490},
+       {0x00016098, 0xd411eb84},
+       {0x000160a0, 0xc2108ffe},
+       {0x000160a4, 0x812fc370},
+       {0x000160a8, 0x423c8000},
+       {0x000160ac, 0x24651800},
+       {0x000160b0, 0x03284f3e},
+       {0x000160b4, 0x92480040},
+       {0x000160c0, 0x006db6db},
+       {0x000160c4, 0x0186db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x6de6c300},
+       {0x000160d0, 0x14500820},
+       {0x00016100, 0x04cb0001},
+       {0x00016104, 0xfff80015},
+       {0x00016108, 0x00080010},
+       {0x0001610c, 0x00170000},
+       {0x00016140, 0x10804000},
+       {0x00016144, 0x01884080},
+       {0x00016148, 0x000080c0},
+       {0x00016280, 0x01000015},
+       {0x00016284, 0x14d20000},
+       {0x00016288, 0x00318000},
+       {0x0001628c, 0x50000000},
+       {0x00016290, 0x4b96210f},
+       {0x00016380, 0x00000000},
+       {0x00016384, 0x00000000},
+       {0x00016388, 0x00800700},
+       {0x0001638c, 0x00800700},
+       {0x00016390, 0x00800700},
+       {0x00016394, 0x00000000},
+       {0x00016398, 0x00000000},
+       {0x0001639c, 0x00000000},
+       {0x000163a0, 0x00000001},
+       {0x000163a4, 0x00000001},
+       {0x000163a8, 0x00000000},
+       {0x000163ac, 0x00000000},
+       {0x000163b0, 0x00000000},
+       {0x000163b4, 0x00000000},
+       {0x000163b8, 0x00000000},
+       {0x000163bc, 0x00000000},
+       {0x000163c0, 0x000000a0},
+       {0x000163c4, 0x000c0000},
+       {0x000163c8, 0x14021402},
+       {0x000163cc, 0x00001402},
+       {0x000163d0, 0x00000000},
+       {0x000163d4, 0x00000000},
+};
+
+static const u32 ar9331_1p1_soc_postamble[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
+};
+
+static const u32 ar9331_common_wo_xlna_rx_gain_1p1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00060005},
+       {0x0000a004, 0x00810080},
+       {0x0000a008, 0x00830082},
+       {0x0000a00c, 0x00850084},
+       {0x0000a010, 0x01820181},
+       {0x0000a014, 0x01840183},
+       {0x0000a018, 0x01880185},
+       {0x0000a01c, 0x018a0189},
+       {0x0000a020, 0x02850284},
+       {0x0000a024, 0x02890288},
+       {0x0000a028, 0x028b028a},
+       {0x0000a02c, 0x03850384},
+       {0x0000a030, 0x03890388},
+       {0x0000a034, 0x038b038a},
+       {0x0000a038, 0x038d038c},
+       {0x0000a03c, 0x03910390},
+       {0x0000a040, 0x03930392},
+       {0x0000a044, 0x03950394},
+       {0x0000a048, 0x00000396},
+       {0x0000a04c, 0x00000000},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x28282828},
+       {0x0000a084, 0x28282828},
+       {0x0000a088, 0x28282828},
+       {0x0000a08c, 0x28282828},
+       {0x0000a090, 0x28282828},
+       {0x0000a094, 0x24242428},
+       {0x0000a098, 0x171e1e1e},
+       {0x0000a09c, 0x02020b0b},
+       {0x0000a0a0, 0x02020202},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x22072208},
+       {0x0000a0c4, 0x22052206},
+       {0x0000a0c8, 0x22032204},
+       {0x0000a0cc, 0x22012202},
+       {0x0000a0d0, 0x221f2200},
+       {0x0000a0d4, 0x221d221e},
+       {0x0000a0d8, 0x33023303},
+       {0x0000a0dc, 0x33003301},
+       {0x0000a0e0, 0x331e331f},
+       {0x0000a0e4, 0x4402331d},
+       {0x0000a0e8, 0x44004401},
+       {0x0000a0ec, 0x441e441f},
+       {0x0000a0f0, 0x55025503},
+       {0x0000a0f4, 0x55005501},
+       {0x0000a0f8, 0x551e551f},
+       {0x0000a0fc, 0x6602551d},
+       {0x0000a100, 0x66006601},
+       {0x0000a104, 0x661e661f},
+       {0x0000a108, 0x7703661d},
+       {0x0000a10c, 0x77017702},
+       {0x0000a110, 0x00007700},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x111f1100},
+       {0x0000a148, 0x111d111e},
+       {0x0000a14c, 0x111b111c},
+       {0x0000a150, 0x22032204},
+       {0x0000a154, 0x22012202},
+       {0x0000a158, 0x221f2200},
+       {0x0000a15c, 0x221d221e},
+       {0x0000a160, 0x33013302},
+       {0x0000a164, 0x331f3300},
+       {0x0000a168, 0x4402331e},
+       {0x0000a16c, 0x44004401},
+       {0x0000a170, 0x441e441f},
+       {0x0000a174, 0x55015502},
+       {0x0000a178, 0x551f5500},
+       {0x0000a17c, 0x6602551e},
+       {0x0000a180, 0x66006601},
+       {0x0000a184, 0x661e661f},
+       {0x0000a188, 0x7703661d},
+       {0x0000a18c, 0x77017702},
+       {0x0000a190, 0x00007700},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9331_1p1_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a8f6b},
+       {0x0000980c, 0x04800000},
+       {0x00009814, 0x9280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x5f3ca3de},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x14750600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32840bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0x00000000},
+       {0x00009c08, 0x03200000},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x1883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c00400},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038233c},
+       {0x00009e24, 0x9927b515},
+       {0x00009e28, 0x12ef0200},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2dc, 0x00000000},
+       {0x0000a2e0, 0x00000000},
+       {0x0000a2e4, 0x00000000},
+       {0x0000a2e8, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0xaaaaaaaa},
+       {0x0000a3ac, 0x3c466478},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000006},
+       {0x0000a3f8, 0x0cdbd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739ce},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a41c, 0x1ce739ce},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce739ce},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00000000},
+       {0x0000a440, 0x00000000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x04000000},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a458, 0x00000000},
+       {0x0000a640, 0x00000000},
+       {0x0000a644, 0x3fad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00003c37},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000001},
+};
+
+static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+       {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+       {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+       {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+       {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+       {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+       {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+       {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+#define ar9331_1p1_mac_postamble ar9300_2p2_mac_postamble
+
+static const u32 ar9331_1p1_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000002f8},
+};
+
+static const u32 ar9331_1p1_xtal_40M[][2] = {
+       /* Addr      allmodes  */
+       {0x00007038, 0x000004c2},
+       {0x00008244, 0x0010f400},
+       {0x0000824c, 0x0001e800},
+       {0x0001609c, 0x0b283f31},
+};
+
+static const u32 ar9331_1p1_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x00020085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c20},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00a00000},
+       {0x000080d8, 0x00400000},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x18486200},
+       {0x00008174, 0x33332210},
+       {0x00008178, 0x00000000},
+       {0x0000817c, 0x00020000},
+       {0x000081c0, 0x00000000},
+       {0x000081c4, 0x33332210},
+       {0x000081c8, 0x00000000},
+       {0x000081cc, 0x00000000},
+       {0x000081d4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008248, 0x00000800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x9d400010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000140},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xaa48105b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a0, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9331_common_rx_gain_1p1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x01910190},
+       {0x0000a030, 0x01930192},
+       {0x0000a034, 0x01950194},
+       {0x0000a038, 0x038a0196},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x22222229},
+       {0x0000a084, 0x1d1d1d1d},
+       {0x0000a088, 0x1d1d1d1d},
+       {0x0000a08c, 0x1d1d1d1d},
+       {0x0000a090, 0x171d1d1d},
+       {0x0000a094, 0x11111717},
+       {0x0000a098, 0x00030311},
+       {0x0000a09c, 0x00000000},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+};
+
+static const u32 ar9331_common_tx_gain_offset1_1[][1] = {
+       {0},
+       {3},
+       {0},
+       {0},
+};
+
+#endif /* INITVALS_9330_1P1_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9330_1p2_initvals.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9330_1p2_initvals.h
new file mode 100644 (file)
index 0000000..57ed8a1
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9330_1P2_H
+#define INITVALS_9330_1P2_H
+
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+       {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+#define ar9331_modes_high_power_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
+
+#define ar9331_modes_low_ob_db_tx_gain_1p2 ar9331_modes_high_power_tx_gain_1p2
+
+#define ar9331_modes_lowest_ob_db_tx_gain_1p2 ar9331_modes_low_ob_db_tx_gain_1p2
+
+static const u32 ar9331_1p2_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+       {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+       {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+       {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+       {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+       {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+       {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9331_1p2_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73800000},
+       {0x0001600c, 0x00000000},
+       {0x00016040, 0x7f80fff8},
+       {0x00016044, 0x03d6d2db},
+       {0x00016048, 0x6c924268},
+       {0x0001604c, 0x000f0278},
+       {0x00016050, 0x4db6db8c},
+       {0x00016054, 0x6db60000},
+       {0x00016080, 0x00080000},
+       {0x00016084, 0x0e48048c},
+       {0x00016088, 0x14214514},
+       {0x0001608c, 0x119f081c},
+       {0x00016090, 0x24926490},
+       {0x00016098, 0xd411eb84},
+       {0x000160a0, 0xc2108ffe},
+       {0x000160a4, 0x812fc370},
+       {0x000160a8, 0x423c8000},
+       {0x000160ac, 0x24651800},
+       {0x000160b0, 0x03284f3e},
+       {0x000160b4, 0x92480040},
+       {0x000160c0, 0x006db6db},
+       {0x000160c4, 0x0186db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x6de6c300},
+       {0x000160d0, 0x14500820},
+       {0x00016100, 0x04cb0001},
+       {0x00016104, 0xfff80015},
+       {0x00016108, 0x00080010},
+       {0x0001610c, 0x00170000},
+       {0x00016140, 0x10804000},
+       {0x00016144, 0x01884080},
+       {0x00016148, 0x000080c0},
+       {0x00016280, 0x01000015},
+       {0x00016284, 0x14d20000},
+       {0x00016288, 0x00318000},
+       {0x0001628c, 0x50000000},
+       {0x00016290, 0x4b96210f},
+       {0x00016380, 0x00000000},
+       {0x00016384, 0x00000000},
+       {0x00016388, 0x00800700},
+       {0x0001638c, 0x00800700},
+       {0x00016390, 0x00800700},
+       {0x00016394, 0x00000000},
+       {0x00016398, 0x00000000},
+       {0x0001639c, 0x00000000},
+       {0x000163a0, 0x00000001},
+       {0x000163a4, 0x00000001},
+       {0x000163a8, 0x00000000},
+       {0x000163ac, 0x00000000},
+       {0x000163b0, 0x00000000},
+       {0x000163b4, 0x00000000},
+       {0x000163b8, 0x00000000},
+       {0x000163bc, 0x00000000},
+       {0x000163c0, 0x000000a0},
+       {0x000163c4, 0x000c0000},
+       {0x000163c8, 0x14021402},
+       {0x000163cc, 0x00001402},
+       {0x000163d0, 0x00000000},
+       {0x000163d4, 0x00000000},
+};
+
+#define ar9331_1p2_baseband_core_txfir_coeff_japan_2484 ar9331_1p1_baseband_core_txfir_coeff_japan_2484
+
+#define ar9331_1p2_xtal_25M ar9331_1p1_xtal_25M
+
+#define ar9331_1p2_xtal_40M ar9331_1p1_xtal_40M
+
+#define ar9331_1p2_baseband_core ar9331_1p1_baseband_core
+
+#define ar9331_1p2_soc_postamble ar9331_1p1_soc_postamble
+
+#define ar9331_1p2_mac_postamble ar9331_1p1_mac_postamble
+
+#define ar9331_1p2_soc_preamble ar9331_1p1_soc_preamble
+
+#define ar9331_1p2_mac_core ar9331_1p1_mac_core
+
+#define ar9331_common_wo_xlna_rx_gain_1p2 ar9331_common_wo_xlna_rx_gain_1p1
+
+#define ar9331_common_rx_gain_1p2 ar9485_common_rx_gain_1_1
+
+#endif /* INITVALS_9330_1P2_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9340_initvals.h
new file mode 100644 (file)
index 0000000..1d8235e
--- /dev/null
@@ -0,0 +1,1348 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9340_H
+#define INITVALS_9340_H
+
+static const u32 ar9340_1p0_radio_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800},
+       {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00016140, 0x10804000, 0x10804000, 0x50804000, 0x50804000},
+       {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00016540, 0x10804000, 0x10804000, 0x50804000, 0x50804000},
+};
+
+static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+       {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+       {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+       {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+       {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+};
+
+#define ar9340Modes_fast_clock_1p0 ar9300Modes_fast_clock_2p2
+
+static const u32 ar9340_1p0_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73f00000},
+       {0x0001600c, 0x00000000},
+       {0x00016040, 0x7f80fff8},
+       {0x00016044, 0x03b6d2db},
+       {0x00016048, 0x24925266},
+       {0x0001604c, 0x000f0278},
+       {0x00016050, 0x6db6db6c},
+       {0x00016054, 0x6db60000},
+       {0x00016080, 0x00080000},
+       {0x00016084, 0x0e48048c},
+       {0x00016088, 0x14214514},
+       {0x0001608c, 0x119f081c},
+       {0x00016090, 0x24926490},
+       {0x00016094, 0x00000000},
+       {0x00016098, 0xd411eb84},
+       {0x0001609c, 0x03e47f32},
+       {0x000160a0, 0xc2108ffe},
+       {0x000160a4, 0x812fc370},
+       {0x000160a8, 0x423c8000},
+       {0x000160ac, 0xa4646800},
+       {0x000160b0, 0x00fe7f46},
+       {0x000160b4, 0x92480000},
+       {0x000160c0, 0x006db6db},
+       {0x000160c4, 0x6db6db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x6de6db6c},
+       {0x000160d0, 0xb6da4924},
+       {0x00016100, 0x04cb0001},
+       {0x00016104, 0xfff80000},
+       {0x00016108, 0x00080010},
+       {0x00016140, 0x50804008},
+       {0x00016144, 0x01884080},
+       {0x00016148, 0x000080c0},
+       {0x00016280, 0x01000015},
+       {0x00016284, 0x15530000},
+       {0x00016288, 0x00318000},
+       {0x0001628c, 0x50000000},
+       {0x00016380, 0x00000000},
+       {0x00016384, 0x00000000},
+       {0x00016388, 0x00800700},
+       {0x0001638c, 0x00800700},
+       {0x00016390, 0x00800700},
+       {0x00016394, 0x00000000},
+       {0x00016398, 0x00000000},
+       {0x0001639c, 0x00000000},
+       {0x000163a0, 0x00000001},
+       {0x000163a4, 0x00000001},
+       {0x000163a8, 0x00000000},
+       {0x000163ac, 0x00000000},
+       {0x000163b0, 0x00000000},
+       {0x000163b4, 0x00000000},
+       {0x000163b8, 0x00000000},
+       {0x000163bc, 0x00000000},
+       {0x000163c0, 0x000000a0},
+       {0x000163c4, 0x000c0000},
+       {0x000163c8, 0x14021402},
+       {0x000163cc, 0x00001402},
+       {0x000163d0, 0x00000000},
+       {0x000163d4, 0x00000000},
+       {0x00016400, 0x36db6db6},
+       {0x00016404, 0x6db6db40},
+       {0x00016408, 0x73f00000},
+       {0x0001640c, 0x00000000},
+       {0x00016440, 0x7f80fff8},
+       {0x00016444, 0x03b6d2db},
+       {0x00016448, 0x24927266},
+       {0x0001644c, 0x000f0278},
+       {0x00016450, 0x6db6db6c},
+       {0x00016454, 0x6db60000},
+       {0x00016500, 0x04cb0001},
+       {0x00016504, 0xfff80000},
+       {0x00016508, 0x00080010},
+       {0x0001650c, 0x00000000},
+       {0x00016540, 0x50804008},
+       {0x00016544, 0x01884080},
+       {0x00016548, 0x000080c0},
+       {0x00016780, 0x00000000},
+       {0x00016784, 0x00000000},
+       {0x00016788, 0x00800700},
+       {0x0001678c, 0x00800700},
+       {0x00016790, 0x00800700},
+       {0x00016794, 0x00000000},
+       {0x00016798, 0x00000000},
+       {0x0001679c, 0x00000000},
+       {0x000167a0, 0x00000001},
+       {0x000167a4, 0x00000001},
+       {0x000167a8, 0x00000000},
+       {0x000167ac, 0x00000000},
+       {0x000167b0, 0x00000000},
+       {0x000167b4, 0x00000000},
+       {0x000167b8, 0x00000000},
+       {0x000167bc, 0x00000000},
+       {0x000167c0, 0x000000a0},
+       {0x000167c4, 0x000c0000},
+       {0x000167c8, 0x14021402},
+       {0x000167cc, 0x00001402},
+       {0x000167d0, 0x00000000},
+       {0x000167d4, 0x00000000},
+};
+
+static const u32 ar9340_1p0_radio_core_40M[][2] = {
+       /* Addr      allmodes  */
+       {0x0001609c, 0x02566f3a},
+       {0x000160ac, 0xa4647c00},
+       {0x000160b0, 0x01885f5a},
+};
+
+#define ar9340_1p0_mac_postamble ar9300_2p2_mac_postamble
+
+#define ar9340_1p0_soc_postamble ar9300_2p2_soc_postamble
+
+static const u32 ar9340_1p0_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+       {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+       {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+       {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+       {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e},
+       {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x00003ec0, 0x00003ec4, 0x00003ec4, 0x00003ec0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f},
+       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+       {0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110},
+       {0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00041983, 0x00041983, 0x00041982, 0x00041982},
+       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+       {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+};
+
+static const u32 ar9340_1p0_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a9f6b},
+       {0x0000980c, 0x04900000},
+       {0x00009814, 0x3280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x6400a190},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x14000600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32840bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0xff55ff55},
+       {0x00009c08, 0x0320ff55},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x9883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c0040b},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038230c},
+       {0x00009e24, 0x990bb515},
+       {0x00009e28, 0x0c6f0000},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009e54, 0x00000000},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x00009fd0, 0x01193b93},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0xaaaaaaaa},
+       {0x0000a3ac, 0x3c466478},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000000},
+       {0x0000a3f8, 0x0cdbd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739ce},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a41c, 0x1ce739ce},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce739ce},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00100000},
+       {0x0000a440, 0x00000000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x05000080},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a458, 0x00000000},
+       {0x0000a640, 0x00000000},
+       {0x0000a644, 0x3fad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00003c37},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000000},
+       {0x0000a8d0, 0x004b6a8e},
+       {0x0000a8d4, 0x00000820},
+       {0x0000a8dc, 0x00000000},
+       {0x0000a8f0, 0x00000000},
+       {0x0000a8f4, 0x00000000},
+       {0x0000b2d0, 0x00000080},
+       {0x0000b2d4, 0x00000000},
+       {0x0000b2ec, 0x00000000},
+       {0x0000b2f0, 0x00000000},
+       {0x0000b2f4, 0x00000000},
+       {0x0000b2f8, 0x00000000},
+       {0x0000b408, 0x0e79e5c0},
+       {0x0000b40c, 0x00820820},
+       {0x0000b420, 0x00000000},
+};
+
+static const u32 ar9340Modes_high_power_tx_gain_table_1p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+       {0x0000a504, 0x04002222, 0x04002222, 0x02000001, 0x02000001},
+       {0x0000a508, 0x09002421, 0x09002421, 0x05000003, 0x05000003},
+       {0x0000a50c, 0x0d002621, 0x0d002621, 0x0a000005, 0x0a000005},
+       {0x0000a510, 0x13004620, 0x13004620, 0x0e000201, 0x0e000201},
+       {0x0000a514, 0x19004a20, 0x19004a20, 0x11000203, 0x11000203},
+       {0x0000a518, 0x1d004e20, 0x1d004e20, 0x14000401, 0x14000401},
+       {0x0000a51c, 0x21005420, 0x21005420, 0x18000403, 0x18000403},
+       {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000602, 0x1b000602},
+       {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000802, 0x1f000802},
+       {0x0000a528, 0x2f005e42, 0x2f005e42, 0x21000620, 0x21000620},
+       {0x0000a52c, 0x33005e44, 0x33005e44, 0x25000820, 0x25000820},
+       {0x0000a530, 0x38005e65, 0x38005e65, 0x29000822, 0x29000822},
+       {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2d000824, 0x2d000824},
+       {0x0000a538, 0x40005e6b, 0x40005e6b, 0x30000828, 0x30000828},
+       {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x3400082a, 0x3400082a},
+       {0x0000a540, 0x49005e72, 0x49005e72, 0x38000849, 0x38000849},
+       {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b000a2c, 0x3b000a2c},
+       {0x0000a548, 0x53005f12, 0x53005f12, 0x3e000e2b, 0x3e000e2b},
+       {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42000e2d, 0x42000e2d},
+       {0x0000a550, 0x5e025f12, 0x5e025f12, 0x4500124a, 0x4500124a},
+       {0x0000a554, 0x61027f12, 0x61027f12, 0x4900124c, 0x4900124c},
+       {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c00126c, 0x4c00126c},
+       {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x4f00128c, 0x4f00128c},
+       {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x52001290, 0x52001290},
+       {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+       {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+       {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+       {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+       {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+       {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+       {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+       {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+       {0x0000a584, 0x04802222, 0x04802222, 0x02800001, 0x02800001},
+       {0x0000a588, 0x09802421, 0x09802421, 0x05800003, 0x05800003},
+       {0x0000a58c, 0x0d802621, 0x0d802621, 0x0a800005, 0x0a800005},
+       {0x0000a590, 0x13804620, 0x13804620, 0x0e800201, 0x0e800201},
+       {0x0000a594, 0x19804a20, 0x19804a20, 0x11800203, 0x11800203},
+       {0x0000a598, 0x1d804e20, 0x1d804e20, 0x14800401, 0x14800401},
+       {0x0000a59c, 0x21805420, 0x21805420, 0x18800403, 0x18800403},
+       {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800602, 0x1b800602},
+       {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800802, 0x1f800802},
+       {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x21800620, 0x21800620},
+       {0x0000a5ac, 0x33805e44, 0x33805e44, 0x25800820, 0x25800820},
+       {0x0000a5b0, 0x38805e65, 0x38805e65, 0x29800822, 0x29800822},
+       {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2d800824, 0x2d800824},
+       {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x30800828, 0x30800828},
+       {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x3480082a, 0x3480082a},
+       {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38800849, 0x38800849},
+       {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b800a2c, 0x3b800a2c},
+       {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e800e2b, 0x3e800e2b},
+       {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42800e2d, 0x42800e2d},
+       {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x4580124a, 0x4580124a},
+       {0x0000a5d4, 0x61827f12, 0x61827f12, 0x4980124c, 0x4980124c},
+       {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c80126c, 0x4c80126c},
+       {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x4f80128c, 0x4f80128c},
+       {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x52801290, 0x52801290},
+       {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+       {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+       {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+       {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+       {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+       {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+       {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+       {0x00016044, 0x056db2db, 0x056db2db, 0x022492db, 0x022492db},
+       {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+       {0x00016444, 0x056db2db, 0x056db2db, 0x022492db, 0x022492db},
+       {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+};
+
+static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+       {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+       {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+       {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+       {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+       {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+       {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+       {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+       {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+       {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+       {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+       {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+       {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+       {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+       {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+       {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+       {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+       {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+       {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+       {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+       {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+       {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+       {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+       {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+       {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+       {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+       {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+       {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
+       {0x00016048, 0x8e481666, 0x8e481666, 0x8e481266, 0x8e481266},
+       {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015},
+       {0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
+       {0x00016448, 0x8e481666, 0x8e481666, 0x8e481266, 0x8e481266},
+};
+
+static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+       {0x00009820, 0x206a022e, 0x206a022e, 0x206a00ae, 0x206a00ae},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec82d2e, 0x7ec82d2e},
+       {0x0000a2dc, 0xfef5d402, 0xfef5d402, 0xfdab5b52, 0xfdab5b52},
+       {0x0000a2e0, 0xfe896600, 0xfe896600, 0xfd339c84, 0xfd339c84},
+       {0x0000a2e4, 0xff01f800, 0xff01f800, 0xfec3e000, 0xfec3e000},
+       {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffc0000, 0xfffc0000},
+       {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+       {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+       {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+       {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+       {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+       {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+       {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+       {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+       {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+       {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+       {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+       {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+       {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+       {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+       {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+       {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+       {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+       {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+       {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+       {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+       {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+       {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+       {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+       {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+       {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+       {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+       {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+       {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x00016044, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
+       {0x00016048, 0x8e480086, 0x8e480086, 0x8e480086, 0x8e480086},
+       {0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
+       {0x00016448, 0x8e480086, 0x8e480086, 0x8e480086, 0x8e480086},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0xfef5d402, 0xfef5d402, 0xfdab5b52, 0xfdab5b52},
+       {0x0000b2e0, 0xfe896600, 0xfe896600, 0xfd339c84, 0xfd339c84},
+       {0x0000b2e4, 0xff01f800, 0xff01f800, 0xfec3e000, 0xfec3e000},
+       {0x0000b2e8, 0xfffe0000, 0xfffe0000, 0xfffc0000, 0xfffc0000},
+};
+
+static const u32 ar9340Common_rx_gain_table_1p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x01910190},
+       {0x0000a030, 0x01930192},
+       {0x0000a034, 0x01950194},
+       {0x0000a038, 0x038a0196},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x22222229},
+       {0x0000a084, 0x1d1d1d1d},
+       {0x0000a088, 0x1d1d1d1d},
+       {0x0000a08c, 0x1d1d1d1d},
+       {0x0000a090, 0x171d1d1d},
+       {0x0000a094, 0x11111717},
+       {0x0000a098, 0x00030311},
+       {0x0000a09c, 0x00000000},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x23232323},
+       {0x0000b084, 0x21232323},
+       {0x0000b088, 0x19191c1e},
+       {0x0000b08c, 0x12141417},
+       {0x0000b090, 0x07070e0e},
+       {0x0000b094, 0x03030305},
+       {0x0000b098, 0x00000003},
+       {0x0000b09c, 0x00000000},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+       {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+       {0x00016048, 0x24925666, 0x24925666, 0x24925266, 0x24925266},
+       {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015},
+       {0x00016288, 0xf0318000, 0xf0318000, 0xf0318000, 0xf0318000},
+       {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+       {0x00016448, 0x24925666, 0x24925666, 0x24925266, 0x24925266},
+};
+
+static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400},
+       {0x0000a598, 0x21820220, 0x21820220, 0x15800402, 0x15800402},
+       {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660},
+       {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861},
+       {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81},
+       {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42801a83, 0x42801a83},
+       {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x44801c84, 0x44801c84},
+       {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x48801ce3, 0x48801ce3},
+       {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c801ce5, 0x4c801ce5},
+       {0x0000a5dc, 0x7086308c, 0x7086308c, 0x50801ce9, 0x50801ce9},
+       {0x0000a5e0, 0x738a308a, 0x738a308a, 0x54801ceb, 0x54801ceb},
+       {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4},
+       {0x00016048, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266},
+       {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015},
+       {0x00016288, 0x30318000, 0x30318000, 0x00318000, 0x00318000},
+       {0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4},
+       {0x00016448, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266},
+};
+
+static const u32 ar9340_1p0_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x00020085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008010, 0x00080800},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c22},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00a00000},
+       {0x000080d8, 0x00400000},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x18486200},
+       {0x00008174, 0x33332210},
+       {0x00008178, 0x00000000},
+       {0x0000817c, 0x00020000},
+       {0x000081c0, 0x00000000},
+       {0x000081c4, 0x33332210},
+       {0x000081c8, 0x00000000},
+       {0x000081cc, 0x00000000},
+       {0x000081d4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f424},
+       {0x00008248, 0x00000800},
+       {0x0000824c, 0x0001e848},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x9d400010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000140},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xaa48105b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a0, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x000101ff},
+};
+
+#define ar9340Common_wo_xlna_rx_gain_table_1p0 ar9300Common_wo_xlna_rx_gain_table_2p2
+
+static const u32 ar9340_1p0_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x00007008, 0x00000000},
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+};
+
+#endif /* INITVALS_9340_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9462_2p0_initvals.h
new file mode 100644 (file)
index 0000000..4ef7dcc
--- /dev/null
@@ -0,0 +1,1453 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9462_2P0_H
+#define INITVALS_9462_2P0_H
+
+/* AR9462 2.0 */
+
+static const u32 ar9462_modes_fast_clock_2p0[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x00001030, 0x00000268, 0x000004d0},
+       {0x00001070, 0x0000018c, 0x00000318},
+       {0x000010b0, 0x00000fd0, 0x00001fa0},
+       {0x00008014, 0x044c044c, 0x08980898},
+       {0x0000801c, 0x148ec02b, 0x148ec057},
+       {0x00008318, 0x000044c0, 0x00008980},
+       {0x00009e00, 0x0372131c, 0x0372131c},
+       {0x0000a230, 0x0000400b, 0x00004016},
+       {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x18253ede},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0003580c},
+};
+
+static const u32 ar9462_2p0_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d},
+       {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae},
+       {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
+       {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+       {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+       {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+       {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
+       {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
+       {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x32395d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
+       {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x01318fc0, 0x01318fc4, 0x01318fc4, 0x01318fc0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f},
+       {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+       {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+       {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+       {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+       {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000},
+       {0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa},
+       {0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00},
+       {0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
+       {0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce},
+       {0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
+       {0x0000a428, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
+       {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+       {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
+};
+
+static const u32 ar9462_common_rx_gain_table_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x01910190},
+       {0x0000a030, 0x01930192},
+       {0x0000a034, 0x01950194},
+       {0x0000a038, 0x038a0196},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x22222229},
+       {0x0000a084, 0x1d1d1d1d},
+       {0x0000a088, 0x1d1d1d1d},
+       {0x0000a08c, 0x1d1d1d1d},
+       {0x0000a090, 0x171d1d1d},
+       {0x0000a094, 0x11111717},
+       {0x0000a098, 0x00030311},
+       {0x0000a09c, 0x00000000},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x2a2d2f32},
+       {0x0000b084, 0x21232328},
+       {0x0000b088, 0x19191c1e},
+       {0x0000b08c, 0x12141417},
+       {0x0000b090, 0x07070e0e},
+       {0x0000b094, 0x03030305},
+       {0x0000b098, 0x00000003},
+       {0x0000b09c, 0x00000000},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x18213ede},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0003580c},
+};
+
+static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x18212ede},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0003580c},
+};
+
+static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
+       {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+       {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+};
+
+static const u32 ar9462_common_wo_xlna_rx_gain_table_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x03820190},
+       {0x0000a030, 0x03840383},
+       {0x0000a034, 0x03880385},
+       {0x0000a038, 0x038a0389},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x29292929},
+       {0x0000a084, 0x29292929},
+       {0x0000a088, 0x29292929},
+       {0x0000a08c, 0x29292929},
+       {0x0000a090, 0x22292929},
+       {0x0000a094, 0x1d1d2222},
+       {0x0000a098, 0x0c111117},
+       {0x0000a09c, 0x00030303},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x32323232},
+       {0x0000b084, 0x2f2f3232},
+       {0x0000b088, 0x23282a2d},
+       {0x0000b08c, 0x1c1e2123},
+       {0x0000b090, 0x14171919},
+       {0x0000b094, 0x0e0e1214},
+       {0x0000b098, 0x03050707},
+       {0x0000b09c, 0x00030303},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9462_2p0_baseband_core_txfir_coeff_japan_2484[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x6f7f0301},
+       {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9462_modes_low_ob_db_tx_gain_table_2p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+       {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060},
+       {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+       {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+       {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000},
+       {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+};
+
+static const u32 ar9462_2p0_soc_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033},
+};
+
+static const u32 ar9462_2p0_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a9f6b},
+       {0x0000980c, 0x04900000},
+       {0x00009814, 0x9280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x6400a290},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x0d000600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32440bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098e4, 0x01ffffff},
+       {0x000098e8, 0x01ffffff},
+       {0x000098ec, 0x01ffffff},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009bf0, 0x80000000},
+       {0x00009c04, 0xff55ff55},
+       {0x00009c08, 0x0320ff55},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x9883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c0040b},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038230c},
+       {0x00009e24, 0x990bb515},
+       {0x00009e28, 0x0c6f0000},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x15262820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009e54, 0xe4c555c2},
+       {0x00009e58, 0xfd857722},
+       {0x00009e5c, 0xe9198724},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x00009fd0, 0x01193b93},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000006},
+       {0x0000a3f8, 0x0c9bd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739ce},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00100000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x05000080},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a454, 0x07000000},
+       {0x0000a644, 0xbfad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00002037},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a6b0, 0x0000000a},
+       {0x0000a6b4, 0x00512c01},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000001},
+       {0x0000a7f0, 0x80000000},
+       {0x0000a8d0, 0x004b6a8e},
+       {0x0000a8d4, 0x00000820},
+       {0x0000a8dc, 0x00000000},
+       {0x0000a8f0, 0x00000000},
+       {0x0000a8f4, 0x00000000},
+       {0x0000abf0, 0x80000000},
+       {0x0000b2d0, 0x00000080},
+       {0x0000b2d4, 0x00000000},
+       {0x0000b2ec, 0x00000000},
+       {0x0000b2f0, 0x00000000},
+       {0x0000b2f4, 0x00000000},
+       {0x0000b2f8, 0x00000000},
+       {0x0000b408, 0x0e79e5c0},
+       {0x0000b40c, 0x00820820},
+       {0x0000b420, 0x00000000},
+       {0x0000b6b0, 0x0000000a},
+       {0x0000b6b4, 0x00000001},
+};
+
+static const u32 ar9462_2p0_radio_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524},
+       {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70},
+       {0x0001610c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
+       {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
+};
+
+static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+       {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
+       {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
+       {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
+       {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
+       {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+       {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060},
+       {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+       {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+       {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000},
+       {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+};
+
+static const u32 ar9462_2p0_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73f00000},
+       {0x0001600c, 0x00000000},
+       {0x00016010, 0x6d820001},
+       {0x00016040, 0x7f80fff8},
+       {0x0001604c, 0x2699e04f},
+       {0x00016050, 0x6db6db6c},
+       {0x00016058, 0x6c200000},
+       {0x00016080, 0x000c0000},
+       {0x00016084, 0x9a68048c},
+       {0x00016088, 0x54214514},
+       {0x0001608c, 0x1203040b},
+       {0x00016090, 0x24926490},
+       {0x00016098, 0xd2888888},
+       {0x000160a0, 0x0a108ffe},
+       {0x000160a4, 0x812fc491},
+       {0x000160a8, 0x423c8000},
+       {0x000160b4, 0x92000000},
+       {0x000160b8, 0x0285dddc},
+       {0x000160bc, 0x02908888},
+       {0x000160c0, 0x00adb6d0},
+       {0x000160c4, 0x6db6db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x0de6c1b0},
+       {0x00016100, 0x3fffbe04},
+       {0x00016104, 0xfff80000},
+       {0x00016108, 0x00200400},
+       {0x00016110, 0x00000000},
+       {0x00016144, 0x02084080},
+       {0x00016148, 0x000080c0},
+       {0x00016280, 0x050a0001},
+       {0x00016284, 0x3d841418},
+       {0x00016288, 0x00000000},
+       {0x0001628c, 0xe3000000},
+       {0x00016290, 0xa1005080},
+       {0x00016294, 0x00000020},
+       {0x00016298, 0x54a82900},
+       {0x00016340, 0x121e4276},
+       {0x00016344, 0x00300000},
+       {0x00016400, 0x36db6db6},
+       {0x00016404, 0x6db6db40},
+       {0x00016408, 0x73f00000},
+       {0x0001640c, 0x00000000},
+       {0x00016410, 0x6c800001},
+       {0x00016440, 0x7f80fff8},
+       {0x0001644c, 0x4699e04f},
+       {0x00016450, 0x6db6db6c},
+       {0x00016500, 0x3fffbe04},
+       {0x00016504, 0xfff80000},
+       {0x00016508, 0x00200400},
+       {0x00016510, 0x00000000},
+       {0x00016544, 0x02084080},
+       {0x00016548, 0x000080c0},
+};
+
+static const u32 ar9462_2p0_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x000040a4, 0x00a0c1c9},
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+};
+
+static const u32 ar9462_2p0_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x000e0085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00001810, 0x0f000003},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00080000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008050, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c20},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00b00005},
+       {0x000080d8, 0x00400002},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x18486e00},
+       {0x00008174, 0x33332210},
+       {0x00008178, 0x00000000},
+       {0x0000817c, 0x00020000},
+       {0x000081c4, 0x33332210},
+       {0x000081c8, 0x00000000},
+       {0x000081cc, 0x00000000},
+       {0x000081d4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f424},
+       {0x00008248, 0x00000800},
+       {0x0000824c, 0x0001e848},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x99c00010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000140},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x0000001f},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0xffff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xaa48105b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9462_2p0_mac_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9462_common_mixed_rx_gain_table_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x03820190},
+       {0x0000a030, 0x03840383},
+       {0x0000a034, 0x03880385},
+       {0x0000a038, 0x038a0389},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x29292929},
+       {0x0000a084, 0x29292929},
+       {0x0000a088, 0x29292929},
+       {0x0000a08c, 0x29292929},
+       {0x0000a090, 0x22292929},
+       {0x0000a094, 0x1d1d2222},
+       {0x0000a098, 0x0c111117},
+       {0x0000a09c, 0x00030303},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x2a2d2f32},
+       {0x0000b084, 0x21232328},
+       {0x0000b088, 0x19191c1e},
+       {0x0000b08c, 0x12141417},
+       {0x0000b090, 0x07070e0e},
+       {0x0000b094, 0x03030305},
+       {0x0000b098, 0x00000003},
+       {0x0000b09c, 0x00000000},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+#endif /* INITVALS_9462_2P0_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9485_initvals.h
new file mode 100644 (file)
index 0000000..fb4497f
--- /dev/null
@@ -0,0 +1,853 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9485_H
+#define INITVALS_9485_H
+
+/* AR9485 1.0 */
+
+#define ar9485_1_1_mac_postamble ar9300_2p2_mac_postamble
+
+static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x18012e5e},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00060005},
+       {0x0000a004, 0x00810080},
+       {0x0000a008, 0x00830082},
+       {0x0000a00c, 0x00850084},
+       {0x0000a010, 0x01820181},
+       {0x0000a014, 0x01840183},
+       {0x0000a018, 0x01880185},
+       {0x0000a01c, 0x018a0189},
+       {0x0000a020, 0x02850284},
+       {0x0000a024, 0x02890288},
+       {0x0000a028, 0x028b028a},
+       {0x0000a02c, 0x03850384},
+       {0x0000a030, 0x03890388},
+       {0x0000a034, 0x038b038a},
+       {0x0000a038, 0x038d038c},
+       {0x0000a03c, 0x03910390},
+       {0x0000a040, 0x03930392},
+       {0x0000a044, 0x03950394},
+       {0x0000a048, 0x00000396},
+       {0x0000a04c, 0x00000000},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x28282828},
+       {0x0000a084, 0x28282828},
+       {0x0000a088, 0x28282828},
+       {0x0000a08c, 0x28282828},
+       {0x0000a090, 0x28282828},
+       {0x0000a094, 0x24242428},
+       {0x0000a098, 0x171e1e1e},
+       {0x0000a09c, 0x02020b0b},
+       {0x0000a0a0, 0x02020202},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x22072208},
+       {0x0000a0c4, 0x22052206},
+       {0x0000a0c8, 0x22032204},
+       {0x0000a0cc, 0x22012202},
+       {0x0000a0d0, 0x221f2200},
+       {0x0000a0d4, 0x221d221e},
+       {0x0000a0d8, 0x33023303},
+       {0x0000a0dc, 0x33003301},
+       {0x0000a0e0, 0x331e331f},
+       {0x0000a0e4, 0x4402331d},
+       {0x0000a0e8, 0x44004401},
+       {0x0000a0ec, 0x441e441f},
+       {0x0000a0f0, 0x55025503},
+       {0x0000a0f4, 0x55005501},
+       {0x0000a0f8, 0x551e551f},
+       {0x0000a0fc, 0x6602551d},
+       {0x0000a100, 0x66006601},
+       {0x0000a104, 0x661e661f},
+       {0x0000a108, 0x7703661d},
+       {0x0000a10c, 0x77017702},
+       {0x0000a110, 0x00007700},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x111f1100},
+       {0x0000a148, 0x111d111e},
+       {0x0000a14c, 0x111b111c},
+       {0x0000a150, 0x22032204},
+       {0x0000a154, 0x22012202},
+       {0x0000a158, 0x221f2200},
+       {0x0000a15c, 0x221d221e},
+       {0x0000a160, 0x33013302},
+       {0x0000a164, 0x331f3300},
+       {0x0000a168, 0x4402331e},
+       {0x0000a16c, 0x44004401},
+       {0x0000a170, 0x441e441f},
+       {0x0000a174, 0x55015502},
+       {0x0000a178, 0x551f5500},
+       {0x0000a17c, 0x6602551e},
+       {0x0000a180, 0x66006601},
+       {0x0000a184, 0x661e661f},
+       {0x0000a188, 0x7703661d},
+       {0x0000a18c, 0x77017702},
+       {0x0000a190, 0x00007700},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+       {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+       {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+#define ar9485Modes_high_ob_db_tx_gain_1_1 ar9485Modes_high_power_tx_gain_1_1
+
+#define ar9485Modes_low_ob_db_tx_gain_1_1 ar9485Modes_high_ob_db_tx_gain_1_1
+
+#define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1
+
+static const u32 ar9485_1_1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a580, 0x00000000},
+       {0x0000a584, 0x00000000},
+       {0x0000a588, 0x00000000},
+       {0x0000a58c, 0x00000000},
+       {0x0000a590, 0x00000000},
+       {0x0000a594, 0x00000000},
+       {0x0000a598, 0x00000000},
+       {0x0000a59c, 0x00000000},
+       {0x0000a5a0, 0x00000000},
+       {0x0000a5a4, 0x00000000},
+       {0x0000a5a8, 0x00000000},
+       {0x0000a5ac, 0x00000000},
+       {0x0000a5b0, 0x00000000},
+       {0x0000a5b4, 0x00000000},
+       {0x0000a5b8, 0x00000000},
+       {0x0000a5bc, 0x00000000},
+};
+
+static const u32 ar9485_1_1_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73800000},
+       {0x0001600c, 0x00000000},
+       {0x00016040, 0x7f80fff8},
+       {0x0001604c, 0x000f0278},
+       {0x00016050, 0x4db6db8c},
+       {0x00016054, 0x6db60000},
+       {0x00016080, 0x00080000},
+       {0x00016084, 0x0e48048c},
+       {0x00016088, 0x14214514},
+       {0x0001608c, 0x119f081e},
+       {0x00016090, 0x24926490},
+       {0x00016098, 0xd28b3330},
+       {0x000160a0, 0xc2108ffe},
+       {0x000160a4, 0x812fc370},
+       {0x000160a8, 0x423c8000},
+       {0x000160b4, 0x92480040},
+       {0x000160c0, 0x006db6db},
+       {0x000160c4, 0x0186db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x6de6fbe0},
+       {0x000160d0, 0xf7dfcf3c},
+       {0x00016100, 0x04cb0001},
+       {0x00016104, 0xfff80015},
+       {0x00016108, 0x00080010},
+       {0x00016144, 0x01884080},
+       {0x00016148, 0x00008040},
+       {0x00016240, 0x08400000},
+       {0x00016244, 0x1bf90f00},
+       {0x00016248, 0x00000000},
+       {0x0001624c, 0x00000000},
+       {0x00016280, 0x01000015},
+       {0x00016284, 0x00d30000},
+       {0x00016288, 0x00318000},
+       {0x0001628c, 0x50000000},
+       {0x00016290, 0x4b96210f},
+       {0x00016380, 0x00000000},
+       {0x00016384, 0x00000000},
+       {0x00016388, 0x00800700},
+       {0x0001638c, 0x00800700},
+       {0x00016390, 0x00800700},
+       {0x00016394, 0x00000000},
+       {0x00016398, 0x00000000},
+       {0x0001639c, 0x00000000},
+       {0x000163a0, 0x00000001},
+       {0x000163a4, 0x00000001},
+       {0x000163a8, 0x00000000},
+       {0x000163ac, 0x00000000},
+       {0x000163b0, 0x00000000},
+       {0x000163b4, 0x00000000},
+       {0x000163b8, 0x00000000},
+       {0x000163bc, 0x00000000},
+       {0x000163c0, 0x000000a0},
+       {0x000163c4, 0x000c0000},
+       {0x000163c8, 0x14021402},
+       {0x000163cc, 0x00001402},
+       {0x000163d0, 0x00000000},
+       {0x000163d4, 0x00000000},
+       {0x00016c40, 0x13188278},
+       {0x00016c44, 0x12000000},
+};
+
+static const u32 ar9485_1_1_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a8f6b},
+       {0x0000980c, 0x04800000},
+       {0x00009814, 0x9280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x5f3ca3de},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x14750600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x52440bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0x00000000},
+       {0x00009c08, 0x03200000},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x1883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c00400},
+       {0x00009d18, 0x00000000},
+       {0x00009d1c, 0x00000000},
+       {0x00009e08, 0x0038233c},
+       {0x00009e24, 0x9927b515},
+       {0x00009e28, 0x12ef0200},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009fc0, 0x80be4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x0000a20c, 0x00000000},
+       {0x0000a210, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2dc, 0x00000000},
+       {0x0000a2e0, 0x00000000},
+       {0x0000a2e4, 0x00000000},
+       {0x0000a2e8, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3a4, 0x000000ff},
+       {0x0000a3a8, 0x3b3b3b3b},
+       {0x0000a3ac, 0x2f2f2f2f},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000006},
+       {0x0000a3f8, 0x0cdbd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739cf},
+       {0x0000a418, 0x2d0019ce},
+       {0x0000a41c, 0x1ce739ce},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce739ce},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00000000},
+       {0x0000a440, 0x00000000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x04000000},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a5c4, 0xbfad9d74},
+       {0x0000a5c8, 0x0048060a},
+       {0x0000a5cc, 0x00000637},
+       {0x0000a760, 0x03020100},
+       {0x0000a764, 0x09080504},
+       {0x0000a768, 0x0d0c0b0a},
+       {0x0000a76c, 0x13121110},
+       {0x0000a770, 0x31301514},
+       {0x0000a774, 0x35343332},
+       {0x0000a778, 0x00000036},
+       {0x0000a780, 0x00000838},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000000},
+};
+
+static const u32 ar9485_common_rx_gain_1_1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x01800082},
+       {0x0000a014, 0x01820181},
+       {0x0000a018, 0x01840183},
+       {0x0000a01c, 0x01880185},
+       {0x0000a020, 0x018a0189},
+       {0x0000a024, 0x02850284},
+       {0x0000a028, 0x02890288},
+       {0x0000a02c, 0x03850384},
+       {0x0000a030, 0x03890388},
+       {0x0000a034, 0x038b038a},
+       {0x0000a038, 0x038d038c},
+       {0x0000a03c, 0x03910390},
+       {0x0000a040, 0x03930392},
+       {0x0000a044, 0x03950394},
+       {0x0000a048, 0x00000396},
+       {0x0000a04c, 0x00000000},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x28282828},
+       {0x0000a084, 0x28282828},
+       {0x0000a088, 0x28282828},
+       {0x0000a08c, 0x28282828},
+       {0x0000a090, 0x28282828},
+       {0x0000a094, 0x21212128},
+       {0x0000a098, 0x171c1c1c},
+       {0x0000a09c, 0x02020212},
+       {0x0000a0a0, 0x00000202},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x111f1100},
+       {0x0000a0c8, 0x111d111e},
+       {0x0000a0cc, 0x111b111c},
+       {0x0000a0d0, 0x22032204},
+       {0x0000a0d4, 0x22012202},
+       {0x0000a0d8, 0x221f2200},
+       {0x0000a0dc, 0x221d221e},
+       {0x0000a0e0, 0x33013302},
+       {0x0000a0e4, 0x331f3300},
+       {0x0000a0e8, 0x4402331e},
+       {0x0000a0ec, 0x44004401},
+       {0x0000a0f0, 0x441e441f},
+       {0x0000a0f4, 0x55015502},
+       {0x0000a0f8, 0x551f5500},
+       {0x0000a0fc, 0x6602551e},
+       {0x0000a100, 0x66006601},
+       {0x0000a104, 0x661e661f},
+       {0x0000a108, 0x7703661d},
+       {0x0000a10c, 0x77017702},
+       {0x0000a110, 0x00007700},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x111f1100},
+       {0x0000a148, 0x111d111e},
+       {0x0000a14c, 0x111b111c},
+       {0x0000a150, 0x22032204},
+       {0x0000a154, 0x22012202},
+       {0x0000a158, 0x221f2200},
+       {0x0000a15c, 0x221d221e},
+       {0x0000a160, 0x33013302},
+       {0x0000a164, 0x331f3300},
+       {0x0000a168, 0x4402331e},
+       {0x0000a16c, 0x44004401},
+       {0x0000a170, 0x441e441f},
+       {0x0000a174, 0x55015502},
+       {0x0000a178, 0x551f5500},
+       {0x0000a17c, 0x6602551e},
+       {0x0000a180, 0x66006601},
+       {0x0000a184, 0x661e661f},
+       {0x0000a188, 0x7703661d},
+       {0x0000a18c, 0x77017702},
+       {0x0000a190, 0x00007700},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x18052e5e},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x18053e5e},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485_1_1_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x00004014, 0xba280400},
+       {0x00004090, 0x00aa10aa},
+       {0x000040a4, 0x00a0c9c9},
+       {0x00007010, 0x00000022},
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+       {0x00007048, 0x00000002},
+};
+
+static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x00009e00, 0x03721821, 0x03721821},
+       {0x0000a230, 0x0000400b, 0x00004016},
+       {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9485_1_1_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+       {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+       {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+       {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+       {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
+       {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+       {0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
+       {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982},
+       {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+       {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x18013e5e},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485_1_1_radio_postamble[][2] = {
+       /* Addr      allmodes  */
+       {0x0001609c, 0x0b283f31},
+       {0x000160ac, 0x24611800},
+       {0x000160b0, 0x03284f3e},
+       {0x0001610c, 0x00170000},
+       {0x00016140, 0x50804008},
+};
+
+static const u32 ar9485_1_1_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x00020085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c22},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00a00000},
+       {0x000080d8, 0x00400000},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x18486200},
+       {0x00008174, 0x33332210},
+       {0x00008178, 0x00000000},
+       {0x0000817c, 0x00020000},
+       {0x000081c0, 0x00000000},
+       {0x000081c4, 0x33332210},
+       {0x000081d4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000800},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x9ca00010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000140},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xa248105b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a0, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x000301ff},
+};
+
+#endif /* INITVALS_9485_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k_btcoex/ar9580_1p0_initvals.h
new file mode 100644 (file)
index 0000000..6e1915a
--- /dev/null
@@ -0,0 +1,921 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9580_1P0_H
+#define INITVALS_9580_1P0_H
+
+/* AR9580 1.0 */
+
+#define ar9580_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2
+
+static const u32 ar9580_1p0_radio_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31},
+       {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
+       {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
+       {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+       {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+       {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+};
+
+static const u32 ar9580_1p0_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a9f6b},
+       {0x0000980c, 0x04900000},
+       {0x00009814, 0x3280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x6400a290},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x0d000600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32840bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0xff55ff55},
+       {0x00009c08, 0x0320ff55},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x9883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c0040b},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038230c},
+       {0x00009e24, 0x990bb515},
+       {0x00009e28, 0x0c6f0000},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009e54, 0x00000000},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x00009fd0, 0x01193b93},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0xaaaaaaaa},
+       {0x0000a3ac, 0x3c466478},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000000},
+       {0x0000a3f8, 0x0c9bd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739ce},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a41c, 0x1ce739ce},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce739ce},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00100000},
+       {0x0000a440, 0x00000000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x05000080},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a458, 0x00000000},
+       {0x0000a640, 0x00000000},
+       {0x0000a644, 0x3fad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00003c37},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000000},
+       {0x0000a8d0, 0x004b6a8e},
+       {0x0000a8d4, 0x00000820},
+       {0x0000a8dc, 0x00000000},
+       {0x0000a8f0, 0x00000000},
+       {0x0000a8f4, 0x00000000},
+       {0x0000b2d0, 0x00000080},
+       {0x0000b2d4, 0x00000000},
+       {0x0000b2ec, 0x00000000},
+       {0x0000b2f0, 0x00000000},
+       {0x0000b2f4, 0x00000000},
+       {0x0000b2f8, 0x00000000},
+       {0x0000b408, 0x0e79e5c0},
+       {0x0000b40c, 0x00820820},
+       {0x0000b420, 0x00000000},
+       {0x0000b8d0, 0x004b6a8e},
+       {0x0000b8d4, 0x00000820},
+       {0x0000b8dc, 0x00000000},
+       {0x0000b8f0, 0x00000000},
+       {0x0000b8f4, 0x00000000},
+       {0x0000c2d0, 0x00000080},
+       {0x0000c2d4, 0x00000000},
+       {0x0000c2ec, 0x00000000},
+       {0x0000c2f0, 0x00000000},
+       {0x0000c2f4, 0x00000000},
+       {0x0000c2f8, 0x00000000},
+       {0x0000c408, 0x0e79e5c0},
+       {0x0000c40c, 0x00820820},
+       {0x0000c420, 0x00000000},
+};
+
+#define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble
+
+static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+       {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+#define ar9580_1p0_high_power_tx_gain_table ar9580_1p0_low_ob_db_tx_gain_table
+
+static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+       {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+       {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+       {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+       {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+#define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
+
+static const u32 ar9580_1p0_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x00020085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c22},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00a00000},
+       {0x000080d8, 0x00400000},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x000081c0, 0x00000000},
+       {0x000081c4, 0x33332210},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000800},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x9bc00010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000140},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xaa48105b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a0, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400},
+       {0x0000a598, 0x21802220, 0x21802220, 0x15800402, 0x15800402},
+       {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660},
+       {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861},
+       {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81},
+       {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x42801a83, 0x42801a83},
+       {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x44801c84, 0x44801c84},
+       {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x48801ce3, 0x48801ce3},
+       {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x4c801ce5, 0x4c801ce5},
+       {0x0000a5dc, 0x7082708c, 0x7082708c, 0x50801ce9, 0x50801ce9},
+       {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x54801ceb, 0x54801ceb},
+       {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+       {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+       {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+       {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+       {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+       {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+       {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4},
+       {0x00016048, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001},
+       {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016444, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4},
+       {0x00016448, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001},
+       {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016844, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4},
+       {0x00016848, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001},
+       {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+#define ar9580_1p0_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2
+
+#define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble
+
+#define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2
+
+static const u32 ar9580_1p0_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x000040a4, 0x00a0c1c9},
+       {0x00007008, 0x00000000},
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+       {0x00007048, 0x00000008},
+};
+
+#define ar9580_1p0_rx_gain_table ar9462_common_rx_gain_table_2p0
+
+static const u32 ar9580_1p0_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73f00000},
+       {0x0001600c, 0x00000000},
+       {0x00016040, 0x7f80fff8},
+       {0x0001604c, 0x76d005b5},
+       {0x00016050, 0x556cf031},
+       {0x00016054, 0x13449440},
+       {0x00016058, 0x0c51c92c},
+       {0x0001605c, 0x3db7fffc},
+       {0x00016060, 0xfffffffc},
+       {0x00016064, 0x000f0278},
+       {0x0001606c, 0x6db60000},
+       {0x00016080, 0x00000000},
+       {0x00016084, 0x0e48048c},
+       {0x00016088, 0x54214514},
+       {0x0001608c, 0x119f481e},
+       {0x00016090, 0x24926490},
+       {0x00016098, 0xd2888888},
+       {0x000160a0, 0x0a108ffe},
+       {0x000160a4, 0x812fc370},
+       {0x000160a8, 0x423c8000},
+       {0x000160b4, 0x92480080},
+       {0x000160c0, 0x00adb6d0},
+       {0x000160c4, 0x6db6db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x01e6c000},
+       {0x00016100, 0x3fffbe01},
+       {0x00016104, 0xfff80000},
+       {0x00016108, 0x00080010},
+       {0x00016144, 0x02084080},
+       {0x00016148, 0x00000000},
+       {0x00016280, 0x058a0001},
+       {0x00016284, 0x3d840208},
+       {0x00016288, 0x05a20408},
+       {0x0001628c, 0x00038c07},
+       {0x00016290, 0x00000004},
+       {0x00016294, 0x458aa14f},
+       {0x00016380, 0x00000000},
+       {0x00016384, 0x00000000},
+       {0x00016388, 0x00800700},
+       {0x0001638c, 0x00800700},
+       {0x00016390, 0x00800700},
+       {0x00016394, 0x00000000},
+       {0x00016398, 0x00000000},
+       {0x0001639c, 0x00000000},
+       {0x000163a0, 0x00000001},
+       {0x000163a4, 0x00000001},
+       {0x000163a8, 0x00000000},
+       {0x000163ac, 0x00000000},
+       {0x000163b0, 0x00000000},
+       {0x000163b4, 0x00000000},
+       {0x000163b8, 0x00000000},
+       {0x000163bc, 0x00000000},
+       {0x000163c0, 0x000000a0},
+       {0x000163c4, 0x000c0000},
+       {0x000163c8, 0x14021402},
+       {0x000163cc, 0x00001402},
+       {0x000163d0, 0x00000000},
+       {0x000163d4, 0x00000000},
+       {0x00016400, 0x36db6db6},
+       {0x00016404, 0x6db6db40},
+       {0x00016408, 0x73f00000},
+       {0x0001640c, 0x00000000},
+       {0x00016440, 0x7f80fff8},
+       {0x0001644c, 0x76d005b5},
+       {0x00016450, 0x556cf031},
+       {0x00016454, 0x13449440},
+       {0x00016458, 0x0c51c92c},
+       {0x0001645c, 0x3db7fffc},
+       {0x00016460, 0xfffffffc},
+       {0x00016464, 0x000f0278},
+       {0x0001646c, 0x6db60000},
+       {0x00016500, 0x3fffbe01},
+       {0x00016504, 0xfff80000},
+       {0x00016508, 0x00080010},
+       {0x00016544, 0x02084080},
+       {0x00016548, 0x00000000},
+       {0x00016780, 0x00000000},
+       {0x00016784, 0x00000000},
+       {0x00016788, 0x00800700},
+       {0x0001678c, 0x00800700},
+       {0x00016790, 0x00800700},
+       {0x00016794, 0x00000000},
+       {0x00016798, 0x00000000},
+       {0x0001679c, 0x00000000},
+       {0x000167a0, 0x00000001},
+       {0x000167a4, 0x00000001},
+       {0x000167a8, 0x00000000},
+       {0x000167ac, 0x00000000},
+       {0x000167b0, 0x00000000},
+       {0x000167b4, 0x00000000},
+       {0x000167b8, 0x00000000},
+       {0x000167bc, 0x00000000},
+       {0x000167c0, 0x000000a0},
+       {0x000167c4, 0x000c0000},
+       {0x000167c8, 0x14021402},
+       {0x000167cc, 0x00001402},
+       {0x000167d0, 0x00000000},
+       {0x000167d4, 0x00000000},
+       {0x00016800, 0x36db6db6},
+       {0x00016804, 0x6db6db40},
+       {0x00016808, 0x73f00000},
+       {0x0001680c, 0x00000000},
+       {0x00016840, 0x7f80fff8},
+       {0x0001684c, 0x76d005b5},
+       {0x00016850, 0x556cf031},
+       {0x00016854, 0x13449440},
+       {0x00016858, 0x0c51c92c},
+       {0x0001685c, 0x3db7fffc},
+       {0x00016860, 0xfffffffc},
+       {0x00016864, 0x000f0278},
+       {0x0001686c, 0x6db60000},
+       {0x00016900, 0x3fffbe01},
+       {0x00016904, 0xfff80000},
+       {0x00016908, 0x00080010},
+       {0x00016944, 0x02084080},
+       {0x00016948, 0x00000000},
+       {0x00016b80, 0x00000000},
+       {0x00016b84, 0x00000000},
+       {0x00016b88, 0x00800700},
+       {0x00016b8c, 0x00800700},
+       {0x00016b90, 0x00800700},
+       {0x00016b94, 0x00000000},
+       {0x00016b98, 0x00000000},
+       {0x00016b9c, 0x00000000},
+       {0x00016ba0, 0x00000001},
+       {0x00016ba4, 0x00000001},
+       {0x00016ba8, 0x00000000},
+       {0x00016bac, 0x00000000},
+       {0x00016bb0, 0x00000000},
+       {0x00016bb4, 0x00000000},
+       {0x00016bb8, 0x00000000},
+       {0x00016bbc, 0x00000000},
+       {0x00016bc0, 0x000000a0},
+       {0x00016bc4, 0x000c0000},
+       {0x00016bc8, 0x14021402},
+       {0x00016bcc, 0x00001402},
+       {0x00016bd0, 0x00000000},
+       {0x00016bd4, 0x00000000},
+};
+
+static const u32 ar9580_1p0_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+       {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+       {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+       {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+       {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f},
+       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+       {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+       {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+       {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+       {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+       {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+       {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+       {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+};
+
+static const u32 ar9580_1p0_pcie_phy_clkreq_enable_L1[][2] = {
+       /* Addr      allmodes  */
+       {0x00004040, 0x0835365e},
+       {0x00004040, 0x0008003b},
+       {0x00004044, 0x00000000},
+};
+
+static const u32 ar9580_1p0_pcie_phy_clkreq_disable_L1[][2] = {
+       /* Addr      allmodes  */
+       {0x00004040, 0x0831365e},
+       {0x00004040, 0x0008003b},
+       {0x00004044, 0x00000000},
+};
+
+static const u32 ar9580_1p0_pcie_phy_pll_on_clkreq[][2] = {
+       /* Addr      allmodes  */
+       {0x00004040, 0x0831265e},
+       {0x00004040, 0x0008003b},
+       {0x00004044, 0x00000000},
+};
+
+#endif /* INITVALS_9580_1P0_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/ath9k.h b/drivers/net/wireless/ath/ath9k_btcoex/ath9k.h
new file mode 100644 (file)
index 0000000..29dc1f7
--- /dev/null
@@ -0,0 +1,761 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH9K_H
+#define ATH9K_H
+
+#include <linux/etherdevice.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/leds.h>
+#include <linux/completion.h>
+
+#include "debug.h"
+#include "common.h"
+#include "mci.h"
+
+/*
+ * Header for the ath9k.ko driver core *only* -- hw code nor any other driver
+ * should rely on this file or its contents.
+ */
+
+struct ath_node;
+
+/* Macro to expand scalars to 64-bit objects */
+
+#define        ito64(x) (sizeof(x) == 1) ?                     \
+       (((unsigned long long int)(x)) & (0xff)) :      \
+       (sizeof(x) == 2) ?                              \
+       (((unsigned long long int)(x)) & 0xffff) :      \
+       ((sizeof(x) == 4) ?                             \
+        (((unsigned long long int)(x)) & 0xffffffff) : \
+        (unsigned long long int)(x))
+
+/* increment with wrap-around */
+#define INCR(_l, _sz)   do {                   \
+               (_l)++;                         \
+               (_l) &= ((_sz) - 1);            \
+       } while (0)
+
+/* decrement with wrap-around */
+#define DECR(_l,  _sz)  do {                   \
+               (_l)--;                         \
+               (_l) &= ((_sz) - 1);            \
+       } while (0)
+
+#define TSF_TO_TU(_h,_l) \
+       ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
+
+#define        ATH_TXQ_SETUP(sc, i)        ((sc)->tx.txqsetup & (1<<i))
+
+struct ath_config {
+       u16 txpowlimit;
+       u8 cabqReadytime;
+};
+
+/*************************/
+/* Descriptor Management */
+/*************************/
+
+#define ATH_TXBUF_RESET(_bf) do {                              \
+               (_bf)->bf_stale = false;                        \
+               (_bf)->bf_lastbf = NULL;                        \
+               (_bf)->bf_next = NULL;                          \
+               memset(&((_bf)->bf_state), 0,                   \
+                      sizeof(struct ath_buf_state));           \
+       } while (0)
+
+#define ATH_RXBUF_RESET(_bf) do {              \
+               (_bf)->bf_stale = false;        \
+       } while (0)
+
+/**
+ * enum buffer_type - Buffer type flags
+ *
+ * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
+ * @BUF_AGGR: Indicates whether the buffer can be aggregated
+ *     (used in aggregation scheduling)
+ */
+enum buffer_type {
+       BUF_AMPDU               = BIT(0),
+       BUF_AGGR                = BIT(1),
+};
+
+#define bf_isampdu(bf)         (bf->bf_state.bf_type & BUF_AMPDU)
+#define bf_isaggr(bf)          (bf->bf_state.bf_type & BUF_AGGR)
+
+#define ATH_TXSTATUS_RING_SIZE 512
+
+#define        DS2PHYS(_dd, _ds)                                               \
+       ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
+#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
+
+struct ath_descdma {
+       void *dd_desc;
+       dma_addr_t dd_desc_paddr;
+       u32 dd_desc_len;
+       struct ath_buf *dd_bufptr;
+};
+
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+                     struct list_head *head, const char *name,
+                     int nbuf, int ndesc, bool is_tx);
+void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
+                        struct list_head *head);
+
+/***********/
+/* RX / TX */
+/***********/
+
+#define ATH_RXBUF               512
+#define ATH_TXBUF               512
+#define ATH_TXBUF_RESERVE       5
+#define ATH_MAX_QDEPTH          (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
+#define ATH_TXMAXTRY            13
+
+#define TID_TO_WME_AC(_tid)                            \
+       ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
+        (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
+        (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
+        WME_AC_VO)
+
+#define ATH_AGGR_DELIM_SZ          4
+#define ATH_AGGR_MINPLEN           256 /* in bytes, minimum packet length */
+/* number of delimiters for encryption padding */
+#define ATH_AGGR_ENCRYPTDELIM      10
+/* minimum h/w qdepth to be sustained to maximize aggregation */
+#define ATH_AGGR_MIN_QDEPTH        2
+#define ATH_AMPDU_SUBFRAME_DEFAULT 32
+
+#define IEEE80211_SEQ_SEQ_SHIFT    4
+#define IEEE80211_SEQ_MAX          4096
+#define IEEE80211_WEP_IVLEN        3
+#define IEEE80211_WEP_KIDLEN       1
+#define IEEE80211_WEP_CRCLEN       4
+#define IEEE80211_MAX_MPDU_LEN     (3840 + FCS_LEN +           \
+                                   (IEEE80211_WEP_IVLEN +      \
+                                    IEEE80211_WEP_KIDLEN +     \
+                                    IEEE80211_WEP_CRCLEN))
+
+/* return whether a bit at index _n in bitmap _bm is set
+ * _sz is the size of the bitmap  */
+#define ATH_BA_ISSET(_bm, _n)  (((_n) < (WME_BA_BMP_SIZE)) &&          \
+                               ((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
+
+/* return block-ack bitmap index given sequence and starting sequence */
+#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
+
+/* return the seqno for _start + _offset */
+#define ATH_BA_INDEX2SEQ(_seq, _offset) (((_seq) + (_offset)) & (IEEE80211_SEQ_MAX - 1))
+
+/* returns delimiter padding required given the packet length */
+#define ATH_AGGR_GET_NDELIM(_len)                                      \
+       (((_len) >= ATH_AGGR_MINPLEN) ? 0 :                             \
+        DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ))
+
+#define BAW_WITHIN(_start, _bawsz, _seqno) \
+       ((((_seqno) - (_start)) & 4095) < (_bawsz))
+
+#define ATH_AN_2_TID(_an, _tidno)  (&(_an)->tid[(_tidno)])
+
+#define ATH_TX_COMPLETE_POLL_INT       1000
+
+enum ATH_AGGR_STATUS {
+       ATH_AGGR_DONE,
+       ATH_AGGR_BAW_CLOSED,
+       ATH_AGGR_LIMITED,
+};
+
+#define ATH_TXFIFO_DEPTH 8
+struct ath_txq {
+       int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
+       u32 axq_qnum; /* ath9k hardware queue number */
+       void *axq_link;
+       struct list_head axq_q;
+       spinlock_t axq_lock;
+       u32 axq_depth;
+       u32 axq_ampdu_depth;
+       bool stopped;
+       bool axq_tx_inprogress;
+       struct list_head axq_acq;
+       struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
+       u8 txq_headidx;
+       u8 txq_tailidx;
+       int pending_frames;
+       struct sk_buff_head complete_q;
+};
+
+struct ath_atx_ac {
+       struct ath_txq *txq;
+       int sched;
+       struct list_head list;
+       struct list_head tid_q;
+       bool clear_ps_filter;
+};
+
+struct ath_frame_info {
+       struct ath_buf *bf;
+       int framelen;
+       enum ath9k_key_type keytype;
+       u8 keyix;
+       u8 retries;
+       u8 rtscts_rate;
+};
+
+struct ath_buf_state {
+       u8 bf_type;
+       u8 bfs_paprd;
+       u8 ndelim;
+       u16 seqno;
+       unsigned long bfs_paprd_timestamp;
+};
+
+struct ath_buf {
+       struct list_head list;
+       struct ath_buf *bf_lastbf;      /* last buf of this unit (a frame or
+                                          an aggregate) */
+       struct ath_buf *bf_next;        /* next subframe in the aggregate */
+       struct sk_buff *bf_mpdu;        /* enclosing frame structure */
+       void *bf_desc;                  /* virtual addr of desc */
+       dma_addr_t bf_daddr;            /* physical addr of desc */
+       dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
+       bool bf_stale;
+       struct ath_buf_state bf_state;
+};
+
+struct ath_atx_tid {
+       struct list_head list;
+       struct sk_buff_head buf_q;
+       struct ath_node *an;
+       struct ath_atx_ac *ac;
+       unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
+       int bar_index;
+       u16 seq_start;
+       u16 seq_next;
+       u16 baw_size;
+       int tidno;
+       int baw_head;   /* first un-acked tx buffer */
+       int baw_tail;   /* next unused tx buffer slot */
+       int sched;
+       int paused;
+       u8 state;
+};
+
+struct ath_node {
+#ifdef CONFIG_ATH9K_DEBUGFS
+       struct list_head list; /* for sc->nodes */
+#endif
+       struct ieee80211_sta *sta; /* station struct we're part of */
+       struct ieee80211_vif *vif; /* interface with which we're associated */
+       struct ath_atx_tid tid[WME_NUM_TID];
+       struct ath_atx_ac ac[WME_NUM_AC];
+       int ps_key;
+
+       u16 maxampdu;
+       u8 mpdudensity;
+
+       bool sleeping;
+};
+
+#define AGGR_CLEANUP         BIT(1)
+#define AGGR_ADDBA_COMPLETE  BIT(2)
+#define AGGR_ADDBA_PROGRESS  BIT(3)
+
+struct ath_tx_control {
+       struct ath_txq *txq;
+       struct ath_node *an;
+       u8 paprd;
+};
+
+#define ATH_TX_ERROR        0x01
+
+/**
+ * @txq_map:  Index is mac80211 queue number.  This is
+ *  not necessarily the same as the hardware queue number
+ *  (axq_qnum).
+ */
+struct ath_tx {
+       u16 seq_no;
+       u32 txqsetup;
+       spinlock_t txbuflock;
+       struct list_head txbuf;
+       struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
+       struct ath_descdma txdma;
+       struct ath_txq *txq_map[WME_NUM_AC];
+};
+
+struct ath_rx_edma {
+       struct sk_buff_head rx_fifo;
+       u32 rx_fifo_hwsize;
+};
+
+struct ath_rx {
+       u8 defant;
+       u8 rxotherant;
+       u32 *rxlink;
+       u32 num_pkts;
+       unsigned int rxfilter;
+       spinlock_t rxbuflock;
+       struct list_head rxbuf;
+       struct ath_descdma rxdma;
+       struct ath_buf *rx_bufptr;
+       struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
+
+       struct sk_buff *frag;
+};
+
+int ath_startrecv(struct ath_softc *sc);
+bool ath_stoprecv(struct ath_softc *sc);
+void ath_flushrecv(struct ath_softc *sc);
+u32 ath_calcrxfilter(struct ath_softc *sc);
+int ath_rx_init(struct ath_softc *sc, int nbufs);
+void ath_rx_cleanup(struct ath_softc *sc);
+int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
+struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
+void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
+bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
+void ath_draintxq(struct ath_softc *sc,
+                    struct ath_txq *txq, bool retry_tx);
+void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
+void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
+void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
+int ath_tx_init(struct ath_softc *sc, int nbufs);
+void ath_tx_cleanup(struct ath_softc *sc);
+int ath_txq_update(struct ath_softc *sc, int qnum,
+                  struct ath9k_tx_queue_info *q);
+int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
+                struct ath_tx_control *txctl);
+void ath_tx_tasklet(struct ath_softc *sc);
+void ath_tx_edma_tasklet(struct ath_softc *sc);
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+                     u16 tid, u16 *ssn);
+void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+
+void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
+void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
+                      struct ath_node *an);
+
+/********/
+/* VIFs */
+/********/
+
+struct ath_vif {
+       int av_bslot;
+       bool primary_sta_vif;
+       __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
+       struct ath_buf *av_bcbuf;
+};
+
+/*******************/
+/* Beacon Handling */
+/*******************/
+
+/*
+ * Regardless of the number of beacons we stagger, (i.e. regardless of the
+ * number of BSSIDs) if a given beacon does not go out even after waiting this
+ * number of beacon intervals, the game's up.
+ */
+#define BSTUCK_THRESH                  9
+#define        ATH_BCBUF                       4
+#define ATH_DEFAULT_BINTVAL            100 /* TU */
+#define ATH_DEFAULT_BMISS_LIMIT        10
+#define IEEE80211_MS_TO_TU(x)           (((x) * 1000) / 1024)
+
+struct ath_beacon_config {
+       int beacon_interval;
+       u16 listen_interval;
+       u16 dtim_period;
+       u16 bmiss_timeout;
+       u8 dtim_count;
+       bool enable_beacon;
+};
+
+struct ath_beacon {
+       enum {
+               OK,             /* no change needed */
+               UPDATE,         /* update pending */
+               COMMIT          /* beacon sent, commit change */
+       } updateslot;           /* slot time update fsm */
+
+       u32 beaconq;
+       u32 bmisscnt;
+       u32 bc_tstamp;
+       struct ieee80211_vif *bslot[ATH_BCBUF];
+       int slottime;
+       int slotupdate;
+       struct ath9k_tx_queue_info beacon_qi;
+       struct ath_descdma bdma;
+       struct ath_txq *cabq;
+       struct list_head bbuf;
+
+       bool tx_processed;
+       bool tx_last;
+};
+
+void ath9k_beacon_tasklet(unsigned long data);
+bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
+void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
+                        u32 changed);
+void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif);
+void ath9k_set_beacon(struct ath_softc *sc);
+void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
+
+/*******/
+/* ANI */
+/*******/
+
+#define ATH_STA_SHORT_CALINTERVAL 1000    /* 1 second */
+#define ATH_AP_SHORT_CALINTERVAL  100     /* 100 ms */
+#define ATH_ANI_POLLINTERVAL_OLD  100     /* 100 ms */
+#define ATH_ANI_POLLINTERVAL_NEW  1000    /* 1000 ms */
+#define ATH_LONG_CALINTERVAL_INT  1000    /* 1000 ms */
+#define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
+#define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
+
+#define ATH_PAPRD_TIMEOUT      100 /* msecs */
+
+void ath_reset_work(struct work_struct *work);
+void ath_hw_check(struct work_struct *work);
+void ath_hw_pll_work(struct work_struct *work);
+void ath_rx_poll_work(unsigned long data);
+void ath_start_rx_poll(struct ath_softc *sc, u32 nmsec);
+void ath_paprd_calibrate(struct work_struct *work);
+void ath_ani_calibrate(unsigned long data);
+void ath_start_ani(struct ath_common *common);
+
+/**********/
+/* BTCOEX */
+/**********/
+
+enum bt_op_flags {
+       BT_OP_PRIORITY_DETECTED,
+       BT_OP_SCAN,
+};
+
+struct ath_btcoex {
+       bool hw_timer_enabled;
+       spinlock_t btcoex_lock;
+       struct timer_list period_timer; /* Timer for BT period */
+       u32 bt_priority_cnt;
+       unsigned long bt_priority_time;
+       unsigned long op_flags;
+       int bt_stomp_type; /* Types of BT stomping */
+       u32 btcoex_no_stomp; /* in usec */
+       u32 btcoex_period; /* in usec */
+       u32 btscan_no_stomp; /* in usec */
+       u32 duty_cycle;
+       u32 bt_wait_time;
+       struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
+       struct ath_mci_profile mci;
+};
+
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+int ath9k_init_btcoex(struct ath_softc *sc);
+void ath9k_deinit_btcoex(struct ath_softc *sc);
+void ath9k_start_btcoex(struct ath_softc *sc);
+void ath9k_stop_btcoex(struct ath_softc *sc);
+void ath9k_btcoex_timer_resume(struct ath_softc *sc);
+void ath9k_btcoex_timer_pause(struct ath_softc *sc);
+void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status);
+u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
+void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc);
+#else
+static inline int ath9k_init_btcoex(struct ath_softc *sc)
+{
+       return 0;
+}
+static inline void ath9k_deinit_btcoex(struct ath_softc *sc)
+{
+}
+static inline void ath9k_start_btcoex(struct ath_softc *sc)
+{
+}
+static inline void ath9k_stop_btcoex(struct ath_softc *sc)
+{
+}
+static inline void ath9k_btcoex_handle_interrupt(struct ath_softc *sc,
+                                                u32 status)
+{
+}
+static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc,
+                                         u32 max_4ms_framelen)
+{
+       return 0;
+}
+static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
+{
+}
+#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
+
+/********************/
+/*   LED Control    */
+/********************/
+
+#define ATH_LED_PIN_DEF                1
+#define ATH_LED_PIN_9287               8
+#define ATH_LED_PIN_9300               10
+#define ATH_LED_PIN_9485               6
+#define ATH_LED_PIN_9462               4
+
+#ifdef CONFIG_MAC80211_LEDS
+void ath_init_leds(struct ath_softc *sc);
+void ath_deinit_leds(struct ath_softc *sc);
+#else
+static inline void ath_init_leds(struct ath_softc *sc)
+{
+}
+
+static inline void ath_deinit_leds(struct ath_softc *sc)
+{
+}
+#endif
+
+/*******************************/
+/* Antenna diversity/combining */
+/*******************************/
+
+#define ATH_ANT_RX_CURRENT_SHIFT 4
+#define ATH_ANT_RX_MAIN_SHIFT 2
+#define ATH_ANT_RX_MASK 0x3
+
+#define ATH_ANT_DIV_COMB_SHORT_SCAN_INTR 50
+#define ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT 0x100
+#define ATH_ANT_DIV_COMB_MAX_PKTCOUNT 0x200
+#define ATH_ANT_DIV_COMB_INIT_COUNT 95
+#define ATH_ANT_DIV_COMB_MAX_COUNT 100
+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30
+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20
+
+#define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1
+#define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4
+#define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2
+#define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2
+
+enum ath9k_ant_div_comb_lna_conf {
+       ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
+       ATH_ANT_DIV_COMB_LNA2,
+       ATH_ANT_DIV_COMB_LNA1,
+       ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2,
+};
+
+struct ath_ant_comb {
+       u16 count;
+       u16 total_pkt_count;
+       bool scan;
+       bool scan_not_start;
+       int main_total_rssi;
+       int alt_total_rssi;
+       int alt_recv_cnt;
+       int main_recv_cnt;
+       int rssi_lna1;
+       int rssi_lna2;
+       int rssi_add;
+       int rssi_sub;
+       int rssi_first;
+       int rssi_second;
+       int rssi_third;
+       bool alt_good;
+       int quick_scan_cnt;
+       int main_conf;
+       enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf;
+       enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf;
+       int first_bias;
+       int second_bias;
+       bool first_ratio;
+       bool second_ratio;
+       unsigned long scan_start_time;
+};
+
+void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
+void ath_ant_comb_update(struct ath_softc *sc);
+
+/********************/
+/* Main driver core */
+/********************/
+
+/*
+ * Default cache line size, in bytes.
+ * Used when PCI device not fully initialized by bootrom/BIOS
+*/
+#define DEFAULT_CACHELINE       32
+#define ATH_REGCLASSIDS_MAX     10
+#define ATH_CABQ_READY_TIME     80      /* % of beacon interval */
+#define ATH_MAX_SW_RETRIES      30
+#define ATH_CHAN_MAX            255
+
+#define ATH_TXPOWER_MAX         100     /* .5 dBm units */
+#define ATH_RATE_DUMMY_MARKER   0
+
+enum sc_op_flags {
+       SC_OP_INVALID,
+       SC_OP_BEACONS,
+       SC_OP_RXFLUSH,
+       SC_OP_ANI_RUN,
+       SC_OP_PRIM_STA_VIF,
+       SC_OP_BB_WATCHDOG,
+};
+
+/* Powersave flags */
+#define PS_WAIT_FOR_BEACON        BIT(0)
+#define PS_WAIT_FOR_CAB           BIT(1)
+#define PS_WAIT_FOR_PSPOLL_DATA   BIT(2)
+#define PS_WAIT_FOR_TX_ACK        BIT(3)
+#define PS_BEACON_SYNC            BIT(4)
+
+struct ath_rate_table;
+
+struct ath9k_vif_iter_data {
+       const u8 *hw_macaddr; /* phy's hardware address, set
+                              * before starting iteration for
+                              * valid bssid mask.
+                              */
+       u8 mask[ETH_ALEN]; /* bssid mask */
+       int naps;      /* number of AP vifs */
+       int nmeshes;   /* number of mesh vifs */
+       int nstations; /* number of station vifs */
+       int nwds;      /* number of WDS vifs */
+       int nadhocs;   /* number of adhoc vifs */
+};
+
+struct ath_softc {
+       struct ieee80211_hw *hw;
+       struct device *dev;
+
+       struct survey_info *cur_survey;
+       struct survey_info survey[ATH9K_NUM_CHANNELS];
+
+       struct tasklet_struct intr_tq;
+       struct tasklet_struct bcon_tasklet;
+       struct ath_hw *sc_ah;
+       void __iomem *mem;
+       int irq;
+       spinlock_t sc_serial_rw;
+       spinlock_t sc_pm_lock;
+       spinlock_t sc_pcu_lock;
+       spinlock_t sc_bb_lock;
+       struct mutex mutex;
+       struct work_struct paprd_work;
+       struct work_struct hw_check_work;
+       struct work_struct hw_reset_work;
+       struct completion paprd_complete;
+
+       unsigned int hw_busy_count;
+
+       u32 intrstatus;
+       unsigned long sc_flags;
+       u16 ps_flags; /* PS_* */
+       u16 curtxpow;
+       bool ps_enabled;
+       bool ps_idle;
+       short nbcnvifs;
+       short nvifs;
+       unsigned long ps_usecount;
+
+       struct ath_config config;
+       struct ath_rx rx;
+       struct ath_tx tx;
+       struct ath_beacon beacon;
+       struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+
+#ifdef CONFIG_MAC80211_LEDS
+       bool led_registered;
+       char led_name[32];
+       struct led_classdev led_cdev;
+#endif
+
+       struct ath9k_hw_cal_data caldata;
+       int last_rssi;
+
+#ifdef CONFIG_ATH9K_DEBUGFS
+       struct ath9k_debug debug;
+       spinlock_t nodes_lock;
+       struct list_head nodes; /* basically, stations */
+       unsigned int tx_complete_poll_work_seen;
+#endif
+       struct ath_beacon_config cur_beacon_conf;
+       struct delayed_work tx_complete_work;
+       struct delayed_work hw_pll_work;
+       struct timer_list rx_poll_timer;
+
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+       struct ath_btcoex btcoex;
+       struct ath_mci_coex mci_coex;
+       struct work_struct mci_work;
+#endif
+
+       struct ath_descdma txsdma;
+
+       struct ath_ant_comb ant_comb;
+       u8 ant_tx, ant_rx;
+       atomic_t stop_rx_poll;
+};
+
+void ath9k_tasklet(unsigned long data);
+int ath_cabq_update(struct ath_softc *);
+
+static inline void ath_read_cachesize(struct ath_common *common, int *csz)
+{
+       common->bus_ops->read_cachesize(common, csz);
+}
+
+extern struct ieee80211_ops ath9k_ops;
+extern int ath9k_modparam_nohwcrypt;
+extern int led_blink;
+extern bool is_ath9k_unloaded;
+
+u8 ath9k_parse_mpdudensity(u8 mpdudensity);
+irqreturn_t ath_isr(int irq, void *dev);
+int ath9k_init_device(u16 devid, struct ath_softc *sc,
+                   const struct ath_bus_ops *bus_ops);
+void ath9k_deinit_device(struct ath_softc *sc);
+void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
+void ath9k_reload_chainmask_settings(struct ath_softc *sc);
+
+bool ath9k_uses_beacons(int type);
+
+#ifdef CONFIG_ATH9K_PCI
+int ath_pci_init(void);
+void ath_pci_exit(void);
+#else
+static inline int ath_pci_init(void) { return 0; };
+static inline void ath_pci_exit(void) {};
+#endif
+
+#ifdef CONFIG_ATH9K_AHB
+int ath_ahb_init(void);
+void ath_ahb_exit(void);
+#else
+static inline int ath_ahb_init(void) { return 0; };
+static inline void ath_ahb_exit(void) {};
+#endif
+
+void ath9k_ps_wakeup(struct ath_softc *sc);
+void ath9k_ps_restore(struct ath_softc *sc);
+
+u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
+
+void ath_start_rfkill_poll(struct ath_softc *sc);
+extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
+void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+                              struct ieee80211_vif *vif,
+                              struct ath9k_vif_iter_data *iter_data);
+
+
+#endif /* ATH9K_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/beacon.c b/drivers/net/wireless/ath/ath9k_btcoex/beacon.c
new file mode 100644 (file)
index 0000000..de71ba0
--- /dev/null
@@ -0,0 +1,716 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/dma-mapping.h>
+#include "ath9k.h"
+
+#define FUDGE 2
+
+static void ath9k_reset_beacon_status(struct ath_softc *sc)
+{
+       sc->beacon.tx_processed = false;
+       sc->beacon.tx_last = false;
+}
+
+/*
+ *  This function will modify certain transmit queue properties depending on
+ *  the operating mode of the station (AP or AdHoc).  Parameters are AIFS
+ *  settings and channel width min/max
+*/
+static void ath9k_beaconq_config(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_tx_queue_info qi, qi_be;
+       struct ath_txq *txq;
+
+       ath9k_btcoex_ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
+
+       if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
+               /* Always burst out beacon and CAB traffic. */
+               qi.tqi_aifs = 1;
+               qi.tqi_cwmin = 0;
+               qi.tqi_cwmax = 0;
+       } else {
+               /* Adhoc mode; important thing is to use 2x cwmin. */
+               txq = sc->tx.txq_map[WME_AC_BE];
+               ath9k_btcoex_ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
+               qi.tqi_aifs = qi_be.tqi_aifs;
+               if (ah->slottime == ATH9K_SLOT_TIME_20)
+                       qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
+               else
+                       qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
+               qi.tqi_cwmax = qi_be.tqi_cwmax;
+       }
+
+       if (!ath9k_btcoex_ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
+               ath_err(common, "Unable to update h/w beacon queue parameters\n");
+       } else {
+               ath9k_btcoex_ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
+       }
+}
+
+/*
+ *  Associates the beacon frame buffer with a transmit descriptor.  Will set
+ *  up rate codes, and channel flags. Beacons are always sent out at the
+ *  lowest rate, and are not retried.
+*/
+static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
+                            struct ath_buf *bf, int rateidx)
+{
+       struct sk_buff *skb = bf->bf_mpdu;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_tx_info info;
+       struct ieee80211_supported_band *sband;
+       u8 chainmask = ah->txchainmask;
+       u8 rate = 0;
+
+       sband = &sc->sbands[common->hw->conf.channel->band];
+       rate = sband->bitrates[rateidx].hw_value;
+       if (vif->bss_conf.use_short_preamble)
+               rate |= sband->bitrates[rateidx].hw_value_short;
+
+       memset(&info, 0, sizeof(info));
+       info.pkt_len = skb->len + FCS_LEN;
+       info.type = ATH9K_PKT_TYPE_BEACON;
+       info.txpower = MAX_RATE_POWER;
+       info.keyix = ATH9K_TXKEYIX_INVALID;
+       info.keytype = ATH9K_KEY_TYPE_CLEAR;
+       info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_CLRDMASK;
+
+       info.buf_addr[0] = bf->bf_buf_addr;
+       info.buf_len[0] = roundup(skb->len, 4);
+
+       info.is_first = true;
+       info.is_last = true;
+
+       info.qcu = sc->beacon.beaconq;
+
+       info.rates[0].Tries = 1;
+       info.rates[0].Rate = rate;
+       info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate);
+
+       ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
+}
+
+static void ath9k_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_tx_control txctl;
+
+       memset(&txctl, 0, sizeof(struct ath_tx_control));
+       txctl.txq = sc->beacon.cabq;
+
+       ath_dbg(common, XMIT, "transmitting CABQ packet, skb: %p\n", skb);
+
+       if (ath_tx_start(hw, skb, &txctl) != 0) {
+               ath_dbg(common, XMIT, "CABQ TX failed\n");
+               dev_kfree_skb_any(skb);
+       }
+}
+
+static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
+                                            struct ieee80211_vif *vif)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_buf *bf;
+       struct ath_vif *avp = (void *)vif->drv_priv;
+       struct sk_buff *skb;
+       struct ath_txq *cabq = sc->beacon.cabq;
+       struct ieee80211_tx_info *info;
+       struct ieee80211_mgmt *mgmt_hdr;
+       int cabq_depth;
+
+       if (avp->av_bcbuf == NULL)
+               return NULL;
+
+       bf = avp->av_bcbuf;
+       skb = bf->bf_mpdu;
+       if (skb) {
+               dma_unmap_single(sc->dev, bf->bf_buf_addr,
+                                skb->len, DMA_TO_DEVICE);
+               dev_kfree_skb_any(skb);
+               bf->bf_buf_addr = 0;
+       }
+
+       skb = ieee80211_beacon_get(hw, vif);
+       if (skb == NULL)
+               return NULL;
+
+       bf->bf_mpdu = skb;
+
+       mgmt_hdr = (struct ieee80211_mgmt *)skb->data;
+       mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust;
+
+       info = IEEE80211_SKB_CB(skb);
+       if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+               /*
+                * TODO: make sure the seq# gets assigned properly (vs. other
+                * TX frames)
+                */
+               struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+               sc->tx.seq_no += 0x10;
+               hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+               hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
+       }
+
+       bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+                                        skb->len, DMA_TO_DEVICE);
+       if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
+               dev_kfree_skb_any(skb);
+               bf->bf_mpdu = NULL;
+               bf->bf_buf_addr = 0;
+               ath_err(common, "dma_mapping_error on beaconing\n");
+               return NULL;
+       }
+
+       skb = ieee80211_get_buffered_bc(hw, vif);
+
+       /*
+        * if the CABQ traffic from previous DTIM is pending and the current
+        *  beacon is also a DTIM.
+        *  1) if there is only one vif let the cab traffic continue.
+        *  2) if there are more than one vif and we are using staggered
+        *     beacons, then drain the cabq by dropping all the frames in
+        *     the cabq so that the current vifs cab traffic can be scheduled.
+        */
+       spin_lock_bh(&cabq->axq_lock);
+       cabq_depth = cabq->axq_depth;
+       spin_unlock_bh(&cabq->axq_lock);
+
+       if (skb && cabq_depth) {
+               if (sc->nvifs > 1) {
+                       ath_dbg(common, BEACON,
+                               "Flushing previous cabq traffic\n");
+                       ath_draintxq(sc, cabq, false);
+               }
+       }
+
+       ath9k_beacon_setup(sc, vif, bf, info->control.rates[0].idx);
+
+       while (skb) {
+               ath9k_tx_cabq(hw, skb);
+               skb = ieee80211_get_buffered_bc(hw, vif);
+       }
+
+       return bf;
+}
+
+void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_vif *avp = (void *)vif->drv_priv;
+       int slot;
+
+       avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, struct ath_buf, list);
+       list_del(&avp->av_bcbuf->list);
+
+       for (slot = 0; slot < ATH_BCBUF; slot++) {
+               if (sc->beacon.bslot[slot] == NULL) {
+                       avp->av_bslot = slot;
+                       break;
+               }
+       }
+
+       sc->beacon.bslot[avp->av_bslot] = vif;
+       sc->nbcnvifs++;
+
+       ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n",
+               avp->av_bslot);
+}
+
+void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_vif *avp = (void *)vif->drv_priv;
+       struct ath_buf *bf = avp->av_bcbuf;
+
+       ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n",
+               avp->av_bslot);
+
+       tasklet_disable(&sc->bcon_tasklet);
+
+       if (bf && bf->bf_mpdu) {
+               struct sk_buff *skb = bf->bf_mpdu;
+               dma_unmap_single(sc->dev, bf->bf_buf_addr,
+                                skb->len, DMA_TO_DEVICE);
+               dev_kfree_skb_any(skb);
+               bf->bf_mpdu = NULL;
+               bf->bf_buf_addr = 0;
+       }
+
+       avp->av_bcbuf = NULL;
+       sc->beacon.bslot[avp->av_bslot] = NULL;
+       sc->nbcnvifs--;
+       list_add_tail(&bf->list, &sc->beacon.bbuf);
+
+       tasklet_enable(&sc->bcon_tasklet);
+}
+
+static int ath9k_beacon_choose_slot(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+       u16 intval;
+       u32 tsftu;
+       u64 tsf;
+       int slot;
+
+       if (sc->sc_ah->opmode != NL80211_IFTYPE_AP) {
+               ath_dbg(common, BEACON, "slot 0, tsf: %llu\n",
+                       ath9k_btcoex_ath9k_hw_gettsf64(sc->sc_ah));
+               return 0;
+       }
+
+       intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
+       tsf = ath9k_btcoex_ath9k_hw_gettsf64(sc->sc_ah);
+       tsf += TU_TO_USEC(sc->sc_ah->config.sw_beacon_response_time);
+       tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
+       slot = (tsftu % (intval * ATH_BCBUF)) / intval;
+
+       ath_dbg(common, BEACON, "slot: %d tsf: %llu tsftu: %u\n",
+               slot, tsf, tsftu / ATH_BCBUF);
+
+       return slot;
+}
+
+void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+       struct ath_vif *avp = (void *)vif->drv_priv;
+       u64 tsfadjust;
+
+       if (avp->av_bslot == 0)
+               return;
+
+       tsfadjust = cur_conf->beacon_interval * avp->av_bslot / ATH_BCBUF;
+       avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
+
+       ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n",
+               (unsigned long long)tsfadjust, avp->av_bslot);
+}
+
+void ath9k_beacon_tasklet(unsigned long data)
+{
+       struct ath_softc *sc = (struct ath_softc *)data;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_buf *bf = NULL;
+       struct ieee80211_vif *vif;
+       bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+       int slot;
+
+       if (work_pending(&sc->hw_reset_work)) {
+               ath_dbg(common, RESET,
+                       "reset work is pending, skip beaconing now\n");
+               return;
+       }
+       /*
+        * Check if the previous beacon has gone out.  If
+        * not don't try to post another, skip this period
+        * and wait for the next.  Missed beacons indicate
+        * a problem and should not occur.  If we miss too
+        * many consecutive beacons reset the device.
+        */
+       if (ath9k_btcoex_ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
+               sc->beacon.bmisscnt++;
+
+               if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
+                       ath_dbg(common, BSTUCK,
+                               "missed %u consecutive beacons\n",
+                               sc->beacon.bmisscnt);
+                       ath9k_btcoex_ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
+                       if (sc->beacon.bmisscnt > 3)
+                               ath9k_btcoex_ath9k_hw_bstuck_nfcal(ah);
+               } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
+                       ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
+                       sc->beacon.bmisscnt = 0;
+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+               }
+
+               return;
+       }
+
+       slot = ath9k_beacon_choose_slot(sc);
+       vif = sc->beacon.bslot[slot];
+
+       if (!vif || !vif->bss_conf.enable_beacon)
+               return;
+
+       bf = ath9k_beacon_generate(sc->hw, vif);
+       WARN_ON(!bf);
+
+       if (sc->beacon.bmisscnt != 0) {
+               ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n",
+                       sc->beacon.bmisscnt);
+               sc->beacon.bmisscnt = 0;
+       }
+
+       /*
+        * Handle slot time change when a non-ERP station joins/leaves
+        * an 11g network.  The 802.11 layer notifies us via callback,
+        * we mark updateslot, then wait one beacon before effecting
+        * the change.  This gives associated stations at least one
+        * beacon interval to note the state change.
+        *
+        * NB: The slot time change state machine is clocked according
+        *     to whether we are bursting or staggering beacons.  We
+        *     recognize the request to update and record the current
+        *     slot then don't transition until that slot is reached
+        *     again.  If we miss a beacon for that slot then we'll be
+        *     slow to transition but we'll be sure at least one beacon
+        *     interval has passed.  When bursting slot is always left
+        *     set to ATH_BCBUF so this check is a noop.
+        */
+       if (sc->beacon.updateslot == UPDATE) {
+               sc->beacon.updateslot = COMMIT;
+               sc->beacon.slotupdate = slot;
+       } else if (sc->beacon.updateslot == COMMIT &&
+                  sc->beacon.slotupdate == slot) {
+               ah->slottime = sc->beacon.slottime;
+               ath9k_btcoex_ath9k_hw_init_global_settings(ah);
+               sc->beacon.updateslot = OK;
+       }
+
+       if (bf) {
+               ath9k_reset_beacon_status(sc);
+
+               ath_dbg(common, BEACON,
+                       "Transmitting beacon for slot: %d\n", slot);
+
+               /* NB: cabq traffic should already be queued and primed */
+               ath9k_btcoex_ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
+
+               if (!edma)
+                       ath9k_btcoex_ath9k_hw_txstart(ah, sc->beacon.beaconq);
+       }
+}
+
+static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, u32 intval)
+{
+       struct ath_hw *ah = sc->sc_ah;
+
+       ath9k_btcoex_ath9k_hw_disable_interrupts(ah);
+       ath9k_btcoex_ath9k_hw_reset_tsf(ah);
+       ath9k_beaconq_config(sc);
+       ath9k_btcoex_ath9k_hw_beaconinit(ah, nexttbtt, intval);
+       sc->beacon.bmisscnt = 0;
+       ath9k_btcoex_ath9k_hw_set_interrupts(ah);
+       ath9k_btcoex_ath9k_hw_enable_interrupts(ah);
+}
+
+/*
+ * For multi-bss ap support beacons are either staggered evenly over N slots or
+ * burst together.  For the former arrange for the SWBA to be delivered for each
+ * slot. Slots that are not occupied will generate nothing.
+ */
+static void ath9k_beacon_config_ap(struct ath_softc *sc,
+                                  struct ath_beacon_config *conf)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 nexttbtt, intval;
+
+       /* NB: the beacon interval is kept internally in TU's */
+       intval = TU_TO_USEC(conf->beacon_interval);
+       intval /= ATH_BCBUF;
+       nexttbtt = intval;
+
+       if (conf->enable_beacon)
+               ah->imask |= ATH9K_INT_SWBA;
+       else
+               ah->imask &= ~ATH9K_INT_SWBA;
+
+       ath_dbg(common, BEACON, "AP nexttbtt: %u intval: %u conf_intval: %u\n",
+               nexttbtt, intval, conf->beacon_interval);
+
+       ath9k_beacon_init(sc, nexttbtt, intval);
+}
+
+/*
+ * This sets up the beacon timers according to the timestamp of the last
+ * received beacon and the current TSF, configures PCF and DTIM
+ * handling, programs the sleep registers so the hardware will wakeup in
+ * time to receive beacons, and configures the beacon miss handling so
+ * we'll receive a BMISS interrupt when we stop seeing beacons from the AP
+ * we've associated with.
+ */
+static void ath9k_beacon_config_sta(struct ath_softc *sc,
+                                   struct ath_beacon_config *conf)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_beacon_state bs;
+       int dtimperiod, dtimcount, sleepduration;
+       int cfpperiod, cfpcount;
+       u32 nexttbtt = 0, intval, tsftu;
+       u64 tsf;
+       int num_beacons, offset, dtim_dec_count, cfp_dec_count;
+
+       /* No need to configure beacon if we are not associated */
+       if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
+               ath_dbg(common, BEACON,
+                       "STA is not yet associated..skipping beacon config\n");
+               return;
+       }
+
+       memset(&bs, 0, sizeof(bs));
+       intval = conf->beacon_interval;
+
+       /*
+        * Setup dtim and cfp parameters according to
+        * last beacon we received (which may be none).
+        */
+       dtimperiod = conf->dtim_period;
+       dtimcount = conf->dtim_count;
+       if (dtimcount >= dtimperiod)    /* NB: sanity check */
+               dtimcount = 0;
+       cfpperiod = 1;                  /* NB: no PCF support yet */
+       cfpcount = 0;
+
+       sleepduration = conf->listen_interval * intval;
+
+       /*
+        * Pull nexttbtt forward to reflect the current
+        * TSF and calculate dtim+cfp state for the result.
+        */
+       tsf = ath9k_btcoex_ath9k_hw_gettsf64(ah);
+       tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
+
+       num_beacons = tsftu / intval + 1;
+       offset = tsftu % intval;
+       nexttbtt = tsftu - offset;
+       if (offset)
+               nexttbtt += intval;
+
+       /* DTIM Beacon every dtimperiod Beacon */
+       dtim_dec_count = num_beacons % dtimperiod;
+       /* CFP every cfpperiod DTIM Beacon */
+       cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
+       if (dtim_dec_count)
+               cfp_dec_count++;
+
+       dtimcount -= dtim_dec_count;
+       if (dtimcount < 0)
+               dtimcount += dtimperiod;
+
+       cfpcount -= cfp_dec_count;
+       if (cfpcount < 0)
+               cfpcount += cfpperiod;
+
+       bs.bs_intval = intval;
+       bs.bs_nexttbtt = nexttbtt;
+       bs.bs_dtimperiod = dtimperiod*intval;
+       bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
+       bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
+       bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
+       bs.bs_cfpmaxduration = 0;
+
+       /*
+        * Calculate the number of consecutive beacons to miss* before taking
+        * a BMISS interrupt. The configuration is specified in TU so we only
+        * need calculate based on the beacon interval.  Note that we clamp the
+        * result to at most 15 beacons.
+        */
+       if (sleepduration > intval) {
+               bs.bs_bmissthreshold = conf->listen_interval *
+                       ATH_DEFAULT_BMISS_LIMIT / 2;
+       } else {
+               bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval);
+               if (bs.bs_bmissthreshold > 15)
+                       bs.bs_bmissthreshold = 15;
+               else if (bs.bs_bmissthreshold <= 0)
+                       bs.bs_bmissthreshold = 1;
+       }
+
+       /*
+        * Calculate sleep duration. The configuration is given in ms.
+        * We ensure a multiple of the beacon period is used. Also, if the sleep
+        * duration is greater than the DTIM period then it makes senses
+        * to make it a multiple of that.
+        *
+        * XXX fixed at 100ms
+        */
+
+       bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
+       if (bs.bs_sleepduration > bs.bs_dtimperiod)
+               bs.bs_sleepduration = bs.bs_dtimperiod;
+
+       /* TSF out of range threshold fixed at 1 second */
+       bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
+
+       ath_dbg(common, BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
+       ath_dbg(common, BEACON,
+               "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
+               bs.bs_bmissthreshold, bs.bs_sleepduration,
+               bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
+
+       /* Set the computed STA beacon timers */
+
+       ath9k_btcoex_ath9k_hw_disable_interrupts(ah);
+       ath9k_btcoex_ath9k_hw_set_sta_beacon_timers(ah, &bs);
+       ah->imask |= ATH9K_INT_BMISS;
+
+       ath9k_btcoex_ath9k_hw_set_interrupts(ah);
+       ath9k_btcoex_ath9k_hw_enable_interrupts(ah);
+}
+
+static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
+                                     struct ath_beacon_config *conf)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 intval, nexttbtt;
+
+       ath9k_reset_beacon_status(sc);
+
+       intval = TU_TO_USEC(conf->beacon_interval);
+       nexttbtt = intval;
+
+       if (conf->enable_beacon)
+               ah->imask |= ATH9K_INT_SWBA;
+       else
+               ah->imask &= ~ATH9K_INT_SWBA;
+
+       ath_dbg(common, BEACON, "IBSS nexttbtt: %u intval: %u conf_intval: %u\n",
+               nexttbtt, intval, conf->beacon_interval);
+
+       ath9k_beacon_init(sc, nexttbtt, intval);
+}
+
+bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_vif *avp = (void *)vif->drv_priv;
+
+       if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
+               if ((vif->type != NL80211_IFTYPE_AP) ||
+                   (sc->nbcnvifs > 1)) {
+                       ath_dbg(common, CONFIG,
+                               "An AP interface is already present !\n");
+                       return false;
+               }
+       }
+
+       if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
+               if ((vif->type == NL80211_IFTYPE_STATION) &&
+                   test_bit(SC_OP_BEACONS, &sc->sc_flags) &&
+                   !avp->primary_sta_vif) {
+                       ath_dbg(common, CONFIG,
+                               "Beacon already configured for a station interface\n");
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static void ath9k_cache_beacon_config(struct ath_softc *sc,
+                                     struct ieee80211_bss_conf *bss_conf)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+
+       ath_dbg(common, BEACON,
+               "Caching beacon data for BSS: %pM\n", bss_conf->bssid);
+
+       cur_conf->beacon_interval = bss_conf->beacon_int;
+       cur_conf->dtim_period = bss_conf->dtim_period;
+       cur_conf->listen_interval = 1;
+       cur_conf->dtim_count = 1;
+       cur_conf->bmiss_timeout =
+               ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
+
+       /*
+        * It looks like mac80211 may end up using beacon interval of zero in
+        * some cases (at least for mesh point). Avoid getting into an
+        * infinite loop by using a bit safer value instead. To be safe,
+        * do sanity check on beacon interval for all operating modes.
+        */
+       if (cur_conf->beacon_interval == 0)
+               cur_conf->beacon_interval = 100;
+
+       /*
+        * We don't parse dtim period from mac80211 during the driver
+        * initialization as it breaks association with hidden-ssid
+        * AP and it causes latency in roaming
+        */
+       if (cur_conf->dtim_period == 0)
+               cur_conf->dtim_period = 1;
+
+}
+
+void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
+                        u32 changed)
+{
+       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+       struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+
+       if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
+               ath9k_cache_beacon_config(sc, bss_conf);
+               ath9k_set_beacon(sc);
+               set_bit(SC_OP_BEACONS, &sc->sc_flags);
+       } else {
+               /*
+                * Take care of multiple interfaces when
+                * enabling/disabling SWBA.
+                */
+               if (changed & BSS_CHANGED_BEACON_ENABLED) {
+                       if (!bss_conf->enable_beacon &&
+                           (sc->nbcnvifs <= 1)) {
+                               cur_conf->enable_beacon = false;
+                       } else if (bss_conf->enable_beacon) {
+                               cur_conf->enable_beacon = true;
+                               ath9k_cache_beacon_config(sc, bss_conf);
+                       }
+               }
+
+               if (cur_conf->beacon_interval) {
+                       ath9k_set_beacon(sc);
+
+                       if (cur_conf->enable_beacon)
+                               set_bit(SC_OP_BEACONS, &sc->sc_flags);
+                       else
+                               clear_bit(SC_OP_BEACONS, &sc->sc_flags);
+               }
+       }
+}
+
+void ath9k_set_beacon(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+
+       switch (sc->sc_ah->opmode) {
+       case NL80211_IFTYPE_AP:
+               ath9k_beacon_config_ap(sc, cur_conf);
+               break;
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_MESH_POINT:
+               ath9k_beacon_config_adhoc(sc, cur_conf);
+               break;
+       case NL80211_IFTYPE_STATION:
+               ath9k_beacon_config_sta(sc, cur_conf);
+               break;
+       default:
+               ath_dbg(common, CONFIG, "Unsupported beaconing mode\n");
+               return;
+       }
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/btcoex.c b/drivers/net/wireless/ath/ath9k_btcoex/btcoex.c
new file mode 100644 (file)
index 0000000..f8cb242
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2009-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/export.h>
+#include "hw.h"
+
+enum ath_bt_mode {
+       ATH_BT_COEX_MODE_LEGACY,        /* legacy rx_clear mode */
+       ATH_BT_COEX_MODE_UNSLOTTED,     /* untimed/unslotted mode */
+       ATH_BT_COEX_MODE_SLOTTED,       /* slotted mode */
+       ATH_BT_COEX_MODE_DISABLED,      /* coexistence disabled */
+};
+
+struct ath_btcoex_config {
+       u8 bt_time_extend;
+       bool bt_txstate_extend;
+       bool bt_txframe_extend;
+       enum ath_bt_mode bt_mode; /* coexistence mode */
+       bool bt_quiet_collision;
+       bool bt_rxclear_polarity; /* invert rx_clear as WLAN_ACTIVE*/
+       u8 bt_priority_time;
+       u8 bt_first_slot_time;
+       bool bt_hold_rx_clear;
+};
+
+static const u32 ar9003_wlan_weights[ATH_BTCOEX_STOMP_MAX]
+                                   [AR9300_NUM_WLAN_WEIGHTS] = {
+       { 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0 }, /* STOMP_ALL */
+       { 0x88888880, 0x88888880, 0x88888880, 0x88888880 }, /* STOMP_LOW */
+       { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* STOMP_NONE */
+};
+
+static const u32 ar9462_wlan_weights[ATH_BTCOEX_STOMP_MAX]
+                                   [AR9300_NUM_WLAN_WEIGHTS] = {
+       { 0x01017d01, 0x41414101, 0x41414101, 0x41414141 }, /* STOMP_ALL */
+       { 0x01017d01, 0x3b3b3b01, 0x3b3b3b01, 0x3b3b3b3b }, /* STOMP_LOW */
+       { 0x01017d01, 0x01010101, 0x01010101, 0x01010101 }, /* STOMP_NONE */
+       { 0x01017d01, 0x013b0101, 0x3b3b0101, 0x3b3b013b }, /* STOMP_LOW_FTP */
+};
+
+void ath9k_btcoex_ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
+{
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+       const struct ath_btcoex_config ath_bt_config = {
+               .bt_time_extend = 0,
+               .bt_txstate_extend = true,
+               .bt_txframe_extend = true,
+               .bt_mode = ATH_BT_COEX_MODE_SLOTTED,
+               .bt_quiet_collision = true,
+               .bt_rxclear_polarity = true,
+               .bt_priority_time = 2,
+               .bt_first_slot_time = 5,
+               .bt_hold_rx_clear = true,
+       };
+       u32 i, idx;
+       bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
+
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               rxclear_polarity = !ath_bt_config.bt_rxclear_polarity;
+
+       btcoex_hw->bt_coex_mode =
+               (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) |
+               SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) |
+               SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) |
+               SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |
+               SM(ath_bt_config.bt_mode, AR_BT_MODE) |
+               SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) |
+               SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) |
+               SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) |
+               SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) |
+               SM(qnum, AR_BT_QCU_THRESH);
+
+       btcoex_hw->bt_coex_mode2 =
+               SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
+               SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
+               AR_BT_DISABLE_BT_ANT;
+
+       for (i = 0; i < 32; i++) {
+               idx = (debruijn32 << i) >> 27;
+               ah->hw_gen_timers.gen_timer_index[idx] = i;
+       }
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_init_btcoex_hw);
+
+void ath9k_btcoex_ath9k_hw_btcoex_init_scheme(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+
+       /*
+        * Check if BTCOEX is globally disabled.
+        */
+       if (!common->btcoex_enabled) {
+               btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE;
+               return;
+       }
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
+               btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300;
+               btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300;
+               btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9300;
+       } else if (AR_SREV_9280_20_OR_LATER(ah)) {
+               btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9280;
+               btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9280;
+
+               if (AR_SREV_9285(ah)) {
+                       btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
+                       btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9285;
+               } else {
+                       btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE;
+               }
+       }
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_btcoex_init_scheme);
+
+void ath9k_btcoex_ath9k_hw_btcoex_init_2wire(struct ath_hw *ah)
+{
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+
+       /* connect bt_active to baseband */
+       REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+                   (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
+                    AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
+
+       REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+                   AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
+
+       /* Set input mux for bt_active to gpio pin */
+       REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
+                     AR_GPIO_INPUT_MUX1_BT_ACTIVE,
+                     btcoex_hw->btactive_gpio);
+
+       /* Configure the desired gpio port for input */
+       ath9k_btcoex_ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_btcoex_init_2wire);
+
+void ath9k_btcoex_ath9k_hw_btcoex_init_3wire(struct ath_hw *ah)
+{
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+
+       /* btcoex 3-wire */
+       REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+                       (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
+                        AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB));
+
+       /* Set input mux for bt_prority_async and
+        *                  bt_active_async to GPIO pins */
+       REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
+                       AR_GPIO_INPUT_MUX1_BT_ACTIVE,
+                       btcoex_hw->btactive_gpio);
+
+       REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
+                       AR_GPIO_INPUT_MUX1_BT_PRIORITY,
+                       btcoex_hw->btpriority_gpio);
+
+       /* Configure the desired GPIO ports for input */
+
+       ath9k_btcoex_ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio);
+       ath9k_btcoex_ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btpriority_gpio);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_btcoex_init_3wire);
+
+void ath9k_btcoex_ath9k_hw_btcoex_init_mci(struct ath_hw *ah)
+{
+       ah->btcoex_hw.mci.ready = false;
+       ah->btcoex_hw.mci.bt_state = 0;
+       ah->btcoex_hw.mci.bt_ver_major = 3;
+       ah->btcoex_hw.mci.bt_ver_minor = 0;
+       ah->btcoex_hw.mci.bt_version_known = false;
+       ah->btcoex_hw.mci.update_2g5g = true;
+       ah->btcoex_hw.mci.is_2g = true;
+       ah->btcoex_hw.mci.wlan_channels_update = false;
+       ah->btcoex_hw.mci.wlan_channels[0] = 0x00000000;
+       ah->btcoex_hw.mci.wlan_channels[1] = 0xffffffff;
+       ah->btcoex_hw.mci.wlan_channels[2] = 0xffffffff;
+       ah->btcoex_hw.mci.wlan_channels[3] = 0x7fffffff;
+       ah->btcoex_hw.mci.query_bt = true;
+       ah->btcoex_hw.mci.unhalt_bt_gpm = true;
+       ah->btcoex_hw.mci.halted_bt_gpm = false;
+       ah->btcoex_hw.mci.need_flush_btinfo = false;
+       ah->btcoex_hw.mci.wlan_cal_seq = 0;
+       ah->btcoex_hw.mci.wlan_cal_done = 0;
+       ah->btcoex_hw.mci.config = 0x2201;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_btcoex_init_mci);
+
+static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah)
+{
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+
+       /* Configure the desired GPIO port for TX_FRAME output */
+       ath9k_btcoex_ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
+                           AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
+}
+
+void ath9k_btcoex_ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
+                               u32 bt_weight,
+                               u32 wlan_weight)
+{
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+
+       btcoex_hw->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) |
+                                    SM(wlan_weight, AR_BTCOEX_WL_WGHT);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_btcoex_set_weight);
+
+
+static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
+{
+       struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
+       u32  val;
+       int i;
+
+       /*
+        * Program coex mode and weight registers to
+        * enable coex 3-wire
+        */
+       REG_WRITE(ah, AR_BT_COEX_MODE, btcoex->bt_coex_mode);
+       REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2);
+
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, btcoex->wlan_weight[0]);
+               REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, btcoex->wlan_weight[1]);
+               for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+                       REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS(i),
+                                 btcoex->bt_weight[i]);
+       } else
+               REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex->bt_coex_weights);
+
+
+
+       if (AR_SREV_9271(ah)) {
+               val = REG_READ(ah, 0x50040);
+               val &= 0xFFFFFEFF;
+               REG_WRITE(ah, 0x50040, val);
+       }
+
+       REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
+       REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
+
+       ath9k_btcoex_ath9k_hw_cfg_output(ah, btcoex->wlanactive_gpio,
+                           AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
+}
+
+static void ath9k_hw_btcoex_enable_mci(struct ath_hw *ah)
+{
+       struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
+       int i;
+
+       for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+               REG_WRITE(ah, AR_MCI_COEX_WL_WEIGHTS(i),
+                         btcoex->wlan_weight[i]);
+
+       REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
+       btcoex->enabled = true;
+}
+
+void ath9k_btcoex_ath9k_hw_btcoex_enable(struct ath_hw *ah)
+{
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+
+       switch (ath9k_hw_get_btcoex_scheme(ah)) {
+       case ATH_BTCOEX_CFG_NONE:
+               return;
+       case ATH_BTCOEX_CFG_2WIRE:
+               ath9k_hw_btcoex_enable_2wire(ah);
+               break;
+       case ATH_BTCOEX_CFG_3WIRE:
+               if (AR_SREV_9462(ah)) {
+                       ath9k_hw_btcoex_enable_mci(ah);
+                       return;
+               }
+               ath9k_hw_btcoex_enable_3wire(ah);
+               break;
+       }
+
+       REG_RMW(ah, AR_GPIO_PDPU,
+               (0x2 << (btcoex_hw->btactive_gpio * 2)),
+               (0x3 << (btcoex_hw->btactive_gpio * 2)));
+
+       ah->btcoex_hw.enabled = true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_btcoex_enable);
+
+void ath9k_btcoex_ath9k_hw_btcoex_disable(struct ath_hw *ah)
+{
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+       int i;
+
+       btcoex_hw->enabled = false;
+       if (AR_SREV_9462(ah)) {
+               ath9k_btcoex_ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
+               for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+                       REG_WRITE(ah, AR_MCI_COEX_WL_WEIGHTS(i),
+                                 btcoex_hw->wlan_weight[i]);
+               return;
+       }
+       ath9k_btcoex_ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0);
+
+       ath9k_btcoex_ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
+                       AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+
+       if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) {
+               REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE);
+               REG_WRITE(ah, AR_BT_COEX_MODE2, 0);
+
+               if (AR_SREV_9300_20_OR_LATER(ah)) {
+                       REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, 0);
+                       REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, 0);
+                       for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+                               REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS(i), 0);
+               } else
+                       REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);
+
+       }
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_btcoex_disable);
+
+static void ar9003_btcoex_bt_stomp(struct ath_hw *ah,
+                        enum ath_stomp_type stomp_type)
+{
+       struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
+       const u32 *weight = ar9003_wlan_weights[stomp_type];
+       int i;
+
+       if (AR_SREV_9462(ah)) {
+               if ((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
+                   btcoex->mci.stomp_ftp)
+                       stomp_type = ATH_BTCOEX_STOMP_LOW_FTP;
+               weight = ar9462_wlan_weights[stomp_type];
+       }
+
+       for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
+               btcoex->bt_weight[i] = AR9300_BT_WGHT;
+               btcoex->wlan_weight[i] = weight[i];
+       }
+}
+
+/*
+ * Configures appropriate weight based on stomp type.
+ */
+void ath9k_btcoex_ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
+                             enum ath_stomp_type stomp_type)
+{
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               ar9003_btcoex_bt_stomp(ah, stomp_type);
+               return;
+       }
+
+       switch (stomp_type) {
+       case ATH_BTCOEX_STOMP_ALL:
+               ath9k_btcoex_ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+                               AR_STOMP_ALL_WLAN_WGHT);
+               break;
+       case ATH_BTCOEX_STOMP_LOW:
+               ath9k_btcoex_ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+                               AR_STOMP_LOW_WLAN_WGHT);
+               break;
+       case ATH_BTCOEX_STOMP_NONE:
+               ath9k_btcoex_ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+                               AR_STOMP_NONE_WLAN_WGHT);
+               break;
+       default:
+               ath_dbg(ath9k_hw_common(ah), BTCOEX, "Invalid Stomptype\n");
+               break;
+       }
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_btcoex_bt_stomp);
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/btcoex.h b/drivers/net/wireless/ath/ath9k_btcoex/btcoex.h
new file mode 100644 (file)
index 0000000..6be1eb2
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2009-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef BTCOEX_H
+#define BTCOEX_H
+
+#include "hw.h"
+
+#define ATH_WLANACTIVE_GPIO_9280     5
+#define ATH_BTACTIVE_GPIO_9280       6
+#define ATH_BTPRIORITY_GPIO_9285     7
+
+#define ATH_WLANACTIVE_GPIO_9300     5
+#define ATH_BTACTIVE_GPIO_9300       4
+#define ATH_BTPRIORITY_GPIO_9300     8
+
+#define ATH_BTCOEX_DEF_BT_PERIOD  45
+#define ATH_BTCOEX_DEF_DUTY_CYCLE 55
+#define ATH_BTCOEX_BTSCAN_DUTY_CYCLE 90
+#define ATH_BTCOEX_BMISS_THRESH   50
+
+#define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */
+#define ATH_BT_CNT_THRESHOLD          3
+#define ATH_BT_CNT_SCAN_THRESHOLD      15
+
+#define ATH_BTCOEX_RX_WAIT_TIME       100
+#define ATH_BTCOEX_STOMP_FTP_THRESH   5
+
+#define AR9300_NUM_BT_WEIGHTS   4
+#define AR9300_NUM_WLAN_WEIGHTS 4
+/* Defines the BT AR_BT_COEX_WGHT used */
+enum ath_stomp_type {
+       ATH_BTCOEX_STOMP_ALL,
+       ATH_BTCOEX_STOMP_LOW,
+       ATH_BTCOEX_STOMP_NONE,
+       ATH_BTCOEX_STOMP_LOW_FTP,
+       ATH_BTCOEX_STOMP_MAX
+};
+
+enum ath_btcoex_scheme {
+       ATH_BTCOEX_CFG_NONE,
+       ATH_BTCOEX_CFG_2WIRE,
+       ATH_BTCOEX_CFG_3WIRE,
+};
+
+struct ath9k_hw_mci {
+       u32 raw_intr;
+       u32 rx_msg_intr;
+       u32 cont_status;
+       u32 gpm_addr;
+       u32 gpm_len;
+       u32 gpm_idx;
+       u32 sched_addr;
+       u32 wlan_channels[4];
+       u32 wlan_cal_seq;
+       u32 wlan_cal_done;
+       u32 config;
+       u8 *gpm_buf;
+       bool ready;
+       bool update_2g5g;
+       bool is_2g;
+       bool query_bt;
+       bool unhalt_bt_gpm; /* need send UNHALT */
+       bool halted_bt_gpm; /* HALT sent */
+       bool need_flush_btinfo;
+       bool bt_version_known;
+       bool wlan_channels_update;
+       u8 wlan_ver_major;
+       u8 wlan_ver_minor;
+       u8 bt_ver_major;
+       u8 bt_ver_minor;
+       u8 bt_state;
+       u8 stomp_ftp;
+};
+
+struct ath_btcoex_hw {
+       enum ath_btcoex_scheme scheme;
+       struct ath9k_hw_mci mci;
+       bool enabled;
+       u8 wlanactive_gpio;
+       u8 btactive_gpio;
+       u8 btpriority_gpio;
+       u32 bt_coex_mode;       /* Register setting for AR_BT_COEX_MODE */
+       u32 bt_coex_weights;    /* Register setting for AR_BT_COEX_WEIGHT */
+       u32 bt_coex_mode2;      /* Register setting for AR_BT_COEX_MODE2 */
+       u32 bt_weight[AR9300_NUM_BT_WEIGHTS];
+       u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
+};
+
+void ath9k_btcoex_ath9k_hw_btcoex_init_scheme(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_btcoex_init_2wire(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_btcoex_init_3wire(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_btcoex_init_mci(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum);
+void ath9k_btcoex_ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
+                               u32 bt_weight,
+                               u32 wlan_weight);
+void ath9k_btcoex_ath9k_hw_btcoex_disable(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
+                             enum ath_stomp_type stomp_type);
+
+#endif
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/calib.c b/drivers/net/wireless/ath/ath9k_btcoex/calib.c
new file mode 100644 (file)
index 0000000..fc32151
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+#include <linux/export.h>
+
+/* Common calibration code */
+
+
+static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
+{
+       int16_t nfval;
+       int16_t sort[ATH9K_NF_CAL_HIST_MAX];
+       int i, j;
+
+       for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
+               sort[i] = nfCalBuffer[i];
+
+       for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
+               for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
+                       if (sort[j] > sort[j - 1]) {
+                               nfval = sort[j];
+                               sort[j] = sort[j - 1];
+                               sort[j - 1] = nfval;
+                       }
+               }
+       }
+       nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
+
+       return nfval;
+}
+
+static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah,
+                                                   struct ath9k_channel *chan)
+{
+       struct ath_nf_limits *limit;
+
+       if (!chan || IS_CHAN_2GHZ(chan))
+               limit = &ah->nf_2g;
+       else
+               limit = &ah->nf_5g;
+
+       return limit;
+}
+
+static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
+                                  struct ath9k_channel *chan)
+{
+       return ath9k_hw_get_nf_limits(ah, chan)->nominal;
+}
+
+s16 ath9k_btcoex_ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       s8 noise = ATH_DEFAULT_NOISE_FLOOR;
+
+       if (chan && chan->noisefloor) {
+               s8 delta = chan->noisefloor -
+                          ath9k_hw_get_default_nf(ah, chan);
+               if (delta > 0)
+                       noise += delta;
+       }
+       return noise;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_getchan_noise);
+
+static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
+                                             struct ath9k_hw_cal_data *cal,
+                                             int16_t *nfarray)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_nf_limits *limit;
+       struct ath9k_nfcal_hist *h;
+       bool high_nf_mid = false;
+       u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+       int i;
+
+       h = cal->nfCalHist;
+       limit = ath9k_hw_get_nf_limits(ah, ah->curchan);
+
+       for (i = 0; i < NUM_NF_READINGS; i++) {
+               if (!(chainmask & (1 << i)) ||
+                   ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan)))
+                       continue;
+
+               h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
+
+               if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
+                       h[i].currIndex = 0;
+
+               if (h[i].invalidNFcount > 0) {
+                       h[i].invalidNFcount--;
+                       h[i].privNF = nfarray[i];
+               } else {
+                       h[i].privNF =
+                               ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
+               }
+
+               if (!h[i].privNF)
+                       continue;
+
+               if (h[i].privNF > limit->max) {
+                       high_nf_mid = true;
+
+                       ath_dbg(common, CALIBRATE,
+                               "NFmid[%d] (%d) > MAX (%d), %s\n",
+                               i, h[i].privNF, limit->max,
+                               (cal->nfcal_interference ?
+                                "not corrected (due to interference)" :
+                                "correcting to MAX"));
+
+                       /*
+                        * Normally we limit the average noise floor by the
+                        * hardware specific maximum here. However if we have
+                        * encountered stuck beacons because of interference,
+                        * we bypass this limit here in order to better deal
+                        * with our environment.
+                        */
+                       if (!cal->nfcal_interference)
+                               h[i].privNF = limit->max;
+               }
+       }
+
+       /*
+        * If the noise floor seems normal for all chains, assume that
+        * there is no significant interference in the environment anymore.
+        * Re-enable the enforcement of the NF maximum again.
+        */
+       if (!high_nf_mid)
+               cal->nfcal_interference = false;
+}
+
+static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah,
+                                  enum ieee80211_band band,
+                                  int16_t *nft)
+{
+       switch (band) {
+       case IEEE80211_BAND_5GHZ:
+               *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
+               break;
+       case IEEE80211_BAND_2GHZ:
+               *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
+               break;
+       default:
+               BUG_ON(1);
+               return false;
+       }
+
+       return true;
+}
+
+void ath9k_hw_reset_calibration(struct ath_hw *ah,
+                               struct ath9k_cal_list *currCal)
+{
+       int i;
+
+       ath9k_hw_setup_calibration(ah, currCal);
+
+       currCal->calState = CAL_RUNNING;
+
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               ah->meas0.sign[i] = 0;
+               ah->meas1.sign[i] = 0;
+               ah->meas2.sign[i] = 0;
+               ah->meas3.sign[i] = 0;
+       }
+
+       ah->cal_samples = 0;
+}
+
+/* This is done for the currently configured channel */
+bool ath9k_btcoex_ath9k_hw_reset_calvalid(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_conf *conf = &common->hw->conf;
+       struct ath9k_cal_list *currCal = ah->cal_list_curr;
+
+       if (!ah->caldata)
+               return true;
+
+       if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
+               return true;
+
+       if (currCal == NULL)
+               return true;
+
+       if (currCal->calState != CAL_DONE) {
+               ath_dbg(common, CALIBRATE, "Calibration state incorrect, %d\n",
+                       currCal->calState);
+               return true;
+       }
+
+       if (!(ah->supp_cals & currCal->calData->calType))
+               return true;
+
+       ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n",
+               currCal->calData->calType, conf->channel->center_freq);
+
+       ah->caldata->CalValid &= ~currCal->calData->calType;
+       currCal->calState = CAL_WAITING;
+
+       return false;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_reset_calvalid);
+
+void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update)
+{
+       if (ah->caldata)
+               ah->caldata->nfcal_pending = true;
+
+       REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_ENABLE_NF);
+
+       if (update)
+               REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+       else
+               REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+
+       REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+}
+
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       struct ath9k_nfcal_hist *h = NULL;
+       unsigned i, j;
+       int32_t val;
+       u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_conf *conf = &common->hw->conf;
+       s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
+
+       if (ah->caldata)
+               h = ah->caldata->nfCalHist;
+
+       for (i = 0; i < NUM_NF_READINGS; i++) {
+               if (chainmask & (1 << i)) {
+                       s16 nfval;
+
+                       if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))
+                               continue;
+
+                       if (h)
+                               nfval = h[i].privNF;
+                       else
+                               nfval = default_nf;
+
+                       val = REG_READ(ah, ah->nf_regs[i]);
+                       val &= 0xFFFFFE00;
+                       val |= (((u32) nfval << 1) & 0x1ff);
+                       REG_WRITE(ah, ah->nf_regs[i], val);
+               }
+       }
+
+       /*
+        * Load software filtered NF value into baseband internal minCCApwr
+        * variable.
+        */
+       REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_ENABLE_NF);
+       REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+       REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+       /*
+        * Wait for load to complete, should be fast, a few 10s of us.
+        * The max delay was changed from an original 250us to 10000us
+        * since 250us often results in NF load timeout and causes deaf
+        * condition during stress testing 12/12/2009
+        */
+       for (j = 0; j < 10000; j++) {
+               if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
+                    AR_PHY_AGC_CONTROL_NF) == 0)
+                       break;
+               udelay(10);
+       }
+
+       /*
+        * We timed out waiting for the noisefloor to load, probably due to an
+        * in-progress rx. Simply return here and allow the load plenty of time
+        * to complete before the next calibration interval.  We need to avoid
+        * trying to load -50 (which happens below) while the previous load is
+        * still in progress as this can cause rx deafness. Instead by returning
+        * here, the baseband nf cal will just be capped by our present
+        * noisefloor until the next calibration timer.
+        */
+       if (j == 10000) {
+               ath_dbg(common, ANY,
+                       "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
+                       REG_READ(ah, AR_PHY_AGC_CONTROL));
+               return;
+       }
+
+       /*
+        * Restore maxCCAPower register parameter again so that we're not capped
+        * by the median we just loaded.  This will be initial (and max) value
+        * of next noise floor calibration the baseband does.
+        */
+       ENABLE_REGWRITE_BUFFER(ah);
+       for (i = 0; i < NUM_NF_READINGS; i++) {
+               if (chainmask & (1 << i)) {
+                       if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))
+                               continue;
+
+                       val = REG_READ(ah, ah->nf_regs[i]);
+                       val &= 0xFFFFFE00;
+                       val |= (((u32) (-50) << 1) & 0x1ff);
+                       REG_WRITE(ah, ah->nf_regs[i], val);
+               }
+       }
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+
+static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_nf_limits *limit;
+       int i;
+
+       if (IS_CHAN_2GHZ(ah->curchan))
+               limit = &ah->nf_2g;
+       else
+               limit = &ah->nf_5g;
+
+       for (i = 0; i < NUM_NF_READINGS; i++) {
+               if (!nf[i])
+                       continue;
+
+               ath_dbg(common, CALIBRATE,
+                       "NF calibrated [%s] [chain %d] is %d\n",
+                       (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
+
+               if (nf[i] > limit->max) {
+                       ath_dbg(common, CALIBRATE,
+                               "NF[%d] (%d) > MAX (%d), correcting to MAX\n",
+                               i, nf[i], limit->max);
+                       nf[i] = limit->max;
+               } else if (nf[i] < limit->min) {
+                       ath_dbg(common, CALIBRATE,
+                               "NF[%d] (%d) < MIN (%d), correcting to NOM\n",
+                               i, nf[i], limit->min);
+                       nf[i] = limit->nominal;
+               }
+       }
+}
+
+bool ath9k_btcoex_ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       int16_t nf, nfThresh;
+       int16_t nfarray[NUM_NF_READINGS] = { 0 };
+       struct ath9k_nfcal_hist *h;
+       struct ieee80211_channel *c = chan->chan;
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+
+       chan->channelFlags &= (~CHANNEL_CW_INT);
+       if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
+               ath_dbg(common, CALIBRATE,
+                       "NF did not complete in calibration window\n");
+               return false;
+       }
+
+       ath9k_hw_do_getnf(ah, nfarray);
+       ath9k_hw_nf_sanitize(ah, nfarray);
+       nf = nfarray[0];
+       if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
+           && nf > nfThresh) {
+               ath_dbg(common, CALIBRATE,
+                       "noise floor failed detected; detected %d, threshold %d\n",
+                       nf, nfThresh);
+               chan->channelFlags |= CHANNEL_CW_INT;
+       }
+
+       if (!caldata) {
+               chan->noisefloor = nf;
+               ah->noise = ath9k_btcoex_ath9k_hw_getchan_noise(ah, chan);
+               return false;
+       }
+
+       h = caldata->nfCalHist;
+       caldata->nfcal_pending = false;
+       ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
+       chan->noisefloor = h[0].privNF;
+       ah->noise = ath9k_btcoex_ath9k_hw_getchan_noise(ah, chan);
+       return true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_getnf);
+
+void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
+                                 struct ath9k_channel *chan)
+{
+       struct ath9k_nfcal_hist *h;
+       s16 default_nf;
+       int i, j;
+
+       ah->caldata->channel = chan->channel;
+       ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
+       h = ah->caldata->nfCalHist;
+       default_nf = ath9k_hw_get_default_nf(ah, chan);
+       for (i = 0; i < NUM_NF_READINGS; i++) {
+               h[i].currIndex = 0;
+               h[i].privNF = default_nf;
+               h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH;
+               for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
+                       h[i].nfCalBuffer[j] = default_nf;
+               }
+       }
+}
+
+
+void ath9k_btcoex_ath9k_hw_bstuck_nfcal(struct ath_hw *ah)
+{
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+
+       if (unlikely(!caldata))
+               return;
+
+       /*
+        * If beacons are stuck, the most likely cause is interference.
+        * Triggering a noise floor calibration at this point helps the
+        * hardware adapt to a noisy environment much faster.
+        * To ensure that we recover from stuck beacons quickly, let
+        * the baseband update the internal NF value itself, similar to
+        * what is being done after a full reset.
+        */
+       if (!caldata->nfcal_pending)
+               ath9k_hw_start_nfcal(ah, true);
+       else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF))
+               ath9k_btcoex_ath9k_hw_getnf(ah, ah->curchan);
+
+       caldata->nfcal_interference = true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_bstuck_nfcal);
+
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/calib.h b/drivers/net/wireless/ath/ath9k_btcoex/calib.h
new file mode 100644 (file)
index 0000000..5fdcff5
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef CALIB_H
+#define CALIB_H
+
+#include "hw.h"
+
+#define AR_PHY_CCA_FILTERWINDOW_LENGTH          5
+
+#define NUM_NF_READINGS       6
+#define ATH9K_NF_CAL_HIST_MAX 5
+
+struct ar5416IniArray {
+       u32 *ia_array;
+       u32 ia_rows;
+       u32 ia_columns;
+};
+
+#define INIT_INI_ARRAY(iniarray, array, rows, columns) do {    \
+               (iniarray)->ia_array = (u32 *)(array);          \
+               (iniarray)->ia_rows = (rows);                   \
+               (iniarray)->ia_columns = (columns);             \
+       } while (0)
+
+#define INI_RA(iniarray, row, column) \
+       (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)])
+
+#define INIT_CAL(_perCal) do {                         \
+               (_perCal)->calState = CAL_WAITING;      \
+               (_perCal)->calNext = NULL;              \
+       } while (0)
+
+#define INSERT_CAL(_ahp, _perCal)                                      \
+       do {                                                            \
+               if ((_ahp)->cal_list_last == NULL) {                    \
+                       (_ahp)->cal_list =                              \
+                               (_ahp)->cal_list_last = (_perCal);      \
+                       ((_ahp)->cal_list_last)->calNext = (_perCal); \
+               } else {                                                \
+                       ((_ahp)->cal_list_last)->calNext = (_perCal); \
+                       (_ahp)->cal_list_last = (_perCal);              \
+                       (_perCal)->calNext = (_ahp)->cal_list;  \
+               }                                                       \
+       } while (0)
+
+enum ath9k_cal_state {
+       CAL_INACTIVE,
+       CAL_WAITING,
+       CAL_RUNNING,
+       CAL_DONE
+};
+
+#define MIN_CAL_SAMPLES     1
+#define MAX_CAL_SAMPLES    64
+#define INIT_LOG_COUNT      5
+#define PER_MIN_LOG_COUNT   2
+#define PER_MAX_LOG_COUNT  10
+
+struct ath9k_percal_data {
+       u32 calType;
+       u32 calNumSamples;
+       u32 calCountMax;
+       void (*calCollect) (struct ath_hw *);
+       void (*calPostProc) (struct ath_hw *, u8);
+};
+
+struct ath9k_cal_list {
+       const struct ath9k_percal_data *calData;
+       enum ath9k_cal_state calState;
+       struct ath9k_cal_list *calNext;
+};
+
+struct ath9k_nfcal_hist {
+       int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX];
+       u8 currIndex;
+       int16_t privNF;
+       u8 invalidNFcount;
+};
+
+#define MAX_PACAL_SKIPCOUNT 8
+struct ath9k_pacal_info{
+       int32_t prev_offset;    /* Previous value of PA offset value */
+       int8_t max_skipcount;   /* Max No. of times PACAL can be skipped */
+       int8_t skipcount;       /* No. of times the PACAL to be skipped */
+};
+
+bool ath9k_btcoex_ath9k_hw_reset_calvalid(struct ath_hw *ah);
+void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update);
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
+bool ath9k_btcoex_ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
+void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
+                                 struct ath9k_channel *chan);
+void ath9k_btcoex_ath9k_hw_bstuck_nfcal(struct ath_hw *ah);
+void ath9k_hw_reset_calibration(struct ath_hw *ah,
+                               struct ath9k_cal_list *currCal);
+s16 ath9k_btcoex_ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
+
+
+#endif /* CALIB_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/common.c b/drivers/net/wireless/ath/ath9k_btcoex/common.c
new file mode 100644 (file)
index 0000000..a703309
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2009-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Module for common driver code between ath9k and ath9k_htc
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "common.h"
+
+MODULE_AUTHOR("Atheros Communications");
+MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
+MODULE_LICENSE("Dual BSD/GPL");
+
+int ath9k_btcoex_ath9k_cmn_padpos(__le16 frame_control)
+{
+       int padpos = 24;
+       if (ieee80211_has_a4(frame_control)) {
+               padpos += ETH_ALEN;
+       }
+       if (ieee80211_is_data_qos(frame_control)) {
+               padpos += IEEE80211_QOS_CTL_LEN;
+       }
+
+       return padpos;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_cmn_padpos);
+
+int ath9k_btcoex_ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+
+       if (tx_info->control.hw_key) {
+               switch (tx_info->control.hw_key->cipher) {
+               case WLAN_CIPHER_SUITE_WEP40:
+               case WLAN_CIPHER_SUITE_WEP104:
+                       return ATH9K_KEY_TYPE_WEP;
+               case WLAN_CIPHER_SUITE_TKIP:
+                       return ATH9K_KEY_TYPE_TKIP;
+               case WLAN_CIPHER_SUITE_CCMP:
+                       return ATH9K_KEY_TYPE_AES;
+               default:
+                       break;
+               }
+       }
+
+       return ATH9K_KEY_TYPE_CLEAR;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_cmn_get_hw_crypto_keytype);
+
+static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan,
+                                enum nl80211_channel_type channel_type)
+{
+       u32 chanmode = 0;
+
+       switch (chan->band) {
+       case IEEE80211_BAND_2GHZ:
+               switch (channel_type) {
+               case NL80211_CHAN_NO_HT:
+               case NL80211_CHAN_HT20:
+                       chanmode = CHANNEL_G_HT20;
+                       break;
+               case NL80211_CHAN_HT40PLUS:
+                       chanmode = CHANNEL_G_HT40PLUS;
+                       break;
+               case NL80211_CHAN_HT40MINUS:
+                       chanmode = CHANNEL_G_HT40MINUS;
+                       break;
+               }
+               break;
+       case IEEE80211_BAND_5GHZ:
+               switch (channel_type) {
+               case NL80211_CHAN_NO_HT:
+               case NL80211_CHAN_HT20:
+                       chanmode = CHANNEL_A_HT20;
+                       break;
+               case NL80211_CHAN_HT40PLUS:
+                       chanmode = CHANNEL_A_HT40PLUS;
+                       break;
+               case NL80211_CHAN_HT40MINUS:
+                       chanmode = CHANNEL_A_HT40MINUS;
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return chanmode;
+}
+
+/*
+ * Update internal channel flags.
+ */
+void ath9k_btcoex_ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+                              struct ieee80211_channel *chan,
+                              enum nl80211_channel_type channel_type)
+{
+       ichan->channel = chan->center_freq;
+       ichan->chan = chan;
+
+       if (chan->band == IEEE80211_BAND_2GHZ) {
+               ichan->chanmode = CHANNEL_G;
+               ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
+       } else {
+               ichan->chanmode = CHANNEL_A;
+               ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
+       }
+
+       if (channel_type != NL80211_CHAN_NO_HT)
+               ichan->chanmode = ath9k_get_extchanmode(chan, channel_type);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_cmn_update_ichannel);
+
+/*
+ * Get the internal channel reference.
+ */
+struct ath9k_channel *ath9k_btcoex_ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
+                                              struct ath_hw *ah)
+{
+       struct ieee80211_channel *curchan = hw->conf.channel;
+       struct ath9k_channel *channel;
+       u8 chan_idx;
+
+       chan_idx = curchan->hw_value;
+       channel = &ah->channels[chan_idx];
+       ath9k_btcoex_ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
+
+       return channel;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_cmn_get_curchannel);
+
+int ath9k_btcoex_ath9k_cmn_count_streams(unsigned int chainmask, int max)
+{
+       int streams = 0;
+
+       do {
+               if (++streams == max)
+                       break;
+       } while ((chainmask = chainmask & (chainmask - 1)));
+
+       return streams;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_cmn_count_streams);
+
+void ath9k_btcoex_ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+                           u16 new_txpow, u16 *txpower)
+{
+       struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+
+       if (reg->power_limit != new_txpow) {
+               ath9k_btcoex_ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
+               /* read back in case value is clamped */
+               *txpower = reg->max_power_level;
+       }
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_cmn_update_txpow);
+
+void ath9k_btcoex_ath9k_cmn_init_crypto(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       int i = 0;
+
+       /* Get the hardware key cache size. */
+       common->keymax = AR_KEYTABLE_SIZE;
+
+       /*
+        * Check whether the separate key cache entries
+        * are required to handle both tx+rx MIC keys.
+        * With split mic keys the number of stations is limited
+        * to 27 otherwise 59.
+        */
+       if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
+               common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
+
+       /*
+        * Reset the key cache since some parts do not
+        * reset the contents on initial power up.
+        */
+       for (i = 0; i < common->keymax; i++)
+               ath_hw_keyreset(common, (u16) i);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_cmn_init_crypto);
+
+static int __init ath9k_cmn_init(void)
+{
+       return 0;
+}
+module_init(ath9k_cmn_init);
+
+static void __exit ath9k_cmn_exit(void)
+{
+       return;
+}
+module_exit(ath9k_cmn_exit);
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/common.h b/drivers/net/wireless/ath/ath9k_btcoex/common.h
new file mode 100644 (file)
index 0000000..db2bf45
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <net/mac80211.h>
+
+#include "../ath.h"
+
+#include "hw.h"
+#include "hw-ops.h"
+
+/* Common header for Atheros 802.11n base driver cores */
+
+#define WME_NUM_TID             16
+#define WME_BA_BMP_SIZE         64
+#define WME_MAX_BA              WME_BA_BMP_SIZE
+#define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
+
+/* These must match mac80211 skb queue mapping numbers */
+#define WME_AC_VO   0
+#define WME_AC_VI   1
+#define WME_AC_BE   2
+#define WME_AC_BK   3
+#define WME_NUM_AC  4
+
+#define ATH_RSSI_DUMMY_MARKER   0x127
+#define ATH_RSSI_LPF_LEN               10
+#define RSSI_LPF_THRESHOLD             -20
+#define ATH_RSSI_EP_MULTIPLIER     (1<<7)
+#define ATH_EP_MUL(x, mul)         ((x) * (mul))
+#define ATH_RSSI_IN(x)             (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
+#define ATH_LPF_RSSI(x, y, len) \
+    ((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y))
+#define ATH_RSSI_LPF(x, y) do {                                        \
+    if ((y) >= RSSI_LPF_THRESHOLD)                                     \
+       x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN);      \
+} while (0)
+#define ATH_EP_RND(x, mul)                                             \
+       ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+
+int ath9k_btcoex_ath9k_cmn_padpos(__le16 frame_control);
+int ath9k_btcoex_ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
+void ath9k_btcoex_ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+                              struct ieee80211_channel *chan,
+                              enum nl80211_channel_type channel_type);
+struct ath9k_channel *ath9k_btcoex_ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
+                                              struct ath_hw *ah);
+int ath9k_btcoex_ath9k_cmn_count_streams(unsigned int chainmask, int max);
+void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
+                                 enum ath_stomp_type stomp_type);
+void ath9k_btcoex_ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+                           u16 new_txpow, u16 *txpower);
+void ath9k_btcoex_ath9k_cmn_init_crypto(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/debug.c b/drivers/net/wireless/ath/ath9k_btcoex/debug.c
new file mode 100644 (file)
index 0000000..e2ad70a
--- /dev/null
@@ -0,0 +1,1629 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/export.h>
+#include <asm/unaligned.h>
+
+#include "ath9k.h"
+
+#define REG_WRITE_D(_ah, _reg, _val) \
+       ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg))
+#define REG_READ_D(_ah, _reg) \
+       ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
+
+static int ath9k_debugfs_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+
+static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       u8 *buf = file->private_data;
+       return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
+}
+
+static int ath9k_debugfs_release_buf(struct inode *inode, struct file *file)
+{
+       vfree(file->private_data);
+       return 0;
+}
+
+#ifdef CONFIG_ATH_DEBUG
+
+static ssize_t read_file_debug(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "0x%08x\n", common->debug_mask);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       unsigned long mask;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (strict_strtoul(buf, 0, &mask))
+               return -EINVAL;
+
+       common->debug_mask = mask;
+       return count;
+}
+
+static const struct file_operations fops_debug = {
+       .read = read_file_debug,
+       .write = write_file_debug,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+#endif
+
+#define DMA_BUF_LEN 1024
+
+static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "0x%08x\n", ah->txchainmask);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_tx_chainmask(struct file *file, const char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       unsigned long mask;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (strict_strtoul(buf, 0, &mask))
+               return -EINVAL;
+
+       ah->txchainmask = mask;
+       ah->caps.tx_chainmask = mask;
+       return count;
+}
+
+static const struct file_operations fops_tx_chainmask = {
+       .read = read_file_tx_chainmask,
+       .write = write_file_tx_chainmask,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+
+static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "0x%08x\n", ah->rxchainmask);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_rx_chainmask(struct file *file, const char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       unsigned long mask;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (strict_strtoul(buf, 0, &mask))
+               return -EINVAL;
+
+       ah->rxchainmask = mask;
+       ah->caps.rx_chainmask = mask;
+       return count;
+}
+
+static const struct file_operations fops_rx_chainmask = {
+       .read = read_file_rx_chainmask,
+       .write = write_file_rx_chainmask,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_disable_ani(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "%d\n", common->disable_ani);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_disable_ani(struct file *file,
+                                     const char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       unsigned long disable_ani;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (strict_strtoul(buf, 0, &disable_ani))
+               return -EINVAL;
+
+       common->disable_ani = !!disable_ani;
+
+       if (disable_ani) {
+               clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+               del_timer_sync(&common->ani.timer);
+       } else {
+               set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+               ath_start_ani(common);
+       }
+
+       return count;
+}
+
+static const struct file_operations fops_disable_ani = {
+       .read = read_file_disable_ani,
+       .write = write_file_disable_ani,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_dma(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       char *buf;
+       int retval;
+       unsigned int len = 0;
+       u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
+       int i, qcuOffset = 0, dcuOffset = 0;
+       u32 *qcuBase = &val[0], *dcuBase = &val[4];
+
+       buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ath9k_ps_wakeup(sc);
+
+       REG_WRITE_D(ah, AR_MACMISC,
+                 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+                  (AR_MACMISC_MISC_OBS_BUS_1 <<
+                   AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
+       len += snprintf(buf + len, DMA_BUF_LEN - len,
+                       "Raw DMA Debug values:\n");
+
+       for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
+               if (i % 4 == 0)
+                       len += snprintf(buf + len, DMA_BUF_LEN - len, "\n");
+
+               val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32)));
+               len += snprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ",
+                               i, val[i]);
+       }
+
+       len += snprintf(buf + len, DMA_BUF_LEN - len, "\n\n");
+       len += snprintf(buf + len, DMA_BUF_LEN - len,
+                       "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
+
+       for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
+               if (i == 8) {
+                       qcuOffset = 0;
+                       qcuBase++;
+               }
+
+               if (i == 6) {
+                       dcuOffset = 0;
+                       dcuBase++;
+               }
+
+               len += snprintf(buf + len, DMA_BUF_LEN - len,
+                       "%2d          %2x      %1x     %2x           %2x\n",
+                       i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+                       (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
+                       val[2] & (0x7 << (i * 3)) >> (i * 3),
+                       (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+       }
+
+       len += snprintf(buf + len, DMA_BUF_LEN - len, "\n");
+
+       len += snprintf(buf + len, DMA_BUF_LEN - len,
+               "qcu_stitch state:   %2x    qcu_fetch state:        %2x\n",
+               (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
+       len += snprintf(buf + len, DMA_BUF_LEN - len,
+               "qcu_complete state: %2x    dcu_complete state:     %2x\n",
+               (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
+       len += snprintf(buf + len, DMA_BUF_LEN - len,
+               "dcu_arb state:      %2x    dcu_fp state:           %2x\n",
+               (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
+       len += snprintf(buf + len, DMA_BUF_LEN - len,
+               "chan_idle_dur:     %3d    chan_idle_dur_valid:     %1d\n",
+               (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
+       len += snprintf(buf + len, DMA_BUF_LEN - len,
+               "txfifo_valid_0:      %1d    txfifo_valid_1:          %1d\n",
+               (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
+       len += snprintf(buf + len, DMA_BUF_LEN - len,
+               "txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
+               (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
+
+       len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n",
+                       REG_READ_D(ah, AR_OBS_BUS_1));
+       len += snprintf(buf + len, DMA_BUF_LEN - len,
+                       "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR));
+
+       ath9k_ps_restore(sc);
+
+       if (len > DMA_BUF_LEN)
+               len = DMA_BUF_LEN;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+       return retval;
+}
+
+static const struct file_operations fops_dma = {
+       .read = read_file_dma,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+
+void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
+{
+       if (status)
+               sc->debug.stats.istats.total++;
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               if (status & ATH9K_INT_RXLP)
+                       sc->debug.stats.istats.rxlp++;
+               if (status & ATH9K_INT_RXHP)
+                       sc->debug.stats.istats.rxhp++;
+               if (status & ATH9K_INT_BB_WATCHDOG)
+                       sc->debug.stats.istats.bb_watchdog++;
+       } else {
+               if (status & ATH9K_INT_RX)
+                       sc->debug.stats.istats.rxok++;
+       }
+       if (status & ATH9K_INT_RXEOL)
+               sc->debug.stats.istats.rxeol++;
+       if (status & ATH9K_INT_RXORN)
+               sc->debug.stats.istats.rxorn++;
+       if (status & ATH9K_INT_TX)
+               sc->debug.stats.istats.txok++;
+       if (status & ATH9K_INT_TXURN)
+               sc->debug.stats.istats.txurn++;
+       if (status & ATH9K_INT_RXPHY)
+               sc->debug.stats.istats.rxphyerr++;
+       if (status & ATH9K_INT_RXKCM)
+               sc->debug.stats.istats.rx_keycache_miss++;
+       if (status & ATH9K_INT_SWBA)
+               sc->debug.stats.istats.swba++;
+       if (status & ATH9K_INT_BMISS)
+               sc->debug.stats.istats.bmiss++;
+       if (status & ATH9K_INT_BNR)
+               sc->debug.stats.istats.bnr++;
+       if (status & ATH9K_INT_CST)
+               sc->debug.stats.istats.cst++;
+       if (status & ATH9K_INT_GTT)
+               sc->debug.stats.istats.gtt++;
+       if (status & ATH9K_INT_TIM)
+               sc->debug.stats.istats.tim++;
+       if (status & ATH9K_INT_CABEND)
+               sc->debug.stats.istats.cabend++;
+       if (status & ATH9K_INT_DTIMSYNC)
+               sc->debug.stats.istats.dtimsync++;
+       if (status & ATH9K_INT_DTIM)
+               sc->debug.stats.istats.dtim++;
+       if (status & ATH9K_INT_TSFOOR)
+               sc->debug.stats.istats.tsfoor++;
+       if (status & ATH9K_INT_MCI)
+               sc->debug.stats.istats.mci++;
+}
+
+static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
+                                  size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char buf[512];
+       unsigned int len = 0;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               len += snprintf(buf + len, sizeof(buf) - len,
+                       "%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp);
+               len += snprintf(buf + len, sizeof(buf) - len,
+                       "%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp);
+               len += snprintf(buf + len, sizeof(buf) - len,
+                       "%8s: %10u\n", "WATCHDOG",
+                       sc->debug.stats.istats.bb_watchdog);
+       } else {
+               len += snprintf(buf + len, sizeof(buf) - len,
+                       "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
+       }
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "TX", sc->debug.stats.istats.txok);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "MIB", sc->debug.stats.istats.mib);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "CST", sc->debug.stats.istats.cst);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "TIM", sc->debug.stats.istats.tim);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "TSFOOR", sc->debug.stats.istats.tsfoor);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "MCI", sc->debug.stats.istats.mci);
+       len += snprintf(buf + len, sizeof(buf) - len,
+               "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total);
+
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_interrupt = {
+       .read = read_file_interrupt,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
+#define PR(str, elem)                                                  \
+       do {                                                            \
+               len += snprintf(buf + len, size - len,                  \
+                               "%s%13u%11u%10u%10u\n", str,            \
+               sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem, \
+               sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem, \
+               sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem, \
+               sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem); \
+               if (len >= size)                          \
+                       goto done;                        \
+} while(0)
+
+#define PRX(str, elem)                                                 \
+do {                                                                   \
+       len += snprintf(buf + len, size - len,                          \
+                       "%s%13u%11u%10u%10u\n", str,                    \
+                       (unsigned int)(sc->tx.txq_map[WME_AC_BE]->elem),        \
+                       (unsigned int)(sc->tx.txq_map[WME_AC_BK]->elem),        \
+                       (unsigned int)(sc->tx.txq_map[WME_AC_VI]->elem),        \
+                       (unsigned int)(sc->tx.txq_map[WME_AC_VO]->elem));       \
+       if (len >= size)                                                \
+               goto done;                                              \
+} while(0)
+
+#define PRQLE(str, elem)                                               \
+do {                                                                   \
+       len += snprintf(buf + len, size - len,                          \
+                       "%s%13i%11i%10i%10i\n", str,                    \
+                       list_empty(&sc->tx.txq_map[WME_AC_BE]->elem),   \
+                       list_empty(&sc->tx.txq_map[WME_AC_BK]->elem),   \
+                       list_empty(&sc->tx.txq_map[WME_AC_VI]->elem),   \
+                       list_empty(&sc->tx.txq_map[WME_AC_VO]->elem));  \
+       if (len >= size)                                                \
+               goto done;                                              \
+} while (0)
+
+static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
+                             size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char *buf;
+       unsigned int len = 0, size = 8000;
+       int i;
+       ssize_t retval = 0;
+       char tmp[32];
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       len += sprintf(buf, "Num-Tx-Queues: %i  tx-queues-setup: 0x%x"
+                      " poll-work-seen: %u\n"
+                      "%30s %10s%10s%10s\n\n",
+                      ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup,
+                      sc->tx_complete_poll_work_seen,
+                      "BE", "BK", "VI", "VO");
+
+       PR("MPDUs Queued:    ", queued);
+       PR("MPDUs Completed: ", completed);
+       PR("MPDUs XRetried:  ", xretries);
+       PR("Aggregates:      ", a_aggr);
+       PR("AMPDUs Queued HW:", a_queued_hw);
+       PR("AMPDUs Queued SW:", a_queued_sw);
+       PR("AMPDUs Completed:", a_completed);
+       PR("AMPDUs Retried:  ", a_retries);
+       PR("AMPDUs XRetried: ", a_xretries);
+       PR("FIFO Underrun:   ", fifo_underrun);
+       PR("TXOP Exceeded:   ", xtxop);
+       PR("TXTIMER Expiry:  ", timer_exp);
+       PR("DESC CFG Error:  ", desc_cfg_err);
+       PR("DATA Underrun:   ", data_underrun);
+       PR("DELIM Underrun:  ", delim_underrun);
+       PR("TX-Pkts-All:     ", tx_pkts_all);
+       PR("TX-Bytes-All:    ", tx_bytes_all);
+       PR("hw-put-tx-buf:   ", puttxbuf);
+       PR("hw-tx-start:     ", txstart);
+       PR("hw-tx-proc-desc: ", txprocdesc);
+       len += snprintf(buf + len, size - len,
+                       "%s%11p%11p%10p%10p\n", "txq-memory-address:",
+                       sc->tx.txq_map[WME_AC_BE],
+                       sc->tx.txq_map[WME_AC_BK],
+                       sc->tx.txq_map[WME_AC_VI],
+                       sc->tx.txq_map[WME_AC_VO]);
+       if (len >= size)
+               goto done;
+
+       PRX("axq-qnum:        ", axq_qnum);
+       PRX("axq-depth:       ", axq_depth);
+       PRX("axq-ampdu_depth: ", axq_ampdu_depth);
+       PRX("axq-stopped      ", stopped);
+       PRX("tx-in-progress   ", axq_tx_inprogress);
+       PRX("pending-frames   ", pending_frames);
+       PRX("txq_headidx:     ", txq_headidx);
+       PRX("txq_tailidx:     ", txq_headidx);
+
+       PRQLE("axq_q empty:       ", axq_q);
+       PRQLE("axq_acq empty:     ", axq_acq);
+       for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
+               snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
+               PRQLE(tmp, txq_fifo[i]);
+       }
+
+       /* Print out more detailed queue-info */
+       for (i = 0; i <= WME_AC_BK; i++) {
+               struct ath_txq *txq = &(sc->tx.txq[i]);
+               struct ath_atx_ac *ac;
+               struct ath_atx_tid *tid;
+               if (len >= size)
+                       goto done;
+               spin_lock_bh(&txq->axq_lock);
+               if (!list_empty(&txq->axq_acq)) {
+                       ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac,
+                                             list);
+                       len += snprintf(buf + len, size - len,
+                                       "txq[%i] first-ac: %p sched: %i\n",
+                                       i, ac, ac->sched);
+                       if (list_empty(&ac->tid_q) || (len >= size))
+                               goto done_for;
+                       tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
+                                              list);
+                       len += snprintf(buf + len, size - len,
+                                       " first-tid: %p sched: %i paused: %i\n",
+                                       tid, tid->sched, tid->paused);
+               }
+       done_for:
+               spin_unlock_bh(&txq->axq_lock);
+       }
+
+done:
+       if (len > size)
+               len = size;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static ssize_t read_file_stations(struct file *file, char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char *buf;
+       unsigned int len = 0, size = 64000;
+       struct ath_node *an = NULL;
+       ssize_t retval = 0;
+       int q;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       len += snprintf(buf + len, size - len,
+                       "Stations:\n"
+                       " tid: addr sched paused buf_q-empty an ac baw\n"
+                       " ac: addr sched tid_q-empty txq\n");
+
+       spin_lock(&sc->nodes_lock);
+       list_for_each_entry(an, &sc->nodes, list) {
+               unsigned short ma = an->maxampdu;
+               if (ma == 0)
+                       ma = 65535; /* see ath_lookup_rate */
+               len += snprintf(buf + len, size - len,
+                               "iface: %pM  sta: %pM max-ampdu: %hu mpdu-density: %uus\n",
+                               an->vif->addr, an->sta->addr, ma,
+                               (unsigned int)(an->mpdudensity));
+               if (len >= size)
+                       goto done;
+
+               for (q = 0; q < WME_NUM_TID; q++) {
+                       struct ath_atx_tid *tid = &(an->tid[q]);
+                       len += snprintf(buf + len, size - len,
+                                       " tid: %p %s %s %i %p %p %hu\n",
+                                       tid, tid->sched ? "sched" : "idle",
+                                       tid->paused ? "paused" : "running",
+                                       skb_queue_empty(&tid->buf_q),
+                                       tid->an, tid->ac, tid->baw_size);
+                       if (len >= size)
+                               goto done;
+               }
+
+               for (q = 0; q < WME_NUM_AC; q++) {
+                       struct ath_atx_ac *ac = &(an->ac[q]);
+                       len += snprintf(buf + len, size - len,
+                                       " ac: %p %s %i %p\n",
+                                       ac, ac->sched ? "sched" : "idle",
+                                       list_empty(&ac->tid_q), ac->txq);
+                       if (len >= size)
+                               goto done;
+               }
+       }
+
+done:
+       spin_unlock(&sc->nodes_lock);
+       if (len > size)
+               len = size;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static ssize_t read_file_misc(struct file *file, char __user *user_buf,
+                             size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ieee80211_hw *hw = sc->hw;
+       struct ath9k_vif_iter_data iter_data;
+       char buf[512];
+       unsigned int len = 0;
+       ssize_t retval = 0;
+       unsigned int reg;
+       u32 rxfilter;
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "BSSID: %pM\n", common->curbssid);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "BSSID-MASK: %pM\n", common->bssidmask);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "OPMODE: %s\n", ath_opmode_to_string(sc->sc_ah->opmode));
+
+       ath9k_ps_wakeup(sc);
+       rxfilter = ath9k_btcoex_ath9k_hw_getrxfilter(sc->sc_ah);
+       ath9k_ps_restore(sc);
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "RXFILTER: 0x%x", rxfilter);
+
+       if (rxfilter & ATH9K_RX_FILTER_UCAST)
+               len += snprintf(buf + len, sizeof(buf) - len, " UCAST");
+       if (rxfilter & ATH9K_RX_FILTER_MCAST)
+               len += snprintf(buf + len, sizeof(buf) - len, " MCAST");
+       if (rxfilter & ATH9K_RX_FILTER_BCAST)
+               len += snprintf(buf + len, sizeof(buf) - len, " BCAST");
+       if (rxfilter & ATH9K_RX_FILTER_CONTROL)
+               len += snprintf(buf + len, sizeof(buf) - len, " CONTROL");
+       if (rxfilter & ATH9K_RX_FILTER_BEACON)
+               len += snprintf(buf + len, sizeof(buf) - len, " BEACON");
+       if (rxfilter & ATH9K_RX_FILTER_PROM)
+               len += snprintf(buf + len, sizeof(buf) - len, " PROM");
+       if (rxfilter & ATH9K_RX_FILTER_PROBEREQ)
+               len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
+       if (rxfilter & ATH9K_RX_FILTER_PHYERR)
+               len += snprintf(buf + len, sizeof(buf) - len, " PHYERR");
+       if (rxfilter & ATH9K_RX_FILTER_MYBEACON)
+               len += snprintf(buf + len, sizeof(buf) - len, " MYBEACON");
+       if (rxfilter & ATH9K_RX_FILTER_COMP_BAR)
+               len += snprintf(buf + len, sizeof(buf) - len, " COMP_BAR");
+       if (rxfilter & ATH9K_RX_FILTER_PSPOLL)
+               len += snprintf(buf + len, sizeof(buf) - len, " PSPOLL");
+       if (rxfilter & ATH9K_RX_FILTER_PHYRADAR)
+               len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
+       if (rxfilter & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
+               len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL");
+       if (rxfilter & ATH9K_RX_FILTER_CONTROL_WRAPPER)
+               len += snprintf(buf + len, sizeof(buf) - len, " CONTROL_WRAPPER");
+
+       len += snprintf(buf + len, sizeof(buf) - len, "\n");
+
+       reg = sc->sc_ah->imask;
+
+       len += snprintf(buf + len, sizeof(buf) - len, "INTERRUPT-MASK: 0x%x", reg);
+
+       if (reg & ATH9K_INT_SWBA)
+               len += snprintf(buf + len, sizeof(buf) - len, " SWBA");
+       if (reg & ATH9K_INT_BMISS)
+               len += snprintf(buf + len, sizeof(buf) - len, " BMISS");
+       if (reg & ATH9K_INT_CST)
+               len += snprintf(buf + len, sizeof(buf) - len, " CST");
+       if (reg & ATH9K_INT_RX)
+               len += snprintf(buf + len, sizeof(buf) - len, " RX");
+       if (reg & ATH9K_INT_RXHP)
+               len += snprintf(buf + len, sizeof(buf) - len, " RXHP");
+       if (reg & ATH9K_INT_RXLP)
+               len += snprintf(buf + len, sizeof(buf) - len, " RXLP");
+       if (reg & ATH9K_INT_BB_WATCHDOG)
+               len += snprintf(buf + len, sizeof(buf) - len, " BB_WATCHDOG");
+
+       len += snprintf(buf + len, sizeof(buf) - len, "\n");
+
+       ath9k_calculate_iter_data(hw, NULL, &iter_data);
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i"
+                       " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
+                       iter_data.naps, iter_data.nstations, iter_data.nmeshes,
+                       iter_data.nwds, iter_data.nadhocs,
+                       sc->nvifs, sc->nbcnvifs);
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       return retval;
+}
+
+static ssize_t read_file_reset(struct file *file, char __user *user_buf,
+                              size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char buf[512];
+       unsigned int len = 0;
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%17s: %2d\n", "Baseband Hang",
+                       sc->debug.stats.reset[RESET_TYPE_BB_HANG]);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%17s: %2d\n", "Baseband Watchdog",
+                       sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG]);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%17s: %2d\n", "Fatal HW Error",
+                       sc->debug.stats.reset[RESET_TYPE_FATAL_INT]);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%17s: %2d\n", "TX HW error",
+                       sc->debug.stats.reset[RESET_TYPE_TX_ERROR]);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%17s: %2d\n", "TX Path Hang",
+                       sc->debug.stats.reset[RESET_TYPE_TX_HANG]);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%17s: %2d\n", "PLL RX Hang",
+                       sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
+                      struct ath_tx_status *ts, struct ath_txq *txq,
+                      unsigned int flags)
+{
+#define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\
+                       [sc->debug.tsidx].c)
+       int qnum = txq->axq_qnum;
+
+       TX_STAT_INC(qnum, tx_pkts_all);
+       sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
+
+       if (bf_isampdu(bf)) {
+               if (flags & ATH_TX_ERROR)
+                       TX_STAT_INC(qnum, a_xretries);
+               else
+                       TX_STAT_INC(qnum, a_completed);
+       } else {
+               if (ts->ts_status & ATH9K_TXERR_XRETRY)
+                       TX_STAT_INC(qnum, xretries);
+               else
+                       TX_STAT_INC(qnum, completed);
+       }
+
+       if (ts->ts_status & ATH9K_TXERR_FIFO)
+               TX_STAT_INC(qnum, fifo_underrun);
+       if (ts->ts_status & ATH9K_TXERR_XTXOP)
+               TX_STAT_INC(qnum, xtxop);
+       if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
+               TX_STAT_INC(qnum, timer_exp);
+       if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
+               TX_STAT_INC(qnum, desc_cfg_err);
+       if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
+               TX_STAT_INC(qnum, data_underrun);
+       if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
+               TX_STAT_INC(qnum, delim_underrun);
+
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+       spin_lock(&sc->debug.samp_lock);
+       TX_SAMP_DBG(jiffies) = jiffies;
+       TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0;
+       TX_SAMP_DBG(rssi_ctl1) = ts->ts_rssi_ctl1;
+       TX_SAMP_DBG(rssi_ctl2) = ts->ts_rssi_ctl2;
+       TX_SAMP_DBG(rssi_ext0) = ts->ts_rssi_ext0;
+       TX_SAMP_DBG(rssi_ext1) = ts->ts_rssi_ext1;
+       TX_SAMP_DBG(rssi_ext2) = ts->ts_rssi_ext2;
+       TX_SAMP_DBG(rateindex) = ts->ts_rateindex;
+       TX_SAMP_DBG(isok) = !!(ts->ts_status & ATH9K_TXERR_MASK);
+       TX_SAMP_DBG(rts_fail_cnt) = ts->ts_shortretry;
+       TX_SAMP_DBG(data_fail_cnt) = ts->ts_longretry;
+       TX_SAMP_DBG(rssi) = ts->ts_rssi;
+       TX_SAMP_DBG(tid) = ts->tid;
+       TX_SAMP_DBG(qid) = ts->qid;
+
+       if (ts->ts_flags & ATH9K_TX_BA) {
+               TX_SAMP_DBG(ba_low) = ts->ba_low;
+               TX_SAMP_DBG(ba_high) = ts->ba_high;
+       } else {
+               TX_SAMP_DBG(ba_low) = 0;
+               TX_SAMP_DBG(ba_high) = 0;
+       }
+
+       sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES;
+       spin_unlock(&sc->debug.samp_lock);
+#endif
+
+#undef TX_SAMP_DBG
+}
+
+static const struct file_operations fops_xmit = {
+       .read = read_file_xmit,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static const struct file_operations fops_stations = {
+       .read = read_file_stations,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static const struct file_operations fops_misc = {
+       .read = read_file_misc,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static const struct file_operations fops_reset = {
+       .read = read_file_reset,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_recv(struct file *file, char __user *user_buf,
+                             size_t count, loff_t *ppos)
+{
+#define PHY_ERR(s, p) \
+       len += snprintf(buf + len, size - len, "%22s : %10u\n", s, \
+                       sc->debug.stats.rxstats.phy_err_stats[p]);
+
+       struct ath_softc *sc = file->private_data;
+       char *buf;
+       unsigned int len = 0, size = 1600;
+       ssize_t retval = 0;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       len += snprintf(buf + len, size - len,
+                       "%22s : %10u\n", "CRC ERR",
+                       sc->debug.stats.rxstats.crc_err);
+       len += snprintf(buf + len, size - len,
+                       "%22s : %10u\n", "DECRYPT CRC ERR",
+                       sc->debug.stats.rxstats.decrypt_crc_err);
+       len += snprintf(buf + len, size - len,
+                       "%22s : %10u\n", "PHY ERR",
+                       sc->debug.stats.rxstats.phy_err);
+       len += snprintf(buf + len, size - len,
+                       "%22s : %10u\n", "MIC ERR",
+                       sc->debug.stats.rxstats.mic_err);
+       len += snprintf(buf + len, size - len,
+                       "%22s : %10u\n", "PRE-DELIM CRC ERR",
+                       sc->debug.stats.rxstats.pre_delim_crc_err);
+       len += snprintf(buf + len, size - len,
+                       "%22s : %10u\n", "POST-DELIM CRC ERR",
+                       sc->debug.stats.rxstats.post_delim_crc_err);
+       len += snprintf(buf + len, size - len,
+                       "%22s : %10u\n", "DECRYPT BUSY ERR",
+                       sc->debug.stats.rxstats.decrypt_busy_err);
+
+       PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);
+       PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING);
+       PHY_ERR("PARITY ERR", ATH9K_PHYERR_PARITY);
+       PHY_ERR("RATE ERR", ATH9K_PHYERR_RATE);
+       PHY_ERR("LENGTH ERR", ATH9K_PHYERR_LENGTH);
+       PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR);
+       PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE);
+       PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR);
+       PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING);
+       PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
+       PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
+       PHY_ERR("OFDM-LENGTH ERR", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
+       PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP);
+       PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE);
+       PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART);
+       PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
+       PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING);
+       PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC);
+       PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
+       PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
+       PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
+       PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
+       PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP);
+       PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR);
+       PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
+       PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
+
+       len += snprintf(buf + len, size - len,
+                       "%22s : %10u\n", "RX-Pkts-All",
+                       sc->debug.stats.rxstats.rx_pkts_all);
+       len += snprintf(buf + len, size - len,
+                       "%22s : %10u\n", "RX-Bytes-All",
+                       sc->debug.stats.rxstats.rx_bytes_all);
+
+       if (len > size)
+               len = size;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+
+#undef PHY_ERR
+}
+
+void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
+{
+#define RX_STAT_INC(c) sc->debug.stats.rxstats.c++
+#define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
+#define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\
+                       [sc->debug.rsidx].c)
+
+       RX_STAT_INC(rx_pkts_all);
+       sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen;
+
+       if (rs->rs_status & ATH9K_RXERR_CRC)
+               RX_STAT_INC(crc_err);
+       if (rs->rs_status & ATH9K_RXERR_DECRYPT)
+               RX_STAT_INC(decrypt_crc_err);
+       if (rs->rs_status & ATH9K_RXERR_MIC)
+               RX_STAT_INC(mic_err);
+       if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
+               RX_STAT_INC(pre_delim_crc_err);
+       if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST)
+               RX_STAT_INC(post_delim_crc_err);
+       if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY)
+               RX_STAT_INC(decrypt_busy_err);
+
+       if (rs->rs_status & ATH9K_RXERR_PHY) {
+               RX_STAT_INC(phy_err);
+               if (rs->rs_phyerr < ATH9K_PHYERR_MAX)
+                       RX_PHY_ERR_INC(rs->rs_phyerr);
+       }
+
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+       spin_lock(&sc->debug.samp_lock);
+       RX_SAMP_DBG(jiffies) = jiffies;
+       RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
+       RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1;
+       RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2;
+       RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0;
+       RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1;
+       RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2;
+       RX_SAMP_DBG(antenna) = rs->rs_antenna;
+       RX_SAMP_DBG(rssi) = rs->rs_rssi;
+       RX_SAMP_DBG(rate) = rs->rs_rate;
+       RX_SAMP_DBG(is_mybeacon) = rs->is_mybeacon;
+
+       sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES;
+       spin_unlock(&sc->debug.samp_lock);
+
+#endif
+
+#undef RX_STAT_INC
+#undef RX_PHY_ERR_INC
+#undef RX_SAMP_DBG
+}
+
+static const struct file_operations fops_recv = {
+       .read = read_file_recv,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
+                                size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "0x%08x\n", sc->debug.regidx);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_regidx(struct file *file, const char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       unsigned long regidx;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (strict_strtoul(buf, 0, &regidx))
+               return -EINVAL;
+
+       sc->debug.regidx = regidx;
+       return count;
+}
+
+static const struct file_operations fops_regidx = {
+       .read = read_file_regidx,
+       .write = write_file_regidx,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_regval(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       char buf[32];
+       unsigned int len;
+       u32 regval;
+
+       ath9k_ps_wakeup(sc);
+       regval = REG_READ_D(ah, sc->debug.regidx);
+       ath9k_ps_restore(sc);
+       len = sprintf(buf, "0x%08x\n", regval);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_regval(struct file *file, const char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       unsigned long regval;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (strict_strtoul(buf, 0, &regval))
+               return -EINVAL;
+
+       ath9k_ps_wakeup(sc);
+       REG_WRITE_D(ah, sc->debug.regidx, regval);
+       ath9k_ps_restore(sc);
+       return count;
+}
+
+static const struct file_operations fops_regval = {
+       .read = read_file_regval,
+       .write = write_file_regval,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+#define REGDUMP_LINE_SIZE      20
+
+static int open_file_regdump(struct inode *inode, struct file *file)
+{
+       struct ath_softc *sc = inode->i_private;
+       unsigned int len = 0;
+       u8 *buf;
+       int i;
+       unsigned long num_regs, regdump_len, max_reg_offset;
+
+       max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x16bd4 : 0xb500;
+       num_regs = max_reg_offset / 4 + 1;
+       regdump_len = num_regs * REGDUMP_LINE_SIZE + 1;
+       buf = vmalloc(regdump_len);
+       if (!buf)
+               return -ENOMEM;
+
+       ath9k_ps_wakeup(sc);
+       for (i = 0; i < num_regs; i++)
+               len += scnprintf(buf + len, regdump_len - len,
+                       "0x%06x 0x%08x\n", i << 2, REG_READ(sc->sc_ah, i << 2));
+       ath9k_ps_restore(sc);
+
+       file->private_data = buf;
+
+       return 0;
+}
+
+static const struct file_operations fops_regdump = {
+       .open = open_file_regdump,
+       .read = ath9k_debugfs_read_buf,
+       .release = ath9k_debugfs_release_buf,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,/* read accesses f_pos */
+};
+
+static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf,
+                                   size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_conf *conf = &common->hw->conf;
+       u32 len = 0, size = 1500;
+       u32 i, j;
+       ssize_t retval = 0;
+       char *buf;
+       u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+       u8 nread;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       len += snprintf(buf + len, size - len,
+                       "Channel Noise Floor : %d\n", ah->noise);
+       len += snprintf(buf + len, size - len,
+                       "Chain | privNF | # Readings | NF Readings\n");
+       for (i = 0; i < NUM_NF_READINGS; i++) {
+               if (!(chainmask & (1 << i)) ||
+                   ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+                       continue;
+
+               nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount;
+               len += snprintf(buf + len, size - len, " %d\t %d\t %d\t\t",
+                               i, h[i].privNF, nread);
+               for (j = 0; j < nread; j++)
+                       len += snprintf(buf + len, size - len,
+                                       " %d", h[i].nfCalBuffer[j]);
+               len += snprintf(buf + len, size - len, "\n");
+       }
+
+       if (len > size)
+               len = size;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static const struct file_operations fops_dump_nfcal = {
+       .read = read_file_dump_nfcal,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       u32 len = 0, size = 1500;
+       ssize_t retval = 0;
+       char *buf;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size);
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static const struct file_operations fops_base_eeprom = {
+       .read = read_file_base_eeprom,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       u32 len = 0, size = 6000;
+       char *buf;
+       size_t retval;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size);
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static const struct file_operations fops_modal_eeprom = {
+       .read = read_file_modal_eeprom,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+
+void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
+{
+#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c)
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       unsigned long flags;
+       int i;
+
+       ath9k_ps_wakeup(sc);
+
+       spin_lock_bh(&sc->debug.samp_lock);
+
+       spin_lock_irqsave(&common->cc_lock, flags);
+       ath_hw_cycle_counters_update(common);
+
+       ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles;
+       ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy;
+       ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame;
+       ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame;
+       spin_unlock_irqrestore(&common->cc_lock, flags);
+
+       ATH_SAMP_DBG(noise) = ah->noise;
+
+       REG_WRITE_D(ah, AR_MACMISC,
+                 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+                  (AR_MACMISC_MISC_OBS_BUS_1 <<
+                   AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
+       for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+               ATH_SAMP_DBG(dma_dbg_reg_vals[i]) = REG_READ_D(ah,
+                               AR_DMADBG_0 + (i * sizeof(u32)));
+
+       ATH_SAMP_DBG(pcu_obs) = REG_READ_D(ah, AR_OBS_BUS_1);
+       ATH_SAMP_DBG(pcu_cr) = REG_READ_D(ah, AR_CR);
+
+       memcpy(ATH_SAMP_DBG(nfCalHist), sc->caldata.nfCalHist,
+                       sizeof(ATH_SAMP_DBG(nfCalHist)));
+
+       sc->debug.sampidx = (sc->debug.sampidx + 1) % ATH_DBG_MAX_SAMPLES;
+       spin_unlock_bh(&sc->debug.samp_lock);
+       ath9k_ps_restore(sc);
+
+#undef ATH_SAMP_DBG
+}
+
+static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
+{
+#define ATH_SAMP_DBG(c) bb_mac_samp[sampidx].c
+       struct ath_softc *sc = inode->i_private;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_conf *conf = &common->hw->conf;
+       struct ath_dbg_bb_mac_samp *bb_mac_samp;
+       struct ath9k_nfcal_hist *h;
+       int i, j, qcuOffset = 0, dcuOffset = 0;
+       u32 *qcuBase, *dcuBase, size = 30000, len = 0;
+       u32 sampidx = 0;
+       u8 *buf;
+       u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+       u8 nread;
+
+       if (test_bit(SC_OP_INVALID, &sc->sc_flags))
+               return -EAGAIN;
+
+       buf = vmalloc(size);
+       if (!buf)
+               return -ENOMEM;
+       bb_mac_samp = vmalloc(sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
+       if (!bb_mac_samp) {
+               vfree(buf);
+               return -ENOMEM;
+       }
+       /* Account the current state too */
+       ath9k_debug_samp_bb_mac(sc);
+
+       spin_lock_bh(&sc->debug.samp_lock);
+       memcpy(bb_mac_samp, sc->debug.bb_mac_samp,
+                       sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
+       len += snprintf(buf + len, size - len,
+                       "Current Sample Index: %d\n", sc->debug.sampidx);
+       spin_unlock_bh(&sc->debug.samp_lock);
+
+       len += snprintf(buf + len, size - len,
+                       "Raw DMA Debug Dump:\n");
+       len += snprintf(buf + len, size - len, "Sample |\t");
+       for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+               len += snprintf(buf + len, size - len, " DMA Reg%d |\t", i);
+       len += snprintf(buf + len, size - len, "\n");
+
+       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+               len += snprintf(buf + len, size - len, "%d\t", sampidx);
+
+               for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+                       len += snprintf(buf + len, size - len, " %08x\t",
+                                       ATH_SAMP_DBG(dma_dbg_reg_vals[i]));
+               len += snprintf(buf + len, size - len, "\n");
+       }
+       len += snprintf(buf + len, size - len, "\n");
+
+       len += snprintf(buf + len, size - len,
+                       "Sample Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
+       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+               qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]);
+               dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]);
+
+               for (i = 0; i < ATH9K_NUM_QUEUES; i++,
+                               qcuOffset += 4, dcuOffset += 5) {
+                       if (i == 8) {
+                               qcuOffset = 0;
+                               qcuBase++;
+                       }
+
+                       if (i == 6) {
+                               dcuOffset = 0;
+                               dcuBase++;
+                       }
+                       if (!sc->debug.stats.txstats[i].queued)
+                               continue;
+
+                       len += snprintf(buf + len, size - len,
+                               "%4d %7d    %2x      %1x     %2x         %2x\n",
+                               sampidx, i,
+                               (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+                               (*qcuBase & (0x8 << qcuOffset)) >>
+                               (qcuOffset + 3),
+                               ATH_SAMP_DBG(dma_dbg_reg_vals[2]) &
+                               (0x7 << (i * 3)) >> (i * 3),
+                               (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+               }
+               len += snprintf(buf + len, size - len, "\n");
+       }
+       len += snprintf(buf + len, size - len,
+                       "samp qcu_sh qcu_fh qcu_comp dcu_comp dcu_arb dcu_fp "
+                       "ch_idle_dur ch_idle_dur_val txfifo_val0 txfifo_val1 "
+                       "txfifo_dcu0 txfifo_dcu1 pcu_obs AR_CR\n");
+
+       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+               qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]);
+               dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]);
+
+               len += snprintf(buf + len, size - len, "%4d %5x %5x ", sampidx,
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x003c0000) >> 18,
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x03c00000) >> 22);
+               len += snprintf(buf + len, size - len, "%7x %8x ",
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x1c000000) >> 26,
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x3));
+               len += snprintf(buf + len, size - len, "%7x %7x ",
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x06000000) >> 25,
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x38000000) >> 27);
+               len += snprintf(buf + len, size - len, "%7d %12d ",
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x000003fc) >> 2,
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000400) >> 10);
+               len += snprintf(buf + len, size - len, "%12d %12d ",
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000800) >> 11,
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00001000) >> 12);
+               len += snprintf(buf + len, size - len, "%12d %12d ",
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x0001e000) >> 13,
+                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x001e0000) >> 17);
+               len += snprintf(buf + len, size - len, "0x%07x 0x%07x\n",
+                               ATH_SAMP_DBG(pcu_obs), ATH_SAMP_DBG(pcu_cr));
+       }
+
+       len += snprintf(buf + len, size - len,
+                       "Sample ChNoise Chain privNF #Reading Readings\n");
+       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+               h = ATH_SAMP_DBG(nfCalHist);
+               if (!ATH_SAMP_DBG(noise))
+                       continue;
+
+               for (i = 0; i < NUM_NF_READINGS; i++) {
+                       if (!(chainmask & (1 << i)) ||
+                           ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+                               continue;
+
+                       nread = AR_PHY_CCA_FILTERWINDOW_LENGTH -
+                               h[i].invalidNFcount;
+                       len += snprintf(buf + len, size - len,
+                                       "%4d %5d %4d\t   %d\t %d\t",
+                                       sampidx, ATH_SAMP_DBG(noise),
+                                       i, h[i].privNF, nread);
+                       for (j = 0; j < nread; j++)
+                               len += snprintf(buf + len, size - len,
+                                       " %d", h[i].nfCalBuffer[j]);
+                       len += snprintf(buf + len, size - len, "\n");
+               }
+       }
+       len += snprintf(buf + len, size - len, "\nCycle counters:\n"
+                       "Sample Total    Rxbusy   Rxframes Txframes\n");
+       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+               if (!ATH_SAMP_DBG(cc.cycles))
+                       continue;
+               len += snprintf(buf + len, size - len,
+                               "%4d %08x %08x %08x %08x\n",
+                               sampidx, ATH_SAMP_DBG(cc.cycles),
+                               ATH_SAMP_DBG(cc.rx_busy),
+                               ATH_SAMP_DBG(cc.rx_frame),
+                               ATH_SAMP_DBG(cc.tx_frame));
+       }
+
+       len += snprintf(buf + len, size - len, "Tx status Dump :\n");
+       len += snprintf(buf + len, size - len,
+                       "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb "
+                       "isok rts_fail data_fail rate tid qid "
+                                       "ba_low  ba_high tx_before(ms)\n");
+       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+               for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
+                       if (!ATH_SAMP_DBG(ts[i].jiffies))
+                               continue;
+                       len += snprintf(buf + len, size - len, "%-14d"
+                               "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-8d "
+                               "%-9d %-4d %-3d %-3d %08x %08x %-11d\n",
+                               sampidx,
+                               ATH_SAMP_DBG(ts[i].rssi_ctl0),
+                               ATH_SAMP_DBG(ts[i].rssi_ctl1),
+                               ATH_SAMP_DBG(ts[i].rssi_ctl2),
+                               ATH_SAMP_DBG(ts[i].rssi_ext0),
+                               ATH_SAMP_DBG(ts[i].rssi_ext1),
+                               ATH_SAMP_DBG(ts[i].rssi_ext2),
+                               ATH_SAMP_DBG(ts[i].rssi),
+                               ATH_SAMP_DBG(ts[i].isok),
+                               ATH_SAMP_DBG(ts[i].rts_fail_cnt),
+                               ATH_SAMP_DBG(ts[i].data_fail_cnt),
+                               ATH_SAMP_DBG(ts[i].rateindex),
+                               ATH_SAMP_DBG(ts[i].tid),
+                               ATH_SAMP_DBG(ts[i].qid),
+                               ATH_SAMP_DBG(ts[i].ba_low),
+                               ATH_SAMP_DBG(ts[i].ba_high),
+                               jiffies_to_msecs(jiffies -
+                                       ATH_SAMP_DBG(ts[i].jiffies)));
+               }
+       }
+
+       len += snprintf(buf + len, size - len, "Rx status Dump :\n");
+       len += snprintf(buf + len, size - len, "Sample rssi:- ctl0 ctl1 ctl2 "
+                       "ext0 ext1 ext2 comb beacon ant rate rx_before(ms)\n");
+       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+               for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
+                       if (!ATH_SAMP_DBG(rs[i].jiffies))
+                               continue;
+                       len += snprintf(buf + len, size - len, "%-14d"
+                               "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-9s %-2d %02x %-13d\n",
+                               sampidx,
+                               ATH_SAMP_DBG(rs[i].rssi_ctl0),
+                               ATH_SAMP_DBG(rs[i].rssi_ctl1),
+                               ATH_SAMP_DBG(rs[i].rssi_ctl2),
+                               ATH_SAMP_DBG(rs[i].rssi_ext0),
+                               ATH_SAMP_DBG(rs[i].rssi_ext1),
+                               ATH_SAMP_DBG(rs[i].rssi_ext2),
+                               ATH_SAMP_DBG(rs[i].rssi),
+                               ATH_SAMP_DBG(rs[i].is_mybeacon) ?
+                               "True" : "False",
+                               ATH_SAMP_DBG(rs[i].antenna),
+                               ATH_SAMP_DBG(rs[i].rate),
+                               jiffies_to_msecs(jiffies -
+                                       ATH_SAMP_DBG(rs[i].jiffies)));
+               }
+       }
+
+       vfree(bb_mac_samp);
+       file->private_data = buf;
+
+       return 0;
+#undef ATH_SAMP_DBG
+}
+
+static const struct file_operations fops_samps = {
+       .open = open_file_bb_mac_samps,
+       .read = ath9k_debugfs_read_buf,
+       .release = ath9k_debugfs_release_buf,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+#endif
+
+static ssize_t read_file_dump_eep_power(struct file *file,
+                                       char __user *user_buf,
+                                       size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_hw *ah = sc->sc_ah;
+       u32 len = 0, size = 6000;
+       ssize_t retval = 0;
+       char *buf;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ath9k_ps_wakeup(sc);
+       len = ah->eep_ops->dump_eep_power(ah, buf, len, size);
+       ath9k_ps_restore(sc);
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static const struct file_operations fops_dump_eep_power = {
+       .read = read_file_dump_eep_power,
+       .open = ath9k_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+int ath9k_init_debug(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+       sc->debug.debugfs_phy = debugfs_create_dir("ath9k",
+                                                  sc->hw->wiphy->debugfsdir);
+       if (!sc->debug.debugfs_phy)
+               return -ENOMEM;
+
+#ifdef CONFIG_ATH_DEBUG
+       debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+                           sc, &fops_debug);
+#endif
+       ath9k_dfs_init_debug(sc);
+
+       debugfs_create_file("dma", S_IRUSR | S_IRGRP | S_IROTH,
+                           sc->debug.debugfs_phy, sc, &fops_dma);
+       debugfs_create_file("interrupt", S_IRUSR | S_IRGRP | S_IROTH,
+                           sc->debug.debugfs_phy, sc, &fops_interrupt);
+       debugfs_create_file("xmit", S_IRUSR | S_IRGRP | S_IROTH,
+                           sc->debug.debugfs_phy, sc, &fops_xmit);
+       debugfs_create_file("stations", S_IRUSR | S_IRGRP | S_IROTH,
+                           sc->debug.debugfs_phy, sc, &fops_stations);
+       debugfs_create_file("misc", S_IRUSR | S_IRGRP | S_IROTH,
+                           sc->debug.debugfs_phy, sc, &fops_misc);
+       debugfs_create_file("recv", S_IRUSR | S_IRGRP | S_IROTH,
+                           sc->debug.debugfs_phy, sc, &fops_recv);
+       debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc, &fops_rx_chainmask);
+       debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc, &fops_tx_chainmask);
+       debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc, &fops_disable_ani);
+       debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+                           sc, &fops_regidx);
+       debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+                           sc, &fops_regval);
+       debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy,
+                           &ah->config.cwm_ignore_extcca);
+       debugfs_create_file("regdump", S_IRUSR | S_IRGRP | S_IROTH,
+                           sc->debug.debugfs_phy, sc, &fops_regdump);
+       debugfs_create_file("dump_nfcal", S_IRUSR | S_IRGRP | S_IROTH,
+                           sc->debug.debugfs_phy, sc, &fops_dump_nfcal);
+       debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
+                           &fops_base_eeprom);
+       debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
+                           &fops_modal_eeprom);
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+       debugfs_create_file("samples", S_IRUSR | S_IRGRP | S_IROTH,
+                           sc->debug.debugfs_phy, sc, &fops_samps);
+#endif
+       debugfs_create_file("dump_eep_power", S_IRUSR | S_IRGRP | S_IROTH,
+                           sc->debug.debugfs_phy, sc, &fops_dump_eep_power);
+
+       debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
+                          sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
+
+       debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
+                          sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
+
+       return 0;
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/debug.h b/drivers/net/wireless/ath/ath9k_btcoex/debug.h
new file mode 100644 (file)
index 0000000..0bb0ce5
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include "hw.h"
+#include "rc.h"
+#include "dfs_debug.h"
+
+struct ath_txq;
+struct ath_buf;
+
+#ifdef CONFIG_ATH9K_DEBUGFS
+#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
+#define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++
+#else
+#define TX_STAT_INC(q, c) do { } while (0)
+#define RESET_STAT_INC(sc, type) do { } while (0)
+#endif
+
+#ifdef CONFIG_ATH9K_DEBUGFS
+
+/**
+ * struct ath_interrupt_stats - Contains statistics about interrupts
+ * @total: Total no. of interrupts generated so far
+ * @rxok: RX with no errors
+ * @rxlp: RX with low priority RX
+ * @rxhp: RX with high priority, uapsd only
+ * @rxeol: RX with no more RXDESC available
+ * @rxorn: RX FIFO overrun
+ * @txok: TX completed at the requested rate
+ * @txurn: TX FIFO underrun
+ * @mib: MIB regs reaching its threshold
+ * @rxphyerr: RX with phy errors
+ * @rx_keycache_miss: RX with key cache misses
+ * @swba: Software Beacon Alert
+ * @bmiss: Beacon Miss
+ * @bnr: Beacon Not Ready
+ * @cst: Carrier Sense TImeout
+ * @gtt: Global TX Timeout
+ * @tim: RX beacon TIM occurrence
+ * @cabend: RX End of CAB traffic
+ * @dtimsync: DTIM sync lossage
+ * @dtim: RX Beacon with DTIM
+ * @bb_watchdog: Baseband watchdog
+ * @tsfoor: TSF out of range, indicates that the corrected TSF received
+ * from a beacon differs from the PCU's internal TSF by more than a
+ * (programmable) threshold
+ */
+struct ath_interrupt_stats {
+       u32 total;
+       u32 rxok;
+       u32 rxlp;
+       u32 rxhp;
+       u32 rxeol;
+       u32 rxorn;
+       u32 txok;
+       u32 txeol;
+       u32 txurn;
+       u32 mib;
+       u32 rxphyerr;
+       u32 rx_keycache_miss;
+       u32 swba;
+       u32 bmiss;
+       u32 bnr;
+       u32 cst;
+       u32 gtt;
+       u32 tim;
+       u32 cabend;
+       u32 dtimsync;
+       u32 dtim;
+       u32 bb_watchdog;
+       u32 tsfoor;
+       u32 mci;
+};
+
+/**
+ * struct ath_tx_stats - Statistics about TX
+ * @tx_pkts_all:  No. of total frames transmitted, including ones that
+       may have had errors.
+ * @tx_bytes_all:  No. of total bytes transmitted, including ones that
+       may have had errors.
+ * @queued: Total MPDUs (non-aggr) queued
+ * @completed: Total MPDUs (non-aggr) completed
+ * @a_aggr: Total no. of aggregates queued
+ * @a_queued_hw: Total AMPDUs queued to hardware
+ * @a_queued_sw: Total AMPDUs queued to software queues
+ * @a_completed: Total AMPDUs completed
+ * @a_retries: No. of AMPDUs retried (SW)
+ * @a_xretries: No. of AMPDUs dropped due to xretries
+ * @fifo_underrun: FIFO underrun occurrences
+       Valid only for:
+               - non-aggregate condition.
+               - first packet of aggregate.
+ * @xtxop: No. of frames filtered because of TXOP limit
+ * @timer_exp: Transmit timer expiry
+ * @desc_cfg_err: Descriptor configuration errors
+ * @data_urn: TX data underrun errors
+ * @delim_urn: TX delimiter underrun errors
+ * @puttxbuf: Number of times hardware was given txbuf to write.
+ * @txstart:  Number of times hardware was told to start tx.
+ * @txprocdesc:  Number of times tx descriptor was processed
+ */
+struct ath_tx_stats {
+       u32 tx_pkts_all;
+       u32 tx_bytes_all;
+       u32 queued;
+       u32 completed;
+       u32 xretries;
+       u32 a_aggr;
+       u32 a_queued_hw;
+       u32 a_queued_sw;
+       u32 a_completed;
+       u32 a_retries;
+       u32 a_xretries;
+       u32 fifo_underrun;
+       u32 xtxop;
+       u32 timer_exp;
+       u32 desc_cfg_err;
+       u32 data_underrun;
+       u32 delim_underrun;
+       u32 puttxbuf;
+       u32 txstart;
+       u32 txprocdesc;
+};
+
+/**
+ * struct ath_rx_stats - RX Statistics
+ * @rx_pkts_all:  No. of total frames received, including ones that
+       may have had errors.
+ * @rx_bytes_all:  No. of total bytes received, including ones that
+       may have had errors.
+ * @crc_err: No. of frames with incorrect CRC value
+ * @decrypt_crc_err: No. of frames whose CRC check failed after
+       decryption process completed
+ * @phy_err: No. of frames whose reception failed because the PHY
+       encountered an error
+ * @mic_err: No. of frames with incorrect TKIP MIC verification failure
+ * @pre_delim_crc_err: Pre-Frame delimiter CRC error detections
+ * @post_delim_crc_err: Post-Frame delimiter CRC error detections
+ * @decrypt_busy_err: Decryption interruptions counter
+ * @phy_err_stats: Individual PHY error statistics
+ */
+struct ath_rx_stats {
+       u32 rx_pkts_all;
+       u32 rx_bytes_all;
+       u32 crc_err;
+       u32 decrypt_crc_err;
+       u32 phy_err;
+       u32 mic_err;
+       u32 pre_delim_crc_err;
+       u32 post_delim_crc_err;
+       u32 decrypt_busy_err;
+       u32 phy_err_stats[ATH9K_PHYERR_MAX];
+};
+
+enum ath_reset_type {
+       RESET_TYPE_BB_HANG,
+       RESET_TYPE_BB_WATCHDOG,
+       RESET_TYPE_FATAL_INT,
+       RESET_TYPE_TX_ERROR,
+       RESET_TYPE_TX_HANG,
+       RESET_TYPE_PLL_HANG,
+       __RESET_TYPE_MAX
+};
+
+struct ath_stats {
+       struct ath_interrupt_stats istats;
+       struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
+       struct ath_rx_stats rxstats;
+       struct ath_dfs_stats dfs_stats;
+       u32 reset[__RESET_TYPE_MAX];
+};
+
+#define ATH_DBG_MAX_SAMPLES    10
+struct ath_dbg_bb_mac_samp {
+       u32 dma_dbg_reg_vals[ATH9K_NUM_DMA_DEBUG_REGS];
+       u32 pcu_obs, pcu_cr, noise;
+       struct {
+               u64 jiffies;
+               int8_t rssi_ctl0;
+               int8_t rssi_ctl1;
+               int8_t rssi_ctl2;
+               int8_t rssi_ext0;
+               int8_t rssi_ext1;
+               int8_t rssi_ext2;
+               int8_t rssi;
+               bool isok;
+               u8 rts_fail_cnt;
+               u8 data_fail_cnt;
+               u8 rateindex;
+               u8 qid;
+               u8 tid;
+               u32 ba_low;
+               u32 ba_high;
+       } ts[ATH_DBG_MAX_SAMPLES];
+       struct {
+               u64 jiffies;
+               int8_t rssi_ctl0;
+               int8_t rssi_ctl1;
+               int8_t rssi_ctl2;
+               int8_t rssi_ext0;
+               int8_t rssi_ext1;
+               int8_t rssi_ext2;
+               int8_t rssi;
+               bool is_mybeacon;
+               u8 antenna;
+               u8 rate;
+       } rs[ATH_DBG_MAX_SAMPLES];
+       struct ath_cycle_counters cc;
+       struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
+};
+
+struct ath9k_debug {
+       struct dentry *debugfs_phy;
+       u32 regidx;
+       struct ath_stats stats;
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+       spinlock_t samp_lock;
+       struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES];
+       u8 sampidx;
+       u8 tsidx;
+       u8 rsidx;
+#endif
+};
+
+int ath9k_init_debug(struct ath_hw *ah);
+
+void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
+                      struct ath_tx_status *ts, struct ath_txq *txq,
+                      unsigned int flags);
+void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
+
+#else
+
+static inline int ath9k_init_debug(struct ath_hw *ah)
+{
+       return 0;
+}
+
+static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
+                                           enum ath9k_int status)
+{
+}
+
+static inline void ath_debug_stat_tx(struct ath_softc *sc,
+                                    struct ath_buf *bf,
+                                    struct ath_tx_status *ts,
+                                    struct ath_txq *txq,
+                                    unsigned int flags)
+{
+}
+
+static inline void ath_debug_stat_rx(struct ath_softc *sc,
+                                    struct ath_rx_status *rs)
+{
+}
+
+#endif /* CONFIG_ATH9K_DEBUGFS */
+
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+
+void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
+
+#else
+
+static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
+{
+}
+
+#endif
+
+
+#endif /* DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/dfs.c b/drivers/net/wireless/ath/ath9k_btcoex/dfs.c
new file mode 100644 (file)
index 0000000..f4f56af
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "ath9k.h"
+#include "dfs.h"
+#include "dfs_debug.h"
+
+/*
+ * TODO: move into or synchronize this with generic header
+ *      as soon as IF is defined
+ */
+struct dfs_radar_pulse {
+       u16 freq;
+       u64 ts;
+       u32 width;
+       u8 rssi;
+};
+
+/* internal struct to pass radar data */
+struct ath_radar_data {
+       u8 pulse_bw_info;
+       u8 rssi;
+       u8 ext_rssi;
+       u8 pulse_length_ext;
+       u8 pulse_length_pri;
+};
+
+/* convert pulse duration to usecs, considering clock mode */
+static u32 dur_to_usecs(struct ath_hw *ah, u32 dur)
+{
+       const u32 AR93X_NSECS_PER_DUR = 800;
+       const u32 AR93X_NSECS_PER_DUR_FAST = (8000 / 11);
+       u32 nsecs;
+
+       if (IS_CHAN_A_FAST_CLOCK(ah, ah->curchan))
+               nsecs = dur * AR93X_NSECS_PER_DUR_FAST;
+       else
+               nsecs = dur * AR93X_NSECS_PER_DUR;
+
+       return (nsecs + 500) / 1000;
+}
+
+#define PRI_CH_RADAR_FOUND 0x01
+#define EXT_CH_RADAR_FOUND 0x02
+static bool
+ath9k_postprocess_radar_event(struct ath_softc *sc,
+                             struct ath_radar_data *are,
+                             struct dfs_radar_pulse *drp)
+{
+       u8 rssi;
+       u16 dur;
+
+       ath_dbg(ath9k_hw_common(sc->sc_ah), DFS,
+               "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n",
+               are->pulse_bw_info,
+               are->pulse_length_pri, are->rssi,
+               are->pulse_length_ext, are->ext_rssi);
+
+       /*
+        * Only the last 2 bits of the BW info are relevant, they indicate
+        * which channel the radar was detected in.
+        */
+       are->pulse_bw_info &= 0x03;
+
+       switch (are->pulse_bw_info) {
+       case PRI_CH_RADAR_FOUND:
+               /* radar in ctrl channel */
+               dur = are->pulse_length_pri;
+               DFS_STAT_INC(sc, pri_phy_errors);
+               /*
+                * cannot use ctrl channel RSSI
+                * if extension channel is stronger
+                */
+               rssi = (are->ext_rssi >= (are->rssi + 3)) ? 0 : are->rssi;
+               break;
+       case EXT_CH_RADAR_FOUND:
+               /* radar in extension channel */
+               dur = are->pulse_length_ext;
+               DFS_STAT_INC(sc, ext_phy_errors);
+               /*
+                * cannot use extension channel RSSI
+                * if control channel is stronger
+                */
+               rssi = (are->rssi >= (are->ext_rssi + 12)) ? 0 : are->ext_rssi;
+               break;
+       case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND):
+               /*
+                * Conducted testing, when pulse is on DC, both pri and ext
+                * durations are reported to be same
+                *
+                * Radiated testing, when pulse is on DC, different pri and
+                * ext durations are reported, so take the larger of the two
+                */
+               if (are->pulse_length_ext >= are->pulse_length_pri)
+                       dur = are->pulse_length_ext;
+               else
+                       dur = are->pulse_length_pri;
+               DFS_STAT_INC(sc, dc_phy_errors);
+
+               /* when both are present use stronger one */
+               rssi = (are->rssi < are->ext_rssi) ? are->ext_rssi : are->rssi;
+               break;
+       default:
+               /*
+                * Bogus bandwidth info was received in descriptor,
+                * so ignore this PHY error
+                */
+               DFS_STAT_INC(sc, bwinfo_discards);
+               return false;
+       }
+
+       if (rssi == 0) {
+               DFS_STAT_INC(sc, rssi_discards);
+               return false;
+       }
+
+       /*
+        * TODO: check chirping pulses
+        *       checks for chirping are dependent on the DFS regulatory domain
+        *       used, which is yet TBD
+        */
+
+       /* convert duration to usecs */
+       drp->width = dur_to_usecs(sc->sc_ah, dur);
+       drp->rssi = rssi;
+
+       DFS_STAT_INC(sc, pulses_detected);
+       return true;
+}
+#undef PRI_CH_RADAR_FOUND
+#undef EXT_CH_RADAR_FOUND
+
+/*
+ * DFS: check PHY-error for radar pulse and feed the detector
+ */
+void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
+                             struct ath_rx_status *rs, u64 mactime)
+{
+       struct ath_radar_data ard;
+       u16 datalen;
+       char *vdata_end;
+       struct dfs_radar_pulse drp;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR)) &&
+           (!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) {
+               ath_dbg(common, DFS,
+                       "Error: rs_phyer=0x%x not a radar error\n",
+                       rs->rs_phyerr);
+               return;
+       }
+
+       datalen = rs->rs_datalen;
+       if (datalen == 0) {
+               DFS_STAT_INC(sc, datalen_discards);
+               return;
+       }
+
+       ard.rssi = rs->rs_rssi_ctl0;
+       ard.ext_rssi = rs->rs_rssi_ext0;
+
+       /*
+        * hardware stores this as 8 bit signed value.
+        * we will cap it at 0 if it is a negative number
+        */
+       if (ard.rssi & 0x80)
+               ard.rssi = 0;
+       if (ard.ext_rssi & 0x80)
+               ard.ext_rssi = 0;
+
+       vdata_end = (char *)data + datalen;
+       ard.pulse_bw_info = vdata_end[-1];
+       ard.pulse_length_ext = vdata_end[-2];
+       ard.pulse_length_pri = vdata_end[-3];
+
+       ath_dbg(common, DFS,
+               "bw_info=%d, length_pri=%d, length_ext=%d, "
+               "rssi_pri=%d, rssi_ext=%d\n",
+               ard.pulse_bw_info, ard.pulse_length_pri, ard.pulse_length_ext,
+               ard.rssi, ard.ext_rssi);
+
+       drp.freq = ah->curchan->channel;
+       drp.ts = mactime;
+       if (ath9k_postprocess_radar_event(sc, &ard, &drp)) {
+               static u64 last_ts;
+               ath_dbg(common, DFS,
+                       "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, "
+                       "width=%d, rssi=%d, delta_ts=%llu\n",
+                       drp.freq, drp.ts, drp.width, drp.rssi, drp.ts-last_ts);
+               last_ts = drp.ts;
+               /*
+                * TODO: forward pulse to pattern detector
+                *
+                * ieee80211_add_radar_pulse(drp.freq, drp.ts,
+                *                           drp.width, drp.rssi);
+                */
+       }
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/dfs.h b/drivers/net/wireless/ath/ath9k_btcoex/dfs.h
new file mode 100644 (file)
index 0000000..c241285
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH9K_DFS_H
+#define ATH9K_DFS_H
+
+#if defined(CONFIG_ATH9K_DFS_CERTIFIED)
+/**
+ * ath9k_dfs_process_phyerr - process radar PHY error
+ * @sc: ath_softc
+ * @data: RX payload data
+ * @rs: RX status after processing descriptor
+ * @mactime: receive time
+ *
+ * This function is called whenever the HW DFS module detects a radar
+ * pulse and reports it as a PHY error.
+ *
+ * The radar information provided as raw payload data is validated and
+ * filtered for false pulses. Events passing all tests are forwarded to
+ * the upper layer for pattern detection.
+ */
+void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
+                             struct ath_rx_status *rs, u64 mactime);
+#else
+static inline void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
+                                           struct ath_rx_status *rs, u64 mactime) { }
+#endif
+
+#endif /* ATH9K_DFS_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/dfs_debug.c b/drivers/net/wireless/ath/ath9k_btcoex/dfs_debug.c
new file mode 100644 (file)
index 0000000..4364c10
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/export.h>
+
+#include "ath9k.h"
+#include "dfs_debug.h"
+
+#define ATH9K_DFS_STAT(s, p) \
+       len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \
+                       sc->debug.stats.dfs_stats.p);
+
+static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath9k_hw_version *hw_ver = &sc->sc_ah->hw_version;
+       char *buf;
+       unsigned int len = 0, size = 8000;
+       ssize_t retval = 0;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       len += snprintf(buf + len, size - len, "DFS support for "
+                       "macVersion = 0x%x, macRev = 0x%x: %s\n",
+                       hw_ver->macVersion, hw_ver->macRev,
+                       (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ?
+                                       "enabled" : "disabled");
+       ATH9K_DFS_STAT("DFS pulses detected     ", pulses_detected);
+       ATH9K_DFS_STAT("Datalen discards        ", datalen_discards);
+       ATH9K_DFS_STAT("RSSI discards           ", rssi_discards);
+       ATH9K_DFS_STAT("BW info discards        ", bwinfo_discards);
+       ATH9K_DFS_STAT("Primary channel pulses  ", pri_phy_errors);
+       ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors);
+       ATH9K_DFS_STAT("Dual channel pulses     ", dc_phy_errors);
+
+       if (len > size)
+               len = size;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static const struct file_operations fops_dfs_stats = {
+       .read = read_file_dfs,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+void ath9k_dfs_init_debug(struct ath_softc *sc)
+{
+       debugfs_create_file("dfs_stats", S_IRUSR,
+                           sc->debug.debugfs_phy, sc, &fops_dfs_stats);
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/dfs_debug.h b/drivers/net/wireless/ath/ath9k_btcoex/dfs_debug.h
new file mode 100644 (file)
index 0000000..4911724
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef ATH9K_DFS_DEBUG_H
+#define ATH9K_DFS_DEBUG_H
+
+#include "hw.h"
+
+/**
+ * struct ath_dfs_stats - DFS Statistics
+ *
+ * @pulses_detected:  No. of pulses detected so far
+ * @datalen_discards: No. of pulses discarded due to invalid datalen
+ * @rssi_discards:    No. of pulses discarded due to invalid RSSI
+ * @bwinfo_discards:  No. of pulses discarded due to invalid BW info
+ * @pri_phy_errors:   No. of pulses reported for primary channel
+ * @ext_phy_errors:   No. of pulses reported for extension channel
+ * @dc_phy_errors:    No. of pulses reported for primary + extension channel
+ */
+struct ath_dfs_stats {
+       u32 pulses_detected;
+       u32 datalen_discards;
+       u32 rssi_discards;
+       u32 bwinfo_discards;
+       u32 pri_phy_errors;
+       u32 ext_phy_errors;
+       u32 dc_phy_errors;
+};
+
+#if defined(CONFIG_ATH9K_DFS_DEBUGFS)
+
+#define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++)
+void ath9k_dfs_init_debug(struct ath_softc *sc);
+
+#else
+
+#define DFS_STAT_INC(sc, c) do { } while (0)
+static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { }
+
+#endif /* CONFIG_ATH9K_DFS_DEBUGFS */
+
+#endif /* ATH9K_DFS_DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/eeprom.c b/drivers/net/wireless/ath/ath9k_btcoex/eeprom.c
new file mode 100644 (file)
index 0000000..c435232
--- /dev/null
@@ -0,0 +1,541 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+
+static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
+{
+       if (fbin == AR5416_BCHAN_UNUSED)
+               return fbin;
+
+       return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
+{
+        REG_WRITE(ah, reg, val);
+
+        if (ah->config.analog_shiftreg)
+               udelay(100);
+}
+
+void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
+                              u32 shift, u32 val)
+{
+       u32 regVal;
+
+       regVal = REG_READ(ah, reg) & ~mask;
+       regVal |= (val << shift) & mask;
+
+       REG_WRITE(ah, reg, regVal);
+
+       if (ah->config.analog_shiftreg)
+               udelay(100);
+}
+
+int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
+                            int16_t targetLeft, int16_t targetRight)
+{
+       int16_t rv;
+
+       if (srcRight == srcLeft) {
+               rv = targetLeft;
+       } else {
+               rv = (int16_t) (((target - srcLeft) * targetRight +
+                                (srcRight - target) * targetLeft) /
+                               (srcRight - srcLeft));
+       }
+       return rv;
+}
+
+bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
+                                   u16 *indexL, u16 *indexR)
+{
+       u16 i;
+
+       if (target <= pList[0]) {
+               *indexL = *indexR = 0;
+               return true;
+       }
+       if (target >= pList[listSize - 1]) {
+               *indexL = *indexR = (u16) (listSize - 1);
+               return true;
+       }
+
+       for (i = 0; i < listSize - 1; i++) {
+               if (pList[i] == target) {
+                       *indexL = *indexR = i;
+                       return true;
+               }
+               if (target < pList[i + 1]) {
+                       *indexL = i;
+                       *indexR = (u16) (i + 1);
+                       return false;
+               }
+       }
+       return false;
+}
+
+void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
+                                 int eep_start_loc, int size)
+{
+       int i = 0, j, addr;
+       u32 addrdata[8];
+       u32 data[8];
+
+       for (addr = 0; addr < size; addr++) {
+               addrdata[i] = AR5416_EEPROM_OFFSET +
+                       ((addr + eep_start_loc) << AR5416_EEPROM_S);
+               i++;
+               if (i == 8) {
+                       REG_READ_MULTI(ah, addrdata, data, i);
+
+                       for (j = 0; j < i; j++) {
+                               *eep_data = data[j];
+                               eep_data++;
+                       }
+                       i = 0;
+               }
+       }
+
+       if (i != 0) {
+               REG_READ_MULTI(ah, addrdata, data, i);
+
+               for (j = 0; j < i; j++) {
+                       *eep_data = data[j];
+                       eep_data++;
+               }
+       }
+}
+
+bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data)
+{
+       return common->bus_ops->eeprom_read(common, off, data);
+}
+
+void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
+                            u8 *pVpdList, u16 numIntercepts,
+                            u8 *pRetVpdList)
+{
+       u16 i, k;
+       u8 currPwr = pwrMin;
+       u16 idxL = 0, idxR = 0;
+
+       for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
+               ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
+                                              numIntercepts, &(idxL),
+                                              &(idxR));
+               if (idxR < 1)
+                       idxR = 1;
+               if (idxL == numIntercepts - 1)
+                       idxL = (u16) (numIntercepts - 2);
+               if (pPwrList[idxL] == pPwrList[idxR])
+                       k = pVpdList[idxL];
+               else
+                       k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
+                                  (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
+                                 (pPwrList[idxR] - pPwrList[idxL]));
+               pRetVpdList[i] = (u8) k;
+               currPwr += 2;
+       }
+}
+
+void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
+                                      struct ath9k_channel *chan,
+                                      struct cal_target_power_leg *powInfo,
+                                      u16 numChannels,
+                                      struct cal_target_power_leg *pNewPower,
+                                      u16 numRates, bool isExtTarget)
+{
+       struct chan_centers centers;
+       u16 clo, chi;
+       int i;
+       int matchIndex = -1, lowIndex = -1;
+       u16 freq;
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
+
+       if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
+                                      IS_CHAN_2GHZ(chan))) {
+               matchIndex = 0;
+       } else {
+               for (i = 0; (i < numChannels) &&
+                            (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+                       if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+                                                      IS_CHAN_2GHZ(chan))) {
+                               matchIndex = i;
+                               break;
+                       } else if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
+                                               IS_CHAN_2GHZ(chan)) && i > 0 &&
+                                  freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+                                               IS_CHAN_2GHZ(chan))) {
+                               lowIndex = i - 1;
+                               break;
+                       }
+               }
+               if ((matchIndex == -1) && (lowIndex == -1))
+                       matchIndex = i - 1;
+       }
+
+       if (matchIndex != -1) {
+               *pNewPower = powInfo[matchIndex];
+       } else {
+               clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+                                        IS_CHAN_2GHZ(chan));
+               chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+                                        IS_CHAN_2GHZ(chan));
+
+               for (i = 0; i < numRates; i++) {
+                       pNewPower->tPow2x[i] =
+                               (u8)ath9k_hw_interpolate(freq, clo, chi,
+                                               powInfo[lowIndex].tPow2x[i],
+                                               powInfo[lowIndex + 1].tPow2x[i]);
+               }
+       }
+}
+
+void ath9k_hw_get_target_powers(struct ath_hw *ah,
+                               struct ath9k_channel *chan,
+                               struct cal_target_power_ht *powInfo,
+                               u16 numChannels,
+                               struct cal_target_power_ht *pNewPower,
+                               u16 numRates, bool isHt40Target)
+{
+       struct chan_centers centers;
+       u16 clo, chi;
+       int i;
+       int matchIndex = -1, lowIndex = -1;
+       u16 freq;
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       freq = isHt40Target ? centers.synth_center : centers.ctl_center;
+
+       if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
+               matchIndex = 0;
+       } else {
+               for (i = 0; (i < numChannels) &&
+                            (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+                       if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+                                                      IS_CHAN_2GHZ(chan))) {
+                               matchIndex = i;
+                               break;
+                       } else
+                               if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
+                                               IS_CHAN_2GHZ(chan)) && i > 0 &&
+                                   freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+                                               IS_CHAN_2GHZ(chan))) {
+                                       lowIndex = i - 1;
+                                       break;
+                               }
+               }
+               if ((matchIndex == -1) && (lowIndex == -1))
+                       matchIndex = i - 1;
+       }
+
+       if (matchIndex != -1) {
+               *pNewPower = powInfo[matchIndex];
+       } else {
+               clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+                                        IS_CHAN_2GHZ(chan));
+               chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+                                        IS_CHAN_2GHZ(chan));
+
+               for (i = 0; i < numRates; i++) {
+                       pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
+                                               clo, chi,
+                                               powInfo[lowIndex].tPow2x[i],
+                                               powInfo[lowIndex + 1].tPow2x[i]);
+               }
+       }
+}
+
+u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
+                               bool is2GHz, int num_band_edges)
+{
+       u16 twiceMaxEdgePower = MAX_RATE_POWER;
+       int i;
+
+       for (i = 0; (i < num_band_edges) &&
+                    (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+               if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
+                       twiceMaxEdgePower = CTL_EDGE_TPOWER(pRdEdgesPower[i].ctl);
+                       break;
+               } else if ((i > 0) &&
+                          (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
+                                                     is2GHz))) {
+                       if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
+                                              is2GHz) < freq &&
+                           CTL_EDGE_FLAGS(pRdEdgesPower[i - 1].ctl)) {
+                               twiceMaxEdgePower =
+                                       CTL_EDGE_TPOWER(pRdEdgesPower[i - 1].ctl);
+                       }
+                       break;
+               }
+       }
+
+       return twiceMaxEdgePower;
+}
+
+void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+
+       switch (ar5416_get_ntxchains(ah->txchainmask)) {
+       case 1:
+               break;
+       case 2:
+               regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+               break;
+       case 3:
+               regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+               break;
+       default:
+               ath_dbg(common, EEPROM, "Invalid chainmask configuration\n");
+               break;
+       }
+}
+
+void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
+                               struct ath9k_channel *chan,
+                               void *pRawDataSet,
+                               u8 *bChans, u16 availPiers,
+                               u16 tPdGainOverlap,
+                               u16 *pPdGainBoundaries, u8 *pPDADCValues,
+                               u16 numXpdGains)
+{
+       int i, j, k;
+       int16_t ss;
+       u16 idxL = 0, idxR = 0, numPiers;
+       static u8 vpdTableL[AR5416_NUM_PD_GAINS]
+               [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+       static u8 vpdTableR[AR5416_NUM_PD_GAINS]
+               [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+       static u8 vpdTableI[AR5416_NUM_PD_GAINS]
+               [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+       u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+       u8 minPwrT4[AR5416_NUM_PD_GAINS];
+       u8 maxPwrT4[AR5416_NUM_PD_GAINS];
+       int16_t vpdStep;
+       int16_t tmpVal;
+       u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+       bool match;
+       int16_t minDelta = 0;
+       struct chan_centers centers;
+       int pdgain_boundary_default;
+       struct cal_data_per_freq *data_def = pRawDataSet;
+       struct cal_data_per_freq_4k *data_4k = pRawDataSet;
+       struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet;
+       bool eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah);
+       int intercepts;
+
+       if (AR_SREV_9287(ah))
+               intercepts = AR9287_PD_GAIN_ICEPTS;
+       else
+               intercepts = AR5416_PD_GAIN_ICEPTS;
+
+       memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS);
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+       for (numPiers = 0; numPiers < availPiers; numPiers++) {
+               if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+                       break;
+       }
+
+       match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
+                                                            IS_CHAN_2GHZ(chan)),
+                                              bChans, numPiers, &idxL, &idxR);
+
+       if (match) {
+               if (AR_SREV_9287(ah)) {
+                       /* FIXME: array overrun? */
+                       for (i = 0; i < numXpdGains; i++) {
+                               minPwrT4[i] = data_9287[idxL].pwrPdg[i][0];
+                               maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4];
+                               ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+                                               data_9287[idxL].pwrPdg[i],
+                                               data_9287[idxL].vpdPdg[i],
+                                               intercepts,
+                                               vpdTableI[i]);
+                       }
+               } else if (eeprom_4k) {
+                       for (i = 0; i < numXpdGains; i++) {
+                               minPwrT4[i] = data_4k[idxL].pwrPdg[i][0];
+                               maxPwrT4[i] = data_4k[idxL].pwrPdg[i][4];
+                               ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+                                               data_4k[idxL].pwrPdg[i],
+                                               data_4k[idxL].vpdPdg[i],
+                                               intercepts,
+                                               vpdTableI[i]);
+                       }
+               } else {
+                       for (i = 0; i < numXpdGains; i++) {
+                               minPwrT4[i] = data_def[idxL].pwrPdg[i][0];
+                               maxPwrT4[i] = data_def[idxL].pwrPdg[i][4];
+                               ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+                                               data_def[idxL].pwrPdg[i],
+                                               data_def[idxL].vpdPdg[i],
+                                               intercepts,
+                                               vpdTableI[i]);
+                       }
+               }
+       } else {
+               for (i = 0; i < numXpdGains; i++) {
+                       if (AR_SREV_9287(ah)) {
+                               pVpdL = data_9287[idxL].vpdPdg[i];
+                               pPwrL = data_9287[idxL].pwrPdg[i];
+                               pVpdR = data_9287[idxR].vpdPdg[i];
+                               pPwrR = data_9287[idxR].pwrPdg[i];
+                       } else if (eeprom_4k) {
+                               pVpdL = data_4k[idxL].vpdPdg[i];
+                               pPwrL = data_4k[idxL].pwrPdg[i];
+                               pVpdR = data_4k[idxR].vpdPdg[i];
+                               pPwrR = data_4k[idxR].pwrPdg[i];
+                       } else {
+                               pVpdL = data_def[idxL].vpdPdg[i];
+                               pPwrL = data_def[idxL].pwrPdg[i];
+                               pVpdR = data_def[idxR].vpdPdg[i];
+                               pPwrR = data_def[idxR].pwrPdg[i];
+                       }
+
+                       minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+                       maxPwrT4[i] =
+                               min(pPwrL[intercepts - 1],
+                                   pPwrR[intercepts - 1]);
+
+
+                       ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+                                               pPwrL, pVpdL,
+                                               intercepts,
+                                               vpdTableL[i]);
+                       ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+                                               pPwrR, pVpdR,
+                                               intercepts,
+                                               vpdTableR[i]);
+
+                       for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+                               vpdTableI[i][j] =
+                                       (u8)(ath9k_hw_interpolate((u16)
+                                            FREQ2FBIN(centers.
+                                                      synth_center,
+                                                      IS_CHAN_2GHZ
+                                                      (chan)),
+                                            bChans[idxL], bChans[idxR],
+                                            vpdTableL[i][j], vpdTableR[i][j]));
+                       }
+               }
+       }
+
+       k = 0;
+
+       for (i = 0; i < numXpdGains; i++) {
+               if (i == (numXpdGains - 1))
+                       pPdGainBoundaries[i] =
+                               (u16)(maxPwrT4[i] / 2);
+               else
+                       pPdGainBoundaries[i] =
+                               (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
+
+               pPdGainBoundaries[i] =
+                       min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+               minDelta = 0;
+
+               if (i == 0) {
+                       if (AR_SREV_9280_20_OR_LATER(ah))
+                               ss = (int16_t)(0 - (minPwrT4[i] / 2));
+                       else
+                               ss = 0;
+               } else {
+                       ss = (int16_t)((pPdGainBoundaries[i - 1] -
+                                       (minPwrT4[i] / 2)) -
+                                      tPdGainOverlap + 1 + minDelta);
+               }
+               vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+               vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+               while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+                       tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+                       pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+                       ss++;
+               }
+
+               sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+               tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
+                               (minPwrT4[i] / 2));
+               maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+                       tgtIndex : sizeCurrVpdTable;
+
+               while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+                       pPDADCValues[k++] = vpdTableI[i][ss++];
+               }
+
+               vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+                                   vpdTableI[i][sizeCurrVpdTable - 2]);
+               vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+               if (tgtIndex >= maxIndex) {
+                       while ((ss <= tgtIndex) &&
+                              (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+                               tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
+                                                   (ss - maxIndex + 1) * vpdStep));
+                               pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+                                                        255 : tmpVal);
+                               ss++;
+                       }
+               }
+       }
+
+       if (eeprom_4k)
+               pdgain_boundary_default = 58;
+       else
+               pdgain_boundary_default = pPdGainBoundaries[i - 1];
+
+       while (i < AR5416_PD_GAINS_IN_MASK) {
+               pPdGainBoundaries[i] = pdgain_boundary_default;
+               i++;
+       }
+
+       while (k < AR5416_NUM_PDADC_VALUES) {
+               pPDADCValues[k] = pPDADCValues[k - 1];
+               k++;
+       }
+}
+
+int ath9k_hw_eeprom_init(struct ath_hw *ah)
+{
+       int status;
+
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ah->eep_ops = &eep_ar9300_ops;
+       else if (AR_SREV_9287(ah)) {
+               ah->eep_ops = &eep_ar9287_ops;
+       } else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
+               ah->eep_ops = &eep_4k_ops;
+       } else {
+               ah->eep_ops = &eep_def_ops;
+       }
+
+       if (!ah->eep_ops->fill_eeprom(ah))
+               return -EIO;
+
+       status = ah->eep_ops->check_eeprom(ah);
+
+       return status;
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/eeprom.h b/drivers/net/wireless/ath/ath9k_btcoex/eeprom.h
new file mode 100644 (file)
index 0000000..6353f1d
--- /dev/null
@@ -0,0 +1,711 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef EEPROM_H
+#define EEPROM_H
+
+#define AR_EEPROM_MODAL_SPURS   5
+
+#include "../ath.h"
+#include <net/cfg80211.h>
+#include "ar9003_eeprom.h"
+
+#ifdef __BIG_ENDIAN
+#define AR5416_EEPROM_MAGIC 0x5aa5
+#else
+#define AR5416_EEPROM_MAGIC 0xa55a
+#endif
+
+#define CTRY_DEBUG   0x1ff
+#define        CTRY_DEFAULT 0
+
+#define AR_EEPROM_EEPCAP_COMPRESS_DIS   0x0001
+#define AR_EEPROM_EEPCAP_AES_DIS        0x0002
+#define AR_EEPROM_EEPCAP_FASTFRAME_DIS  0x0004
+#define AR_EEPROM_EEPCAP_BURST_DIS      0x0008
+#define AR_EEPROM_EEPCAP_MAXQCU         0x01F0
+#define AR_EEPROM_EEPCAP_MAXQCU_S       4
+#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN  0x0200
+#define AR_EEPROM_EEPCAP_KC_ENTRIES     0xF000
+#define AR_EEPROM_EEPCAP_KC_ENTRIES_S   12
+
+#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND   0x0040
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN    0x0080
+#define AR_EEPROM_EEREGCAP_EN_KK_U2         0x0100
+#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND    0x0200
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD     0x0400
+#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A    0x0800
+
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0  0x4000
+#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000
+
+#define AR5416_EEPROM_MAGIC_OFFSET  0x0
+#define AR5416_EEPROM_S             2
+#define AR5416_EEPROM_OFFSET        0x2000
+#define AR5416_EEPROM_MAX           0xae0
+
+#define AR5416_EEPROM_START_ADDR \
+       (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200
+
+#define SD_NO_CTL               0xE0
+#define NO_CTL                  0xff
+#define CTL_MODE_M              0xf
+#define CTL_11A                 0
+#define CTL_11B                 1
+#define CTL_11G                 2
+#define CTL_2GHT20              5
+#define CTL_5GHT20              6
+#define CTL_2GHT40              7
+#define CTL_5GHT40              8
+
+#define EXT_ADDITIVE (0x8000)
+#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
+#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
+#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
+
+#define SUB_NUM_CTL_MODES_AT_5G_40 2
+#define SUB_NUM_CTL_MODES_AT_2G_40 3
+
+#define INCREASE_MAXPOW_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
+#define INCREASE_MAXPOW_BY_THREE_CHAIN   10 /* 10*log10(3)*2 */
+
+/*
+ * For AR9285 and later chipsets, the following bits are not being programmed
+ * in EEPROM and so need to be enabled always.
+ *
+ * Bit 0: en_fcc_mid
+ * Bit 1: en_jap_mid
+ * Bit 2: en_fcc_dfs_ht40
+ * Bit 3: en_jap_ht40
+ * Bit 4: en_jap_dfs_ht40
+ */
+#define AR9285_RDEXT_DEFAULT    0x1F
+
+#define ATH9K_POW_SM(_r, _s)   (((_r) & 0x3f) << (_s))
+#define FREQ2FBIN(x, y)                ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
+#define ath9k_hw_use_flash(_ah)        (!(_ah->ah_flags & AH_USE_EEPROM))
+
+#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
+#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
+                                ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \
+                                ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+
+#define EEP_RFSILENT_ENABLED        0x0001
+#define EEP_RFSILENT_ENABLED_S      0
+#define EEP_RFSILENT_POLARITY       0x0002
+#define EEP_RFSILENT_POLARITY_S     1
+#define EEP_RFSILENT_GPIO_SEL       (AR_SREV_9462(ah) ? 0x00fc : 0x001c)
+#define EEP_RFSILENT_GPIO_SEL_S     2
+
+#define AR5416_OPFLAGS_11A           0x01
+#define AR5416_OPFLAGS_11G           0x02
+#define AR5416_OPFLAGS_N_5G_HT40     0x04
+#define AR5416_OPFLAGS_N_2G_HT40     0x08
+#define AR5416_OPFLAGS_N_5G_HT20     0x10
+#define AR5416_OPFLAGS_N_2G_HT20     0x20
+
+#define AR5416_EEP_NO_BACK_VER       0x1
+#define AR5416_EEP_VER               0xE
+#define AR5416_EEP_VER_MINOR_MASK    0x0FFF
+#define AR5416_EEP_MINOR_VER_2       0x2
+#define AR5416_EEP_MINOR_VER_3       0x3
+#define AR5416_EEP_MINOR_VER_7       0x7
+#define AR5416_EEP_MINOR_VER_9       0x9
+#define AR5416_EEP_MINOR_VER_16      0x10
+#define AR5416_EEP_MINOR_VER_17      0x11
+#define AR5416_EEP_MINOR_VER_19      0x13
+#define AR5416_EEP_MINOR_VER_20      0x14
+#define AR5416_EEP_MINOR_VER_21      0x15
+#define AR5416_EEP_MINOR_VER_22      0x16
+
+#define AR5416_NUM_5G_CAL_PIERS         8
+#define AR5416_NUM_2G_CAL_PIERS         4
+#define AR5416_NUM_5G_20_TARGET_POWERS  8
+#define AR5416_NUM_5G_40_TARGET_POWERS  8
+#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_NUM_2G_20_TARGET_POWERS  4
+#define AR5416_NUM_2G_40_TARGET_POWERS  4
+#define AR5416_NUM_CTLS                 24
+#define AR5416_NUM_BAND_EDGES           8
+#define AR5416_NUM_PD_GAINS             4
+#define AR5416_PD_GAINS_IN_MASK         4
+#define AR5416_PD_GAIN_ICEPTS           5
+#define AR5416_NUM_PDADC_VALUES         128
+#define AR5416_BCHAN_UNUSED             0xFF
+#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
+#define AR5416_MAX_CHAINS               3
+#define AR9300_MAX_CHAINS              3
+#define AR5416_PWR_TABLE_OFFSET_DB     -5
+
+/* Rx gain type values */
+#define AR5416_EEP_RXGAIN_23DB_BACKOFF     0
+#define AR5416_EEP_RXGAIN_13DB_BACKOFF     1
+#define AR5416_EEP_RXGAIN_ORIG             2
+
+/* Tx gain type values */
+#define AR5416_EEP_TXGAIN_ORIGINAL         0
+#define AR5416_EEP_TXGAIN_HIGH_POWER       1
+
+#define AR5416_EEP4K_START_LOC                64
+#define AR5416_EEP4K_NUM_2G_CAL_PIERS         3
+#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS  3
+#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS  3
+#define AR5416_EEP4K_NUM_CTLS                 12
+#define AR5416_EEP4K_NUM_BAND_EDGES           4
+#define AR5416_EEP4K_NUM_PD_GAINS             2
+#define AR5416_EEP4K_MAX_CHAINS               1
+
+#define AR9280_TX_GAIN_TABLE_SIZE 22
+
+#define AR9287_EEP_VER               0xE
+#define AR9287_EEP_VER_MINOR_MASK    0xFFF
+#define AR9287_EEP_MINOR_VER_1       0x1
+#define AR9287_EEP_MINOR_VER_2       0x2
+#define AR9287_EEP_MINOR_VER_3       0x3
+#define AR9287_EEP_MINOR_VER         AR9287_EEP_MINOR_VER_3
+#define AR9287_EEP_MINOR_VER_b       AR9287_EEP_MINOR_VER
+#define AR9287_EEP_NO_BACK_VER       AR9287_EEP_MINOR_VER_1
+
+#define AR9287_EEP_START_LOC            128
+#define AR9287_HTC_EEP_START_LOC        256
+#define AR9287_NUM_2G_CAL_PIERS         3
+#define AR9287_NUM_2G_CCK_TARGET_POWERS 3
+#define AR9287_NUM_2G_20_TARGET_POWERS  3
+#define AR9287_NUM_2G_40_TARGET_POWERS  3
+#define AR9287_NUM_CTLS                12
+#define AR9287_NUM_BAND_EDGES          4
+#define AR9287_PD_GAIN_ICEPTS           1
+#define AR9287_EEPMISC_BIG_ENDIAN       0x01
+#define AR9287_EEPMISC_WOW              0x02
+#define AR9287_MAX_CHAINS               2
+#define AR9287_ANT_16S                  32
+
+#define AR9287_DATA_SZ                  32
+
+#define AR9287_PWR_TABLE_OFFSET_DB  -5
+
+#define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1)
+
+#define CTL_EDGE_TPOWER(_ctl) ((_ctl) & 0x3f)
+#define CTL_EDGE_FLAGS(_ctl) (((_ctl) >> 6) & 0x03)
+
+#define LNA_CTL_BUF_MODE       BIT(0)
+#define LNA_CTL_ISEL_LO                BIT(1)
+#define LNA_CTL_ISEL_HI                BIT(2)
+#define LNA_CTL_BUF_IN         BIT(3)
+#define LNA_CTL_FEM_BAND       BIT(4)
+#define LNA_CTL_LOCAL_BIAS     BIT(5)
+#define LNA_CTL_FORCE_XPA      BIT(6)
+#define LNA_CTL_USE_ANT1       BIT(7)
+
+enum eeprom_param {
+       EEP_NFTHRESH_5,
+       EEP_NFTHRESH_2,
+       EEP_MAC_MSW,
+       EEP_MAC_MID,
+       EEP_MAC_LSW,
+       EEP_REG_0,
+       EEP_OP_CAP,
+       EEP_OP_MODE,
+       EEP_RF_SILENT,
+       EEP_OB_5,
+       EEP_DB_5,
+       EEP_OB_2,
+       EEP_DB_2,
+       EEP_MINOR_REV,
+       EEP_TX_MASK,
+       EEP_RX_MASK,
+       EEP_FSTCLK_5G,
+       EEP_RXGAIN_TYPE,
+       EEP_OL_PWRCTRL,
+       EEP_TXGAIN_TYPE,
+       EEP_RC_CHAIN_MASK,
+       EEP_DAC_HPWR_5G,
+       EEP_FRAC_N_5G,
+       EEP_DEV_TYPE,
+       EEP_TEMPSENSE_SLOPE,
+       EEP_TEMPSENSE_SLOPE_PAL_ON,
+       EEP_PWR_TABLE_OFFSET,
+       EEP_DRIVE_STRENGTH,
+       EEP_INTERNAL_REGULATOR,
+       EEP_SWREG,
+       EEP_PAPRD,
+       EEP_MODAL_VER,
+       EEP_ANT_DIV_CTL1,
+       EEP_CHAIN_MASK_REDUCE,
+       EEP_ANTENNA_GAIN_2G,
+       EEP_ANTENNA_GAIN_5G,
+       EEP_QUICK_DROP
+};
+
+enum ar5416_rates {
+       rate6mb, rate9mb, rate12mb, rate18mb,
+       rate24mb, rate36mb, rate48mb, rate54mb,
+       rate1l, rate2l, rate2s, rate5_5l,
+       rate5_5s, rate11l, rate11s, rateXr,
+       rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
+       rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
+       rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
+       rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
+       rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
+       Ar5416RateSize
+};
+
+enum ath9k_hal_freq_band {
+       ATH9K_HAL_FREQ_BAND_5GHZ = 0,
+       ATH9K_HAL_FREQ_BAND_2GHZ = 1
+};
+
+struct base_eep_header {
+       u16 length;
+       u16 checksum;
+       u16 version;
+       u8 opCapFlags;
+       u8 eepMisc;
+       u16 regDmn[2];
+       u8 macAddr[6];
+       u8 rxMask;
+       u8 txMask;
+       u16 rfSilent;
+       u16 blueToothOptions;
+       u16 deviceCap;
+       u32 binBuildNumber;
+       u8 deviceType;
+       u8 pwdclkind;
+       u8 fastClk5g;
+       u8 divChain;
+       u8 rxGainType;
+       u8 dacHiPwrMode_5G;
+       u8 openLoopPwrCntl;
+       u8 dacLpMode;
+       u8 txGainType;
+       u8 rcChainMask;
+       u8 desiredScaleCCK;
+       u8 pwr_table_offset;
+       u8 frac_n_5g;
+       u8 futureBase_3[21];
+} __packed;
+
+struct base_eep_header_4k {
+       u16 length;
+       u16 checksum;
+       u16 version;
+       u8 opCapFlags;
+       u8 eepMisc;
+       u16 regDmn[2];
+       u8 macAddr[6];
+       u8 rxMask;
+       u8 txMask;
+       u16 rfSilent;
+       u16 blueToothOptions;
+       u16 deviceCap;
+       u32 binBuildNumber;
+       u8 deviceType;
+       u8 txGainType;
+} __packed;
+
+
+struct spur_chan {
+       u16 spurChan;
+       u8 spurRangeLow;
+       u8 spurRangeHigh;
+} __packed;
+
+struct modal_eep_header {
+       u32 antCtrlChain[AR5416_MAX_CHAINS];
+       u32 antCtrlCommon;
+       u8 antennaGainCh[AR5416_MAX_CHAINS];
+       u8 switchSettling;
+       u8 txRxAttenCh[AR5416_MAX_CHAINS];
+       u8 rxTxMarginCh[AR5416_MAX_CHAINS];
+       u8 adcDesiredSize;
+       u8 pgaDesiredSize;
+       u8 xlnaGainCh[AR5416_MAX_CHAINS];
+       u8 txEndToXpaOff;
+       u8 txEndToRxOn;
+       u8 txFrameToXpaOn;
+       u8 thresh62;
+       u8 noiseFloorThreshCh[AR5416_MAX_CHAINS];
+       u8 xpdGain;
+       u8 xpd;
+       u8 iqCalICh[AR5416_MAX_CHAINS];
+       u8 iqCalQCh[AR5416_MAX_CHAINS];
+       u8 pdGainOverlap;
+       u8 ob;
+       u8 db;
+       u8 xpaBiasLvl;
+       u8 pwrDecreaseFor2Chain;
+       u8 pwrDecreaseFor3Chain;
+       u8 txFrameToDataStart;
+       u8 txFrameToPaOn;
+       u8 ht40PowerIncForPdadc;
+       u8 bswAtten[AR5416_MAX_CHAINS];
+       u8 bswMargin[AR5416_MAX_CHAINS];
+       u8 swSettleHt40;
+       u8 xatten2Db[AR5416_MAX_CHAINS];
+       u8 xatten2Margin[AR5416_MAX_CHAINS];
+       u8 ob_ch1;
+       u8 db_ch1;
+       u8 lna_ctl;
+       u8 miscBits;
+       u16 xpaBiasLvlFreq[3];
+       u8 futureModal[6];
+
+       struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
+} __packed;
+
+struct calDataPerFreqOpLoop {
+       u8 pwrPdg[2][5];
+       u8 vpdPdg[2][5];
+       u8 pcdac[2][5];
+       u8 empty[2][5];
+} __packed;
+
+struct modal_eep_4k_header {
+       u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
+       u32 antCtrlCommon;
+       u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
+       u8 switchSettling;
+       u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
+       u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
+       u8 adcDesiredSize;
+       u8 pgaDesiredSize;
+       u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
+       u8 txEndToXpaOff;
+       u8 txEndToRxOn;
+       u8 txFrameToXpaOn;
+       u8 thresh62;
+       u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
+       u8 xpdGain;
+       u8 xpd;
+       u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS];
+       u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
+       u8 pdGainOverlap;
+#ifdef __BIG_ENDIAN_BITFIELD
+       u8 ob_1:4, ob_0:4;
+       u8 db1_1:4, db1_0:4;
+#else
+       u8 ob_0:4, ob_1:4;
+       u8 db1_0:4, db1_1:4;
+#endif
+       u8 xpaBiasLvl;
+       u8 txFrameToDataStart;
+       u8 txFrameToPaOn;
+       u8 ht40PowerIncForPdadc;
+       u8 bswAtten[AR5416_EEP4K_MAX_CHAINS];
+       u8 bswMargin[AR5416_EEP4K_MAX_CHAINS];
+       u8 swSettleHt40;
+       u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS];
+       u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
+#ifdef __BIG_ENDIAN_BITFIELD
+       u8 db2_1:4, db2_0:4;
+#else
+       u8 db2_0:4, db2_1:4;
+#endif
+       u8 version;
+#ifdef __BIG_ENDIAN_BITFIELD
+       u8 ob_3:4, ob_2:4;
+       u8 antdiv_ctl1:4, ob_4:4;
+       u8 db1_3:4, db1_2:4;
+       u8 antdiv_ctl2:4, db1_4:4;
+       u8 db2_2:4, db2_3:4;
+       u8 reserved:4, db2_4:4;
+#else
+       u8 ob_2:4, ob_3:4;
+       u8 ob_4:4, antdiv_ctl1:4;
+       u8 db1_2:4, db1_3:4;
+       u8 db1_4:4, antdiv_ctl2:4;
+       u8 db2_2:4, db2_3:4;
+       u8 db2_4:4, reserved:4;
+#endif
+       u8 tx_diversity;
+       u8 flc_pwr_thresh;
+       u8 bb_scale_smrt_antenna;
+#define EEP_4K_BB_DESIRED_SCALE_MASK   0x1f
+       u8 futureModal[1];
+       struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
+} __packed;
+
+struct base_eep_ar9287_header {
+       u16 length;
+       u16 checksum;
+       u16 version;
+       u8 opCapFlags;
+       u8 eepMisc;
+       u16 regDmn[2];
+       u8 macAddr[6];
+       u8 rxMask;
+       u8 txMask;
+       u16 rfSilent;
+       u16 blueToothOptions;
+       u16 deviceCap;
+       u32 binBuildNumber;
+       u8 deviceType;
+       u8 openLoopPwrCntl;
+       int8_t pwrTableOffset;
+       int8_t tempSensSlope;
+       int8_t tempSensSlopePalOn;
+       u8 futureBase[29];
+} __packed;
+
+struct modal_eep_ar9287_header {
+       u32 antCtrlChain[AR9287_MAX_CHAINS];
+       u32 antCtrlCommon;
+       int8_t antennaGainCh[AR9287_MAX_CHAINS];
+       u8 switchSettling;
+       u8 txRxAttenCh[AR9287_MAX_CHAINS];
+       u8 rxTxMarginCh[AR9287_MAX_CHAINS];
+       int8_t adcDesiredSize;
+       u8 txEndToXpaOff;
+       u8 txEndToRxOn;
+       u8 txFrameToXpaOn;
+       u8 thresh62;
+       int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS];
+       u8 xpdGain;
+       u8 xpd;
+       int8_t iqCalICh[AR9287_MAX_CHAINS];
+       int8_t iqCalQCh[AR9287_MAX_CHAINS];
+       u8 pdGainOverlap;
+       u8 xpaBiasLvl;
+       u8 txFrameToDataStart;
+       u8 txFrameToPaOn;
+       u8 ht40PowerIncForPdadc;
+       u8 bswAtten[AR9287_MAX_CHAINS];
+       u8 bswMargin[AR9287_MAX_CHAINS];
+       u8 swSettleHt40;
+       u8 version;
+       u8 db1;
+       u8 db2;
+       u8 ob_cck;
+       u8 ob_psk;
+       u8 ob_qam;
+       u8 ob_pal_off;
+       u8 futureModal[30];
+       struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
+} __packed;
+
+struct cal_data_per_freq {
+       u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+       u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __packed;
+
+struct cal_data_per_freq_4k {
+       u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+       u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __packed;
+
+struct cal_target_power_leg {
+       u8 bChannel;
+       u8 tPow2x[4];
+} __packed;
+
+struct cal_target_power_ht {
+       u8 bChannel;
+       u8 tPow2x[8];
+} __packed;
+
+struct cal_ctl_edges {
+       u8 bChannel;
+       u8 ctl;
+} __packed;
+
+struct cal_data_op_loop_ar9287 {
+       u8 pwrPdg[2][5];
+       u8 vpdPdg[2][5];
+       u8 pcdac[2][5];
+       u8 empty[2][5];
+} __packed;
+
+struct cal_data_per_freq_ar9287 {
+       u8 pwrPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
+       u8 vpdPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
+} __packed;
+
+union cal_data_per_freq_ar9287_u {
+       struct cal_data_op_loop_ar9287 calDataOpen;
+       struct cal_data_per_freq_ar9287 calDataClose;
+} __packed;
+
+struct cal_ctl_data_ar9287 {
+       struct cal_ctl_edges
+       ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES];
+} __packed;
+
+struct cal_ctl_data {
+       struct cal_ctl_edges
+       ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+} __packed;
+
+struct cal_ctl_data_4k {
+       struct cal_ctl_edges
+       ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES];
+} __packed;
+
+struct ar5416_eeprom_def {
+       struct base_eep_header baseEepHeader;
+       u8 custData[64];
+       struct modal_eep_header modalHeader[2];
+       u8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
+       u8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
+       struct cal_data_per_freq
+        calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
+       struct cal_data_per_freq
+        calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
+       struct cal_target_power_leg
+        calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
+       struct cal_target_power_ht
+        calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
+       struct cal_target_power_ht
+        calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
+       struct cal_target_power_leg
+        calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
+       struct cal_target_power_leg
+        calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
+       struct cal_target_power_ht
+        calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
+       struct cal_target_power_ht
+        calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
+       u8 ctlIndex[AR5416_NUM_CTLS];
+       struct cal_ctl_data ctlData[AR5416_NUM_CTLS];
+       u8 padding;
+} __packed;
+
+struct ar5416_eeprom_4k {
+       struct base_eep_header_4k baseEepHeader;
+       u8 custData[20];
+       struct modal_eep_4k_header modalHeader;
+       u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS];
+       struct cal_data_per_freq_4k
+       calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS];
+       struct cal_target_power_leg
+       calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS];
+       struct cal_target_power_leg
+       calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
+       struct cal_target_power_ht
+       calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
+       struct cal_target_power_ht
+       calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS];
+       u8 ctlIndex[AR5416_EEP4K_NUM_CTLS];
+       struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS];
+       u8 padding;
+} __packed;
+
+struct ar9287_eeprom {
+       struct base_eep_ar9287_header baseEepHeader;
+       u8 custData[AR9287_DATA_SZ];
+       struct modal_eep_ar9287_header modalHeader;
+       u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS];
+       union cal_data_per_freq_ar9287_u
+       calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS];
+       struct cal_target_power_leg
+       calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS];
+       struct cal_target_power_leg
+       calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS];
+       struct cal_target_power_ht
+       calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS];
+       struct cal_target_power_ht
+       calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS];
+       u8 ctlIndex[AR9287_NUM_CTLS];
+       struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS];
+       u8 padding;
+} __packed;
+
+enum reg_ext_bitmap {
+       REG_EXT_FCC_MIDBAND = 0,
+       REG_EXT_JAPAN_MIDBAND = 1,
+       REG_EXT_FCC_DFS_HT40 = 2,
+       REG_EXT_JAPAN_NONDFS_HT40 = 3,
+       REG_EXT_JAPAN_DFS_HT40 = 4
+};
+
+struct ath9k_country_entry {
+       u16 countryCode;
+       u16 regDmnEnum;
+       u16 regDmn5G;
+       u16 regDmn2G;
+       u8 isMultidomain;
+       u8 iso[3];
+};
+
+struct eeprom_ops {
+       int (*check_eeprom)(struct ath_hw *hw);
+       u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param);
+       u32 (*dump_eep_power)(struct ath_hw *hw, u8 *buf, u32 len, u32 size);
+       bool (*fill_eeprom)(struct ath_hw *hw);
+       u32 (*dump_eeprom)(struct ath_hw *hw, bool dump_base_hdr, u8 *buf,
+                          u32 len, u32 size);
+       int (*get_eeprom_ver)(struct ath_hw *hw);
+       int (*get_eeprom_rev)(struct ath_hw *hw);
+       void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
+       void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
+       void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
+                          u16 cfgCtl, u8 twiceAntennaReduction,
+                          u8 powerLimit, bool test);
+       u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
+};
+
+void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val);
+void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
+                              u32 shift, u32 val);
+int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
+                            int16_t targetLeft,
+                            int16_t targetRight);
+bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
+                                   u16 *indexL, u16 *indexR);
+bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data);
+void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
+                                 int eep_start_loc, int size);
+void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
+                            u8 *pVpdList, u16 numIntercepts,
+                            u8 *pRetVpdList);
+void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
+                                      struct ath9k_channel *chan,
+                                      struct cal_target_power_leg *powInfo,
+                                      u16 numChannels,
+                                      struct cal_target_power_leg *pNewPower,
+                                      u16 numRates, bool isExtTarget);
+void ath9k_hw_get_target_powers(struct ath_hw *ah,
+                               struct ath9k_channel *chan,
+                               struct cal_target_power_ht *powInfo,
+                               u16 numChannels,
+                               struct cal_target_power_ht *pNewPower,
+                               u16 numRates, bool isHt40Target);
+u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
+                               bool is2GHz, int num_band_edges);
+void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah);
+int ath9k_hw_eeprom_init(struct ath_hw *ah);
+
+void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
+                               struct ath9k_channel *chan,
+                               void *pRawDataSet,
+                               u8 *bChans, u16 availPiers,
+                               u16 tPdGainOverlap,
+                               u16 *pPdGainBoundaries, u8 *pPDADCValues,
+                               u16 numXpdGains);
+
+#define ar5416_get_ntxchains(_txchainmask)                     \
+       (((_txchainmask >> 2) & 1) +                            \
+        ((_txchainmask >> 1) & 1) + (_txchainmask & 1))
+
+extern const struct eeprom_ops eep_def_ops;
+extern const struct eeprom_ops eep_4k_ops;
+extern const struct eeprom_ops eep_ar9287_ops;
+extern const struct eeprom_ops eep_ar9287_ops;
+extern const struct eeprom_ops eep_ar9300_ops;
+
+#endif /* EEPROM_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/eeprom_4k.c b/drivers/net/wireless/ath/ath9k_btcoex/eeprom_4k.c
new file mode 100644 (file)
index 0000000..a850f44
--- /dev/null
@@ -0,0 +1,1111 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <asm/unaligned.h>
+#include "hw.h"
+#include "ar9002_phy.h"
+
+static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
+{
+       return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
+}
+
+static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
+{
+       return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
+}
+
+#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+
+static bool __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u16 *eep_data = (u16 *)&ah->eeprom.map4k;
+       int addr, eep_start_loc = 64;
+
+       for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
+               if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) {
+                       ath_dbg(common, EEPROM,
+                               "Unable to read eeprom region\n");
+                       return false;
+               }
+               eep_data++;
+       }
+
+       return true;
+}
+
+static bool __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw *ah)
+{
+       u16 *eep_data = (u16 *)&ah->eeprom.map4k;
+
+       ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 64, SIZE_EEPROM_4K);
+
+       return true;
+}
+
+static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (!ath9k_hw_use_flash(ah)) {
+               ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
+       }
+
+       if (common->bus_ops->ath_bus_type == ATH_USB)
+               return __ath9k_hw_usb_4k_fill_eeprom(ah);
+       else
+               return __ath9k_hw_4k_fill_eeprom(ah);
+}
+
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size,
+                                     struct modal_eep_4k_header *modal_hdr)
+{
+       PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
+       PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
+       PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
+       PR_EEP("Switch Settle", modal_hdr->switchSettling);
+       PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
+       PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
+       PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+       PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);
+       PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);
+       PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
+       PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
+       PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+       PR_EEP("CCA Threshold)", modal_hdr->thresh62);
+       PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+       PR_EEP("xpdGain", modal_hdr->xpdGain);
+       PR_EEP("External PD", modal_hdr->xpd);
+       PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
+       PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
+       PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
+       PR_EEP("O/D Bias Version", modal_hdr->version);
+       PR_EEP("CCK OutputBias", modal_hdr->ob_0);
+       PR_EEP("BPSK OutputBias", modal_hdr->ob_1);
+       PR_EEP("QPSK OutputBias", modal_hdr->ob_2);
+       PR_EEP("16QAM OutputBias", modal_hdr->ob_3);
+       PR_EEP("64QAM OutputBias", modal_hdr->ob_4);
+       PR_EEP("CCK Driver1_Bias", modal_hdr->db1_0);
+       PR_EEP("BPSK Driver1_Bias", modal_hdr->db1_1);
+       PR_EEP("QPSK Driver1_Bias", modal_hdr->db1_2);
+       PR_EEP("16QAM Driver1_Bias", modal_hdr->db1_3);
+       PR_EEP("64QAM Driver1_Bias", modal_hdr->db1_4);
+       PR_EEP("CCK Driver2_Bias", modal_hdr->db2_0);
+       PR_EEP("BPSK Driver2_Bias", modal_hdr->db2_1);
+       PR_EEP("QPSK Driver2_Bias", modal_hdr->db2_2);
+       PR_EEP("16QAM Driver2_Bias", modal_hdr->db2_3);
+       PR_EEP("64QAM Driver2_Bias", modal_hdr->db2_4);
+       PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+       PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+       PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+       PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
+       PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
+       PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
+       PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
+       PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);
+       PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);
+       PR_EEP("Ant. Diversity ctl1", modal_hdr->antdiv_ctl1);
+       PR_EEP("Ant. Diversity ctl2", modal_hdr->antdiv_ctl2);
+       PR_EEP("TX Diversity", modal_hdr->tx_diversity);
+
+       return len;
+}
+
+static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+                                      u8 *buf, u32 len, u32 size)
+{
+       struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+       struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+
+       if (!dump_base_hdr) {
+               len += snprintf(buf + len, size - len,
+                               "%20s :\n", "2GHz modal Header");
+               len = ath9k_dump_4k_modal_eeprom(buf, len, size,
+                                                 &eep->modalHeader);
+               goto out;
+       }
+
+       PR_EEP("Major Version", pBase->version >> 12);
+       PR_EEP("Minor Version", pBase->version & 0xFFF);
+       PR_EEP("Checksum", pBase->checksum);
+       PR_EEP("Length", pBase->length);
+       PR_EEP("RegDomain1", pBase->regDmn[0]);
+       PR_EEP("RegDomain2", pBase->regDmn[1]);
+       PR_EEP("TX Mask", pBase->txMask);
+       PR_EEP("RX Mask", pBase->rxMask);
+       PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
+       PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
+       PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_2G_HT20));
+       PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_2G_HT40));
+       PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_5G_HT20));
+       PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_5G_HT40));
+       PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
+       PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
+       PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
+       PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
+       PR_EEP("TX Gain type", pBase->txGainType);
+
+       len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+                       pBase->macAddr);
+
+out:
+       if (len > size)
+               len = size;
+
+       return len;
+}
+#else
+static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+                                      u8 *buf, u32 len, u32 size)
+{
+       return 0;
+}
+#endif
+
+
+#undef SIZE_EEPROM_4K
+
+static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
+{
+#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ar5416_eeprom_4k *eep =
+               (struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
+       u16 *eepdata, temp, magic, magic2;
+       u32 sum = 0, el;
+       bool need_swap = false;
+       int i, addr;
+
+
+       if (!ath9k_hw_use_flash(ah)) {
+               if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
+                                        &magic)) {
+                       ath_err(common, "Reading Magic # failed\n");
+                       return false;
+               }
+
+               ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
+
+               if (magic != AR5416_EEPROM_MAGIC) {
+                       magic2 = swab16(magic);
+
+                       if (magic2 == AR5416_EEPROM_MAGIC) {
+                               need_swap = true;
+                               eepdata = (u16 *) (&ah->eeprom);
+
+                               for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
+                                       temp = swab16(*eepdata);
+                                       *eepdata = temp;
+                                       eepdata++;
+                               }
+                       } else {
+                               ath_err(common,
+                                       "Invalid EEPROM Magic. Endianness mismatch.\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       ath_dbg(common, EEPROM, "need_swap = %s\n",
+               need_swap ? "True" : "False");
+
+       if (need_swap)
+               el = swab16(ah->eeprom.map4k.baseEepHeader.length);
+       else
+               el = ah->eeprom.map4k.baseEepHeader.length;
+
+       if (el > sizeof(struct ar5416_eeprom_4k))
+               el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
+       else
+               el = el / sizeof(u16);
+
+       eepdata = (u16 *)(&ah->eeprom);
+
+       for (i = 0; i < el; i++)
+               sum ^= *eepdata++;
+
+       if (need_swap) {
+               u32 integer;
+               u16 word;
+
+               ath_dbg(common, EEPROM,
+                       "EEPROM Endianness is not native.. Changing\n");
+
+               word = swab16(eep->baseEepHeader.length);
+               eep->baseEepHeader.length = word;
+
+               word = swab16(eep->baseEepHeader.checksum);
+               eep->baseEepHeader.checksum = word;
+
+               word = swab16(eep->baseEepHeader.version);
+               eep->baseEepHeader.version = word;
+
+               word = swab16(eep->baseEepHeader.regDmn[0]);
+               eep->baseEepHeader.regDmn[0] = word;
+
+               word = swab16(eep->baseEepHeader.regDmn[1]);
+               eep->baseEepHeader.regDmn[1] = word;
+
+               word = swab16(eep->baseEepHeader.rfSilent);
+               eep->baseEepHeader.rfSilent = word;
+
+               word = swab16(eep->baseEepHeader.blueToothOptions);
+               eep->baseEepHeader.blueToothOptions = word;
+
+               word = swab16(eep->baseEepHeader.deviceCap);
+               eep->baseEepHeader.deviceCap = word;
+
+               integer = swab32(eep->modalHeader.antCtrlCommon);
+               eep->modalHeader.antCtrlCommon = integer;
+
+               for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+                       integer = swab32(eep->modalHeader.antCtrlChain[i]);
+                       eep->modalHeader.antCtrlChain[i] = integer;
+               }
+
+               for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+                       word = swab16(eep->modalHeader.spurChans[i].spurChan);
+                       eep->modalHeader.spurChans[i].spurChan = word;
+               }
+       }
+
+       if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
+           ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+               ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+                       sum, ah->eep_ops->get_eeprom_ver(ah));
+               return -EINVAL;
+       }
+
+       return 0;
+#undef EEPROM_4K_SIZE
+}
+
+static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
+                                 enum eeprom_param param)
+{
+       struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+       struct modal_eep_4k_header *pModal = &eep->modalHeader;
+       struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+       u16 ver_minor;
+
+       ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK;
+
+       switch (param) {
+       case EEP_NFTHRESH_2:
+               return pModal->noiseFloorThreshCh[0];
+       case EEP_MAC_LSW:
+               return get_unaligned_be16(pBase->macAddr);
+       case EEP_MAC_MID:
+               return get_unaligned_be16(pBase->macAddr + 2);
+       case EEP_MAC_MSW:
+               return get_unaligned_be16(pBase->macAddr + 4);
+       case EEP_REG_0:
+               return pBase->regDmn[0];
+       case EEP_OP_CAP:
+               return pBase->deviceCap;
+       case EEP_OP_MODE:
+               return pBase->opCapFlags;
+       case EEP_RF_SILENT:
+               return pBase->rfSilent;
+       case EEP_OB_2:
+               return pModal->ob_0;
+       case EEP_DB_2:
+               return pModal->db1_1;
+       case EEP_MINOR_REV:
+               return ver_minor;
+       case EEP_TX_MASK:
+               return pBase->txMask;
+       case EEP_RX_MASK:
+               return pBase->rxMask;
+       case EEP_FRAC_N_5G:
+               return 0;
+       case EEP_PWR_TABLE_OFFSET:
+               return AR5416_PWR_TABLE_OFFSET_DB;
+       case EEP_MODAL_VER:
+               return pModal->version;
+       case EEP_ANT_DIV_CTL1:
+               return pModal->antdiv_ctl1;
+       case EEP_TXGAIN_TYPE:
+               return pBase->txGainType;
+       case EEP_ANTENNA_GAIN_2G:
+               return pModal->antennaGainCh[0];
+       default:
+               return 0;
+       }
+}
+
+static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
+                                 struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+       struct cal_data_per_freq_4k *pRawDataset;
+       u8 *pCalBChans = NULL;
+       u16 pdGainOverlap_t2;
+       static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+       u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+       u16 numPiers, i, j;
+       u16 numXpdGain, xpdMask;
+       u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
+       u32 reg32, regOffset, regChainOffset;
+
+       xpdMask = pEepData->modalHeader.xpdGain;
+
+       if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+           AR5416_EEP_MINOR_VER_2) {
+               pdGainOverlap_t2 =
+                       pEepData->modalHeader.pdGainOverlap;
+       } else {
+               pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+                                           AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+       }
+
+       pCalBChans = pEepData->calFreqPier2G;
+       numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
+
+       numXpdGain = 0;
+
+       for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+               if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+                       if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
+                               break;
+                       xpdGainValues[numXpdGain] =
+                               (u16)(AR5416_PD_GAINS_IN_MASK - i);
+                       numXpdGain++;
+               }
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+                     (numXpdGain - 1) & 0x3);
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+                     xpdGainValues[0]);
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+                     xpdGainValues[1]);
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
+
+       for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+               regChainOffset = i * 0x1000;
+
+               if (pEepData->baseEepHeader.txMask & (1 << i)) {
+                       pRawDataset = pEepData->calPierData2G[i];
+
+                       ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
+                                           pRawDataset, pCalBChans,
+                                           numPiers, pdGainOverlap_t2,
+                                           gainBoundaries,
+                                           pdadcValues, numXpdGain);
+
+                       ENABLE_REGWRITE_BUFFER(ah);
+
+                       REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+                                 SM(pdGainOverlap_t2,
+                                    AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+                                 | SM(gainBoundaries[0],
+                                      AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+                                 | SM(gainBoundaries[1],
+                                      AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+                                 | SM(gainBoundaries[2],
+                                      AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+                                 | SM(gainBoundaries[3],
+                              AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+
+                       regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+                       for (j = 0; j < 32; j++) {
+                               reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
+                               REG_WRITE(ah, regOffset, reg32);
+
+                               ath_dbg(common, EEPROM,
+                                       "PDADC (%d,%4x): %4.4x %8.8x\n",
+                                       i, regChainOffset, regOffset,
+                                       reg32);
+                               ath_dbg(common, EEPROM,
+                                       "PDADC: Chain %d | "
+                                       "PDADC %3d Value %3d | "
+                                       "PDADC %3d Value %3d | "
+                                       "PDADC %3d Value %3d | "
+                                       "PDADC %3d Value %3d |\n",
+                                       i, 4 * j, pdadcValues[4 * j],
+                                       4 * j + 1, pdadcValues[4 * j + 1],
+                                       4 * j + 2, pdadcValues[4 * j + 2],
+                                       4 * j + 3, pdadcValues[4 * j + 3]);
+
+                               regOffset += 4;
+                       }
+
+                       REGWRITE_BUFFER_FLUSH(ah);
+               }
+       }
+}
+
+static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
+                                                struct ath9k_channel *chan,
+                                                int16_t *ratesArray,
+                                                u16 cfgCtl,
+                                                u16 antenna_reduction,
+                                                u16 powerLimit)
+{
+#define CMP_TEST_GRP \
+       (((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) ==  \
+        pEepData->ctlIndex[i])                                         \
+       || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+           ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
+
+       int i;
+       u16 twiceMinEdgePower;
+       u16 twiceMaxEdgePower;
+       u16 scaledPower = 0, minCtlPower;
+       u16 numCtlModes;
+       const u16 *pCtlMode;
+       u16 ctlMode, freq;
+       struct chan_centers centers;
+       struct cal_ctl_data_4k *rep;
+       struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+       struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+               0, { 0, 0, 0, 0}
+       };
+       struct cal_target_power_leg targetPowerOfdmExt = {
+               0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+               0, { 0, 0, 0, 0 }
+       };
+       struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+               0, {0, 0, 0, 0}
+       };
+       static const u16 ctlModesFor11g[] = {
+               CTL_11B, CTL_11G, CTL_2GHT20,
+               CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+       };
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+       scaledPower = powerLimit - antenna_reduction;
+       numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+       pCtlMode = ctlModesFor11g;
+
+       ath9k_hw_get_legacy_target_powers(ah, chan,
+                       pEepData->calTargetPowerCck,
+                       AR5416_NUM_2G_CCK_TARGET_POWERS,
+                       &targetPowerCck, 4, false);
+       ath9k_hw_get_legacy_target_powers(ah, chan,
+                       pEepData->calTargetPower2G,
+                       AR5416_NUM_2G_20_TARGET_POWERS,
+                       &targetPowerOfdm, 4, false);
+       ath9k_hw_get_target_powers(ah, chan,
+                       pEepData->calTargetPower2GHT20,
+                       AR5416_NUM_2G_20_TARGET_POWERS,
+                       &targetPowerHt20, 8, false);
+
+       if (IS_CHAN_HT40(chan)) {
+               numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+               ath9k_hw_get_target_powers(ah, chan,
+                               pEepData->calTargetPower2GHT40,
+                               AR5416_NUM_2G_40_TARGET_POWERS,
+                               &targetPowerHt40, 8, true);
+               ath9k_hw_get_legacy_target_powers(ah, chan,
+                               pEepData->calTargetPowerCck,
+                               AR5416_NUM_2G_CCK_TARGET_POWERS,
+                               &targetPowerCckExt, 4, true);
+               ath9k_hw_get_legacy_target_powers(ah, chan,
+                               pEepData->calTargetPower2G,
+                               AR5416_NUM_2G_20_TARGET_POWERS,
+                               &targetPowerOfdmExt, 4, true);
+       }
+
+       for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+               bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+                       (pCtlMode[ctlMode] == CTL_2GHT40);
+
+               if (isHt40CtlMode)
+                       freq = centers.synth_center;
+               else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+                       freq = centers.ext_center;
+               else
+                       freq = centers.ctl_center;
+
+               twiceMaxEdgePower = MAX_RATE_POWER;
+
+               for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
+                            pEepData->ctlIndex[i]; i++) {
+
+                       if (CMP_TEST_GRP) {
+                               rep = &(pEepData->ctlData[i]);
+
+                               twiceMinEdgePower = ath9k_hw_get_max_edge_power(
+                                       freq,
+                                       rep->ctlEdges[
+                                       ar5416_get_ntxchains(ah->txchainmask) - 1],
+                                       IS_CHAN_2GHZ(chan),
+                                       AR5416_EEP4K_NUM_BAND_EDGES);
+
+                               if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+                                       twiceMaxEdgePower =
+                                               min(twiceMaxEdgePower,
+                                                   twiceMinEdgePower);
+                               } else {
+                                       twiceMaxEdgePower = twiceMinEdgePower;
+                                       break;
+                               }
+                       }
+               }
+
+               minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+               switch (pCtlMode[ctlMode]) {
+               case CTL_11B:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+                               targetPowerCck.tPow2x[i] =
+                                       min((u16)targetPowerCck.tPow2x[i],
+                                           minCtlPower);
+                       }
+                       break;
+               case CTL_11G:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+                               targetPowerOfdm.tPow2x[i] =
+                                       min((u16)targetPowerOfdm.tPow2x[i],
+                                           minCtlPower);
+                       }
+                       break;
+               case CTL_2GHT20:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+                               targetPowerHt20.tPow2x[i] =
+                                       min((u16)targetPowerHt20.tPow2x[i],
+                                           minCtlPower);
+                       }
+                       break;
+               case CTL_11B_EXT:
+                       targetPowerCckExt.tPow2x[0] =
+                               min((u16)targetPowerCckExt.tPow2x[0],
+                                   minCtlPower);
+                       break;
+               case CTL_11G_EXT:
+                       targetPowerOfdmExt.tPow2x[0] =
+                               min((u16)targetPowerOfdmExt.tPow2x[0],
+                                   minCtlPower);
+                       break;
+               case CTL_2GHT40:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+                               targetPowerHt40.tPow2x[i] =
+                                       min((u16)targetPowerHt40.tPow2x[i],
+                                           minCtlPower);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       ratesArray[rate6mb] =
+       ratesArray[rate9mb] =
+       ratesArray[rate12mb] =
+       ratesArray[rate18mb] =
+       ratesArray[rate24mb] =
+       targetPowerOfdm.tPow2x[0];
+
+       ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+       ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+       ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+       ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+       for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+               ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+       ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+       ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
+       ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
+       ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
+
+       if (IS_CHAN_HT40(chan)) {
+               for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+                       ratesArray[rateHt40_0 + i] =
+                               targetPowerHt40.tPow2x[i];
+               }
+               ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+               ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+               ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+               ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
+       }
+
+#undef CMP_TEST_GRP
+}
+
+static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
+                                   struct ath9k_channel *chan,
+                                   u16 cfgCtl,
+                                   u8 twiceAntennaReduction,
+                                   u8 powerLimit, bool test)
+{
+       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+       struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
+       int16_t ratesArray[Ar5416RateSize];
+       u8 ht40PowerIncForPdadc = 2;
+       int i;
+
+       memset(ratesArray, 0, sizeof(ratesArray));
+
+       if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+           AR5416_EEP_MINOR_VER_2) {
+               ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+       }
+
+       ath9k_hw_set_4k_power_per_rate_table(ah, chan,
+                                            &ratesArray[0], cfgCtl,
+                                            twiceAntennaReduction,
+                                            powerLimit);
+
+       ath9k_hw_set_4k_power_cal_table(ah, chan);
+
+       regulatory->max_power_level = 0;
+       for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+               if (ratesArray[i] > MAX_RATE_POWER)
+                       ratesArray[i] = MAX_RATE_POWER;
+
+               if (ratesArray[i] > regulatory->max_power_level)
+                       regulatory->max_power_level = ratesArray[i];
+       }
+
+       if (test)
+           return;
+
+       for (i = 0; i < Ar5416RateSize; i++)
+               ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       /* OFDM power per rate */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+                 ATH9K_POW_SM(ratesArray[rate18mb], 24)
+                 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+                 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+                 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+                 ATH9K_POW_SM(ratesArray[rate54mb], 24)
+                 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+                 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+                 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+       /* CCK power per rate */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+                 ATH9K_POW_SM(ratesArray[rate2s], 24)
+                 | ATH9K_POW_SM(ratesArray[rate2l], 16)
+                 | ATH9K_POW_SM(ratesArray[rateXr], 8)
+                 | ATH9K_POW_SM(ratesArray[rate1l], 0));
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+                 ATH9K_POW_SM(ratesArray[rate11s], 24)
+                 | ATH9K_POW_SM(ratesArray[rate11l], 16)
+                 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+                 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+
+       /* HT20 power per rate */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+                 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+                 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+       /* HT40 power per rate */
+       if (IS_CHAN_HT40(chan)) {
+               REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+                         ATH9K_POW_SM(ratesArray[rateHt40_3] +
+                                      ht40PowerIncForPdadc, 24)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+                                        ht40PowerIncForPdadc, 16)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+                                        ht40PowerIncForPdadc, 8)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+                                        ht40PowerIncForPdadc, 0));
+               REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+                         ATH9K_POW_SM(ratesArray[rateHt40_7] +
+                                      ht40PowerIncForPdadc, 24)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+                                        ht40PowerIncForPdadc, 16)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+                                        ht40PowerIncForPdadc, 8)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+                                        ht40PowerIncForPdadc, 0));
+               REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+                         ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+                         | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+                         | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+                         | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+       }
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
+                                struct modal_eep_4k_header *pModal,
+                                struct ar5416_eeprom_4k *eep,
+                                u8 txRxAttenLocal)
+{
+       REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0,
+                 pModal->antCtrlChain[0]);
+
+       REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0),
+                 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
+                  ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+                    AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+                 SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+                 SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+       if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+           AR5416_EEP_MINOR_VER_3) {
+               txRxAttenLocal = pModal->txRxAttenCh[0];
+
+               REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+                             AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
+               REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+                             AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
+               REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+                             AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+                             pModal->xatten2Margin[0]);
+               REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+                             AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
+
+               /* Set the block 1 value to block 0 value */
+               REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+                             AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+                             pModal->bswMargin[0]);
+               REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+                             AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
+               REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+                             AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+                             pModal->xatten2Margin[0]);
+               REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+                             AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+                             pModal->xatten2Db[0]);
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
+                     AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+       REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
+                     AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
+
+       REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
+                     AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+       REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
+                     AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
+}
+
+/*
+ * Read EEPROM header info and program the device for correct operation
+ * given the channel value.
+ */
+static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
+                                        struct ath9k_channel *chan)
+{
+       struct modal_eep_4k_header *pModal;
+       struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+       struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+       u8 txRxAttenLocal;
+       u8 ob[5], db1[5], db2[5];
+       u8 ant_div_control1, ant_div_control2;
+       u8 bb_desired_scale;
+       u32 regVal;
+
+       pModal = &eep->modalHeader;
+       txRxAttenLocal = 23;
+
+       REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
+
+       /* Single chain for 4K EEPROM*/
+       ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal);
+
+       /* Initialize Ant Diversity settings from EEPROM */
+       if (pModal->version >= 3) {
+               ant_div_control1 = pModal->antdiv_ctl1;
+               ant_div_control2 = pModal->antdiv_ctl2;
+
+               regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+               regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
+
+               regVal |= SM(ant_div_control1,
+                            AR_PHY_9285_ANT_DIV_CTL);
+               regVal |= SM(ant_div_control2,
+                            AR_PHY_9285_ANT_DIV_ALT_LNACONF);
+               regVal |= SM((ant_div_control2 >> 2),
+                            AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
+               regVal |= SM((ant_div_control1 >> 1),
+                            AR_PHY_9285_ANT_DIV_ALT_GAINTB);
+               regVal |= SM((ant_div_control1 >> 2),
+                            AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
+
+
+               REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
+               regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+               regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
+               regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+               regVal |= SM((ant_div_control1 >> 3),
+                            AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+               REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
+               regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
+       }
+
+       if (pModal->version >= 2) {
+               ob[0] = pModal->ob_0;
+               ob[1] = pModal->ob_1;
+               ob[2] = pModal->ob_2;
+               ob[3] = pModal->ob_3;
+               ob[4] = pModal->ob_4;
+
+               db1[0] = pModal->db1_0;
+               db1[1] = pModal->db1_1;
+               db1[2] = pModal->db1_2;
+               db1[3] = pModal->db1_3;
+               db1[4] = pModal->db1_4;
+
+               db2[0] = pModal->db2_0;
+               db2[1] = pModal->db2_1;
+               db2[2] = pModal->db2_2;
+               db2[3] = pModal->db2_3;
+               db2[4] = pModal->db2_4;
+       } else if (pModal->version == 1) {
+               ob[0] = pModal->ob_0;
+               ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1;
+               db1[0] = pModal->db1_0;
+               db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1;
+               db2[0] = pModal->db2_0;
+               db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1;
+       } else {
+               int i;
+
+               for (i = 0; i < 5; i++) {
+                       ob[i] = pModal->ob_0;
+                       db1[i] = pModal->db1_0;
+                       db2[i] = pModal->db1_0;
+               }
+       }
+
+       if (AR_SREV_9271(ah)) {
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9271_AN_RF2G3_OB_cck,
+                                         AR9271_AN_RF2G3_OB_cck_S,
+                                         ob[0]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9271_AN_RF2G3_OB_psk,
+                                         AR9271_AN_RF2G3_OB_psk_S,
+                                         ob[1]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9271_AN_RF2G3_OB_qam,
+                                         AR9271_AN_RF2G3_OB_qam_S,
+                                         ob[2]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9271_AN_RF2G3_DB_1,
+                                         AR9271_AN_RF2G3_DB_1_S,
+                                         db1[0]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G4,
+                                         AR9271_AN_RF2G4_DB_2,
+                                         AR9271_AN_RF2G4_DB_2_S,
+                                         db2[0]);
+       } else {
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9285_AN_RF2G3_OB_0,
+                                         AR9285_AN_RF2G3_OB_0_S,
+                                         ob[0]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9285_AN_RF2G3_OB_1,
+                                         AR9285_AN_RF2G3_OB_1_S,
+                                         ob[1]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9285_AN_RF2G3_OB_2,
+                                         AR9285_AN_RF2G3_OB_2_S,
+                                         ob[2]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9285_AN_RF2G3_OB_3,
+                                         AR9285_AN_RF2G3_OB_3_S,
+                                         ob[3]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9285_AN_RF2G3_OB_4,
+                                         AR9285_AN_RF2G3_OB_4_S,
+                                         ob[4]);
+
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9285_AN_RF2G3_DB1_0,
+                                         AR9285_AN_RF2G3_DB1_0_S,
+                                         db1[0]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9285_AN_RF2G3_DB1_1,
+                                         AR9285_AN_RF2G3_DB1_1_S,
+                                         db1[1]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G3,
+                                         AR9285_AN_RF2G3_DB1_2,
+                                         AR9285_AN_RF2G3_DB1_2_S,
+                                         db1[2]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G4,
+                                         AR9285_AN_RF2G4_DB1_3,
+                                         AR9285_AN_RF2G4_DB1_3_S,
+                                         db1[3]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G4,
+                                         AR9285_AN_RF2G4_DB1_4,
+                                         AR9285_AN_RF2G4_DB1_4_S, db1[4]);
+
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G4,
+                                         AR9285_AN_RF2G4_DB2_0,
+                                         AR9285_AN_RF2G4_DB2_0_S,
+                                         db2[0]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G4,
+                                         AR9285_AN_RF2G4_DB2_1,
+                                         AR9285_AN_RF2G4_DB2_1_S,
+                                         db2[1]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G4,
+                                         AR9285_AN_RF2G4_DB2_2,
+                                         AR9285_AN_RF2G4_DB2_2_S,
+                                         db2[2]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G4,
+                                         AR9285_AN_RF2G4_DB2_3,
+                                         AR9285_AN_RF2G4_DB2_3_S,
+                                         db2[3]);
+               ath9k_hw_analog_shift_rmw(ah,
+                                         AR9285_AN_RF2G4,
+                                         AR9285_AN_RF2G4_DB2_4,
+                                         AR9285_AN_RF2G4_DB2_4_S,
+                                         db2[4]);
+       }
+
+
+       REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+                     pModal->switchSettling);
+       REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+                     pModal->adcDesiredSize);
+
+       REG_WRITE(ah, AR_PHY_RF_CTL4,
+                 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
+                 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
+                 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)  |
+                 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+       REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+                     pModal->txEndToRxOn);
+
+       if (AR_SREV_9271_10(ah))
+               REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+                             pModal->txEndToRxOn);
+       REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+                     pModal->thresh62);
+       REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
+                     pModal->thresh62);
+
+       if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+                                               AR5416_EEP_MINOR_VER_2) {
+               REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
+                             pModal->txFrameToDataStart);
+               REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+                             pModal->txFrameToPaOn);
+       }
+
+       if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+                                               AR5416_EEP_MINOR_VER_3) {
+               if (IS_CHAN_HT40(chan))
+                       REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+                                     AR_PHY_SETTLING_SWITCH,
+                                     pModal->swSettleHt40);
+       }
+
+       bb_desired_scale = (pModal->bb_scale_smrt_antenna &
+                       EEP_4K_BB_DESIRED_SCALE_MASK);
+       if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
+               u32 pwrctrl, mask, clr;
+
+               mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
+               pwrctrl = mask * bb_desired_scale;
+               clr = mask * 0x1f;
+               REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
+               REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
+               REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
+
+               mask = BIT(0)|BIT(5)|BIT(15);
+               pwrctrl = mask * bb_desired_scale;
+               clr = mask * 0x1f;
+               REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
+
+               mask = BIT(0)|BIT(5);
+               pwrctrl = mask * bb_desired_scale;
+               clr = mask * 0x1f;
+               REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
+               REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
+       }
+}
+
+static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
+{
+#define EEP_MAP4K_SPURCHAN \
+       (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       u16 spur_val = AR_NO_SPUR;
+
+       ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
+               i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+       switch (ah->config.spurmode) {
+       case SPUR_DISABLE:
+               break;
+       case SPUR_ENABLE_IOCTL:
+               spur_val = ah->config.spurchans[i][is2GHz];
+               ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+                       spur_val);
+               break;
+       case SPUR_ENABLE_EEPROM:
+               spur_val = EEP_MAP4K_SPURCHAN;
+               break;
+       }
+
+       return spur_val;
+
+#undef EEP_MAP4K_SPURCHAN
+}
+
+const struct eeprom_ops eep_4k_ops = {
+       .check_eeprom           = ath9k_hw_4k_check_eeprom,
+       .get_eeprom             = ath9k_hw_4k_get_eeprom,
+       .fill_eeprom            = ath9k_hw_4k_fill_eeprom,
+       .dump_eeprom            = ath9k_hw_4k_dump_eeprom,
+       .get_eeprom_ver         = ath9k_hw_4k_get_eeprom_ver,
+       .get_eeprom_rev         = ath9k_hw_4k_get_eeprom_rev,
+       .set_board_values       = ath9k_hw_4k_set_board_values,
+       .set_txpower            = ath9k_hw_4k_set_txpower,
+       .get_spur_channel       = ath9k_hw_4k_get_spur_channel
+};
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/eeprom_9287.c b/drivers/net/wireless/ath/ath9k_btcoex/eeprom_9287.c
new file mode 100644 (file)
index 0000000..45ceac7
--- /dev/null
@@ -0,0 +1,1075 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <asm/unaligned.h>
+#include "hw.h"
+#include "ar9002_phy.h"
+
+#define SIZE_EEPROM_AR9287 (sizeof(struct ar9287_eeprom) / sizeof(u16))
+
+static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah)
+{
+       return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF;
+}
+
+static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah)
+{
+       return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF;
+}
+
+static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
+{
+       struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u16 *eep_data;
+       int addr, eep_start_loc = AR9287_EEP_START_LOC;
+       eep_data = (u16 *)eep;
+
+       for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
+               if (!ath9k_hw_nvram_read(common, addr + eep_start_loc,
+                                        eep_data)) {
+                       ath_dbg(common, EEPROM,
+                               "Unable to read eeprom region\n");
+                       return false;
+               }
+               eep_data++;
+       }
+
+       return true;
+}
+
+static bool __ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw *ah)
+{
+       u16 *eep_data = (u16 *)&ah->eeprom.map9287;
+
+       ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
+                                    AR9287_HTC_EEP_START_LOC,
+                                    SIZE_EEPROM_AR9287);
+       return true;
+}
+
+static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (!ath9k_hw_use_flash(ah)) {
+               ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
+       }
+
+       if (common->bus_ops->ath_bus_type == ATH_USB)
+               return __ath9k_hw_usb_ar9287_fill_eeprom(ah);
+       else
+               return __ath9k_hw_ar9287_fill_eeprom(ah);
+}
+
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size,
+                                   struct modal_eep_ar9287_header *modal_hdr)
+{
+       PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
+       PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]);
+       PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
+       PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
+       PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
+       PR_EEP("Switch Settle", modal_hdr->switchSettling);
+       PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
+       PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
+       PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
+       PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
+       PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+       PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
+       PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
+       PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+       PR_EEP("CCA Threshold)", modal_hdr->thresh62);
+       PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+       PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
+       PR_EEP("xpdGain", modal_hdr->xpdGain);
+       PR_EEP("External PD", modal_hdr->xpd);
+       PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
+       PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
+       PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
+       PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
+       PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
+       PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+       PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+       PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+       PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
+       PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
+       PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
+       PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
+       PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
+       PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
+       PR_EEP("AR92x7 Version", modal_hdr->version);
+       PR_EEP("DriverBias1", modal_hdr->db1);
+       PR_EEP("DriverBias2", modal_hdr->db1);
+       PR_EEP("CCK OutputBias", modal_hdr->ob_cck);
+       PR_EEP("PSK OutputBias", modal_hdr->ob_psk);
+       PR_EEP("QAM OutputBias", modal_hdr->ob_qam);
+       PR_EEP("PAL_OFF OutputBias", modal_hdr->ob_pal_off);
+
+       return len;
+}
+
+static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+                                      u8 *buf, u32 len, u32 size)
+{
+       struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+       struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
+
+       if (!dump_base_hdr) {
+               len += snprintf(buf + len, size - len,
+                               "%20s :\n", "2GHz modal Header");
+               len = ar9287_dump_modal_eeprom(buf, len, size,
+                                               &eep->modalHeader);
+               goto out;
+       }
+
+       PR_EEP("Major Version", pBase->version >> 12);
+       PR_EEP("Minor Version", pBase->version & 0xFFF);
+       PR_EEP("Checksum", pBase->checksum);
+       PR_EEP("Length", pBase->length);
+       PR_EEP("RegDomain1", pBase->regDmn[0]);
+       PR_EEP("RegDomain2", pBase->regDmn[1]);
+       PR_EEP("TX Mask", pBase->txMask);
+       PR_EEP("RX Mask", pBase->rxMask);
+       PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
+       PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
+       PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_2G_HT20));
+       PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_2G_HT40));
+       PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_5G_HT20));
+       PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_5G_HT40));
+       PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
+       PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
+       PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
+       PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
+       PR_EEP("Power Table Offset", pBase->pwrTableOffset);
+       PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
+
+       len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+                       pBase->macAddr);
+
+out:
+       if (len > size)
+               len = size;
+
+       return len;
+}
+#else
+static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+                                      u8 *buf, u32 len, u32 size)
+{
+       return 0;
+}
+#endif
+
+
+static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
+{
+       u32 sum = 0, el, integer;
+       u16 temp, word, magic, magic2, *eepdata;
+       int i, addr;
+       bool need_swap = false;
+       struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (!ath9k_hw_use_flash(ah)) {
+               if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
+                                        &magic)) {
+                       ath_err(common, "Reading Magic # failed\n");
+                       return false;
+               }
+
+               ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
+
+               if (magic != AR5416_EEPROM_MAGIC) {
+                       magic2 = swab16(magic);
+
+                       if (magic2 == AR5416_EEPROM_MAGIC) {
+                               need_swap = true;
+                               eepdata = (u16 *)(&ah->eeprom);
+
+                               for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
+                                       temp = swab16(*eepdata);
+                                       *eepdata = temp;
+                                       eepdata++;
+                               }
+                       } else {
+                               ath_err(common,
+                                       "Invalid EEPROM Magic. Endianness mismatch.\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       ath_dbg(common, EEPROM, "need_swap = %s\n",
+               need_swap ? "True" : "False");
+
+       if (need_swap)
+               el = swab16(ah->eeprom.map9287.baseEepHeader.length);
+       else
+               el = ah->eeprom.map9287.baseEepHeader.length;
+
+       if (el > sizeof(struct ar9287_eeprom))
+               el = sizeof(struct ar9287_eeprom) / sizeof(u16);
+       else
+               el = el / sizeof(u16);
+
+       eepdata = (u16 *)(&ah->eeprom);
+
+       for (i = 0; i < el; i++)
+               sum ^= *eepdata++;
+
+       if (need_swap) {
+               word = swab16(eep->baseEepHeader.length);
+               eep->baseEepHeader.length = word;
+
+               word = swab16(eep->baseEepHeader.checksum);
+               eep->baseEepHeader.checksum = word;
+
+               word = swab16(eep->baseEepHeader.version);
+               eep->baseEepHeader.version = word;
+
+               word = swab16(eep->baseEepHeader.regDmn[0]);
+               eep->baseEepHeader.regDmn[0] = word;
+
+               word = swab16(eep->baseEepHeader.regDmn[1]);
+               eep->baseEepHeader.regDmn[1] = word;
+
+               word = swab16(eep->baseEepHeader.rfSilent);
+               eep->baseEepHeader.rfSilent = word;
+
+               word = swab16(eep->baseEepHeader.blueToothOptions);
+               eep->baseEepHeader.blueToothOptions = word;
+
+               word = swab16(eep->baseEepHeader.deviceCap);
+               eep->baseEepHeader.deviceCap = word;
+
+               integer = swab32(eep->modalHeader.antCtrlCommon);
+               eep->modalHeader.antCtrlCommon = integer;
+
+               for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+                       integer = swab32(eep->modalHeader.antCtrlChain[i]);
+                       eep->modalHeader.antCtrlChain[i] = integer;
+               }
+
+               for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+                       word = swab16(eep->modalHeader.spurChans[i].spurChan);
+                       eep->modalHeader.spurChans[i].spurChan = word;
+               }
+       }
+
+       if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
+           || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+               ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+                       sum, ah->eep_ops->get_eeprom_ver(ah));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
+                                     enum eeprom_param param)
+{
+       struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+       struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
+       struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
+       u16 ver_minor;
+
+       ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK;
+
+       switch (param) {
+       case EEP_NFTHRESH_2:
+               return pModal->noiseFloorThreshCh[0];
+       case EEP_MAC_LSW:
+               return get_unaligned_be16(pBase->macAddr);
+       case EEP_MAC_MID:
+               return get_unaligned_be16(pBase->macAddr + 2);
+       case EEP_MAC_MSW:
+               return get_unaligned_be16(pBase->macAddr + 4);
+       case EEP_REG_0:
+               return pBase->regDmn[0];
+       case EEP_OP_CAP:
+               return pBase->deviceCap;
+       case EEP_OP_MODE:
+               return pBase->opCapFlags;
+       case EEP_RF_SILENT:
+               return pBase->rfSilent;
+       case EEP_MINOR_REV:
+               return ver_minor;
+       case EEP_TX_MASK:
+               return pBase->txMask;
+       case EEP_RX_MASK:
+               return pBase->rxMask;
+       case EEP_DEV_TYPE:
+               return pBase->deviceType;
+       case EEP_OL_PWRCTRL:
+               return pBase->openLoopPwrCntl;
+       case EEP_TEMPSENSE_SLOPE:
+               if (ver_minor >= AR9287_EEP_MINOR_VER_2)
+                       return pBase->tempSensSlope;
+               else
+                       return 0;
+       case EEP_TEMPSENSE_SLOPE_PAL_ON:
+               if (ver_minor >= AR9287_EEP_MINOR_VER_3)
+                       return pBase->tempSensSlopePalOn;
+               else
+                       return 0;
+       case EEP_ANTENNA_GAIN_2G:
+               return max_t(u8, pModal->antennaGainCh[0],
+                                pModal->antennaGainCh[1]);
+       default:
+               return 0;
+       }
+}
+
+static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
+                           struct ath9k_channel *chan,
+                           struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
+                           u8 *pCalChans,  u16 availPiers, int8_t *pPwr)
+{
+       u16 idxL = 0, idxR = 0, numPiers;
+       bool match;
+       struct chan_centers centers;
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+       for (numPiers = 0; numPiers < availPiers; numPiers++) {
+               if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED)
+                       break;
+       }
+
+       match = ath9k_hw_get_lower_upper_index(
+               (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+               pCalChans, numPiers, &idxL, &idxR);
+
+       if (match) {
+               *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0];
+       } else {
+               *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
+                        (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
+       }
+
+}
+
+static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
+                                         int32_t txPower, u16 chain)
+{
+       u32 tmpVal;
+       u32 a;
+
+       /* Enable OLPC for chain 0 */
+
+       tmpVal = REG_READ(ah, 0xa270);
+       tmpVal = tmpVal & 0xFCFFFFFF;
+       tmpVal = tmpVal | (0x3 << 24);
+       REG_WRITE(ah, 0xa270, tmpVal);
+
+       /* Enable OLPC for chain 1 */
+
+       tmpVal = REG_READ(ah, 0xb270);
+       tmpVal = tmpVal & 0xFCFFFFFF;
+       tmpVal = tmpVal | (0x3 << 24);
+       REG_WRITE(ah, 0xb270, tmpVal);
+
+       /* Write the OLPC ref power for chain 0 */
+
+       if (chain == 0) {
+               tmpVal = REG_READ(ah, 0xa398);
+               tmpVal = tmpVal & 0xff00ffff;
+               a = (txPower)&0xff;
+               tmpVal = tmpVal | (a << 16);
+               REG_WRITE(ah, 0xa398, tmpVal);
+       }
+
+       /* Write the OLPC ref power for chain 1 */
+
+       if (chain == 1) {
+               tmpVal = REG_READ(ah, 0xb398);
+               tmpVal = tmpVal & 0xff00ffff;
+               a = (txPower)&0xff;
+               tmpVal = tmpVal | (a << 16);
+               REG_WRITE(ah, 0xb398, tmpVal);
+       }
+}
+
+static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
+                                               struct ath9k_channel *chan)
+{
+       struct cal_data_per_freq_ar9287 *pRawDataset;
+       struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
+       u8 *pCalBChans = NULL;
+       u16 pdGainOverlap_t2;
+       u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+       u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+       u16 numPiers = 0, i, j;
+       u16 numXpdGain, xpdMask;
+       u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0};
+       u32 reg32, regOffset, regChainOffset, regval;
+       int16_t diff = 0;
+       struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
+
+       xpdMask = pEepData->modalHeader.xpdGain;
+
+       if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
+           AR9287_EEP_MINOR_VER_2)
+               pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
+       else
+               pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+                                           AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+
+       if (IS_CHAN_2GHZ(chan)) {
+               pCalBChans = pEepData->calFreqPier2G;
+               numPiers = AR9287_NUM_2G_CAL_PIERS;
+               if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+                       pRawDatasetOpenLoop =
+                       (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0];
+                       ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0];
+               }
+       }
+
+       numXpdGain = 0;
+
+       /* Calculate the value of xpdgains from the xpdGain Mask */
+       for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+               if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+                       if (numXpdGain >= AR5416_NUM_PD_GAINS)
+                               break;
+                       xpdGainValues[numXpdGain] =
+                               (u16)(AR5416_PD_GAINS_IN_MASK-i);
+                       numXpdGain++;
+               }
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+                     (numXpdGain - 1) & 0x3);
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+                     xpdGainValues[0]);
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+                     xpdGainValues[1]);
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+                     xpdGainValues[2]);
+
+       for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+               regChainOffset = i * 0x1000;
+
+               if (pEepData->baseEepHeader.txMask & (1 << i)) {
+                       pRawDatasetOpenLoop =
+                       (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i];
+
+                       if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+                               int8_t txPower;
+                               ar9287_eeprom_get_tx_gain_index(ah, chan,
+                                                       pRawDatasetOpenLoop,
+                                                       pCalBChans, numPiers,
+                                                       &txPower);
+                               ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i);
+                       } else {
+                               pRawDataset =
+                                       (struct cal_data_per_freq_ar9287 *)
+                                       pEepData->calPierData2G[i];
+
+                               ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
+                                                          pRawDataset,
+                                                          pCalBChans, numPiers,
+                                                          pdGainOverlap_t2,
+                                                          gainBoundaries,
+                                                          pdadcValues,
+                                                          numXpdGain);
+                       }
+
+                       ENABLE_REGWRITE_BUFFER(ah);
+
+                       if (i == 0) {
+                               if (!ath9k_hw_ar9287_get_eeprom(ah,
+                                                       EEP_OL_PWRCTRL)) {
+
+                                       regval = SM(pdGainOverlap_t2,
+                                                   AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+                                               | SM(gainBoundaries[0],
+                                                    AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+                                               | SM(gainBoundaries[1],
+                                                    AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+                                               | SM(gainBoundaries[2],
+                                                    AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+                                               | SM(gainBoundaries[3],
+                                                    AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4);
+
+                                       REG_WRITE(ah,
+                                                 AR_PHY_TPCRG5 + regChainOffset,
+                                                 regval);
+                               }
+                       }
+
+                       if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB !=
+                           pEepData->baseEepHeader.pwrTableOffset) {
+                               diff = (u16)(pEepData->baseEepHeader.pwrTableOffset -
+                                            (int32_t)AR9287_PWR_TABLE_OFFSET_DB);
+                               diff *= 2;
+
+                               for (j = 0; j < ((u16)AR5416_NUM_PDADC_VALUES-diff); j++)
+                                       pdadcValues[j] = pdadcValues[j+diff];
+
+                               for (j = (u16)(AR5416_NUM_PDADC_VALUES-diff);
+                                    j < AR5416_NUM_PDADC_VALUES; j++)
+                                       pdadcValues[j] =
+                                         pdadcValues[AR5416_NUM_PDADC_VALUES-diff];
+                       }
+
+                       if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+                               regOffset = AR_PHY_BASE +
+                                       (672 << 2) + regChainOffset;
+
+                               for (j = 0; j < 32; j++) {
+                                       reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
+
+                                       REG_WRITE(ah, regOffset, reg32);
+                                       regOffset += 4;
+                               }
+                       }
+                       REGWRITE_BUFFER_FLUSH(ah);
+               }
+       }
+}
+
+static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
+                                                    struct ath9k_channel *chan,
+                                                    int16_t *ratesArray,
+                                                    u16 cfgCtl,
+                                                    u16 antenna_reduction,
+                                                    u16 powerLimit)
+{
+#define CMP_CTL \
+       (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+        pEepData->ctlIndex[i])
+
+#define CMP_NO_CTL \
+       (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+        ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
+
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN   10
+
+       u16 twiceMaxEdgePower;
+       int i;
+       struct cal_ctl_data_ar9287 *rep;
+       struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
+                                   targetPowerCck = {0, {0, 0, 0, 0} };
+       struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} },
+                                   targetPowerCckExt = {0, {0, 0, 0, 0} };
+       struct cal_target_power_ht targetPowerHt20,
+                                   targetPowerHt40 = {0, {0, 0, 0, 0} };
+       u16 scaledPower = 0, minCtlPower;
+       static const u16 ctlModesFor11g[] = {
+               CTL_11B, CTL_11G, CTL_2GHT20,
+               CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+       };
+       u16 numCtlModes = 0;
+       const u16 *pCtlMode = NULL;
+       u16 ctlMode, freq;
+       struct chan_centers centers;
+       int tx_chainmask;
+       u16 twiceMinEdgePower;
+       struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
+       tx_chainmask = ah->txchainmask;
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       scaledPower = powerLimit - antenna_reduction;
+
+       /*
+        * Reduce scaled Power by number of chains active
+        * to get the per chain tx power level.
+        */
+       switch (ar5416_get_ntxchains(tx_chainmask)) {
+       case 1:
+               break;
+       case 2:
+               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               else
+                       scaledPower = 0;
+               break;
+       case 3:
+               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               else
+                       scaledPower = 0;
+               break;
+       }
+       scaledPower = max((u16)0, scaledPower);
+
+       /*
+        * Get TX power from EEPROM.
+        */
+       if (IS_CHAN_2GHZ(chan)) {
+               /* CTL_11B, CTL_11G, CTL_2GHT20 */
+               numCtlModes =
+                       ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+
+               pCtlMode = ctlModesFor11g;
+
+               ath9k_hw_get_legacy_target_powers(ah, chan,
+                                                 pEepData->calTargetPowerCck,
+                                                 AR9287_NUM_2G_CCK_TARGET_POWERS,
+                                                 &targetPowerCck, 4, false);
+               ath9k_hw_get_legacy_target_powers(ah, chan,
+                                                 pEepData->calTargetPower2G,
+                                                 AR9287_NUM_2G_20_TARGET_POWERS,
+                                                 &targetPowerOfdm, 4, false);
+               ath9k_hw_get_target_powers(ah, chan,
+                                          pEepData->calTargetPower2GHT20,
+                                          AR9287_NUM_2G_20_TARGET_POWERS,
+                                          &targetPowerHt20, 8, false);
+
+               if (IS_CHAN_HT40(chan)) {
+                       /* All 2G CTLs */
+                       numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+                       ath9k_hw_get_target_powers(ah, chan,
+                                                  pEepData->calTargetPower2GHT40,
+                                                  AR9287_NUM_2G_40_TARGET_POWERS,
+                                                  &targetPowerHt40, 8, true);
+                       ath9k_hw_get_legacy_target_powers(ah, chan,
+                                                 pEepData->calTargetPowerCck,
+                                                 AR9287_NUM_2G_CCK_TARGET_POWERS,
+                                                 &targetPowerCckExt, 4, true);
+                       ath9k_hw_get_legacy_target_powers(ah, chan,
+                                                 pEepData->calTargetPower2G,
+                                                 AR9287_NUM_2G_20_TARGET_POWERS,
+                                                 &targetPowerOfdmExt, 4, true);
+               }
+       }
+
+       for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+               bool isHt40CtlMode =
+                       (pCtlMode[ctlMode] == CTL_2GHT40) ? true : false;
+
+               if (isHt40CtlMode)
+                       freq = centers.synth_center;
+               else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+                       freq = centers.ext_center;
+               else
+                       freq = centers.ctl_center;
+
+               twiceMaxEdgePower = MAX_RATE_POWER;
+               /* Walk through the CTL indices stored in EEPROM */
+               for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+                       struct cal_ctl_edges *pRdEdgesPower;
+
+                       /*
+                        * Compare test group from regulatory channel list
+                        * with test mode from pCtlMode list
+                        */
+                       if (CMP_CTL || CMP_NO_CTL) {
+                               rep = &(pEepData->ctlData[i]);
+                               pRdEdgesPower =
+                               rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1];
+
+                               twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
+                                                               pRdEdgesPower,
+                                                               IS_CHAN_2GHZ(chan),
+                                                               AR5416_NUM_BAND_EDGES);
+
+                               if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+                                       twiceMaxEdgePower = min(twiceMaxEdgePower,
+                                                               twiceMinEdgePower);
+                               } else {
+                                       twiceMaxEdgePower = twiceMinEdgePower;
+                                       break;
+                               }
+                       }
+               }
+
+               minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+               /* Apply ctl mode to correct target power set */
+               switch (pCtlMode[ctlMode]) {
+               case CTL_11B:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+                               targetPowerCck.tPow2x[i] =
+                                       (u8)min((u16)targetPowerCck.tPow2x[i],
+                                               minCtlPower);
+                       }
+                       break;
+               case CTL_11A:
+               case CTL_11G:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+                               targetPowerOfdm.tPow2x[i] =
+                                       (u8)min((u16)targetPowerOfdm.tPow2x[i],
+                                               minCtlPower);
+                       }
+                       break;
+               case CTL_5GHT20:
+               case CTL_2GHT20:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+                               targetPowerHt20.tPow2x[i] =
+                                       (u8)min((u16)targetPowerHt20.tPow2x[i],
+                                               minCtlPower);
+                       }
+                       break;
+               case CTL_11B_EXT:
+                       targetPowerCckExt.tPow2x[0] =
+                               (u8)min((u16)targetPowerCckExt.tPow2x[0],
+                                       minCtlPower);
+                       break;
+               case CTL_11A_EXT:
+               case CTL_11G_EXT:
+                       targetPowerOfdmExt.tPow2x[0] =
+                               (u8)min((u16)targetPowerOfdmExt.tPow2x[0],
+                                       minCtlPower);
+                       break;
+               case CTL_5GHT40:
+               case CTL_2GHT40:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+                               targetPowerHt40.tPow2x[i] =
+                                       (u8)min((u16)targetPowerHt40.tPow2x[i],
+                                               minCtlPower);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /* Now set the rates array */
+
+       ratesArray[rate6mb] =
+       ratesArray[rate9mb] =
+       ratesArray[rate12mb] =
+       ratesArray[rate18mb] =
+       ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0];
+
+       ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+       ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+       ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+       ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+       for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+               ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+       if (IS_CHAN_2GHZ(chan)) {
+               ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+               ratesArray[rate2s] =
+               ratesArray[rate2l] = targetPowerCck.tPow2x[1];
+               ratesArray[rate5_5s] =
+               ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
+               ratesArray[rate11s] =
+               ratesArray[rate11l] = targetPowerCck.tPow2x[3];
+       }
+       if (IS_CHAN_HT40(chan)) {
+               for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++)
+                       ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
+
+               ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+               ratesArray[rateDupCck]  = targetPowerHt40.tPow2x[0];
+               ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+
+               if (IS_CHAN_2GHZ(chan))
+                       ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
+       }
+
+#undef CMP_CTL
+#undef CMP_NO_CTL
+#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN
+#undef REDUCE_SCALED_POWER_BY_THREE_CHAIN
+}
+
+static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
+                                       struct ath9k_channel *chan, u16 cfgCtl,
+                                       u8 twiceAntennaReduction,
+                                       u8 powerLimit, bool test)
+{
+       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
+       struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
+       int16_t ratesArray[Ar5416RateSize];
+       u8 ht40PowerIncForPdadc = 2;
+       int i;
+
+       memset(ratesArray, 0, sizeof(ratesArray));
+
+       if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
+           AR9287_EEP_MINOR_VER_2)
+               ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+
+       ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
+                                                &ratesArray[0], cfgCtl,
+                                                twiceAntennaReduction,
+                                                powerLimit);
+
+       ath9k_hw_set_ar9287_power_cal_table(ah, chan);
+
+       regulatory->max_power_level = 0;
+       for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+               if (ratesArray[i] > MAX_RATE_POWER)
+                       ratesArray[i] = MAX_RATE_POWER;
+
+               if (ratesArray[i] > regulatory->max_power_level)
+                       regulatory->max_power_level = ratesArray[i];
+       }
+
+       ath9k_hw_update_regulatory_maxpower(ah);
+
+       if (test)
+               return;
+
+       for (i = 0; i < Ar5416RateSize; i++)
+               ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       /* OFDM power per rate */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+                 ATH9K_POW_SM(ratesArray[rate18mb], 24)
+                 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+                 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+                 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+                 ATH9K_POW_SM(ratesArray[rate54mb], 24)
+                 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+                 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+                 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+       /* CCK power per rate */
+       if (IS_CHAN_2GHZ(chan)) {
+               REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+                         ATH9K_POW_SM(ratesArray[rate2s], 24)
+                         | ATH9K_POW_SM(ratesArray[rate2l], 16)
+                         | ATH9K_POW_SM(ratesArray[rateXr], 8)
+                         | ATH9K_POW_SM(ratesArray[rate1l], 0));
+               REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+                         ATH9K_POW_SM(ratesArray[rate11s], 24)
+                         | ATH9K_POW_SM(ratesArray[rate11l], 16)
+                         | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+                         | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+       }
+
+       /* HT20 power per rate */
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+                 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+                 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+       /* HT40 power per rate */
+       if (IS_CHAN_HT40(chan)) {
+               if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+                       REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+                                 ATH9K_POW_SM(ratesArray[rateHt40_3], 24)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_2], 16)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_1], 8)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_0], 0));
+
+                       REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+                                 ATH9K_POW_SM(ratesArray[rateHt40_7], 24)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_6], 16)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_5], 8)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_4], 0));
+               } else {
+                       REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+                                 ATH9K_POW_SM(ratesArray[rateHt40_3] +
+                                              ht40PowerIncForPdadc, 24)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+                                                ht40PowerIncForPdadc, 16)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+                                                ht40PowerIncForPdadc, 8)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+                                                ht40PowerIncForPdadc, 0));
+
+                       REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+                                 ATH9K_POW_SM(ratesArray[rateHt40_7] +
+                                              ht40PowerIncForPdadc, 24)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+                                                ht40PowerIncForPdadc, 16)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+                                                ht40PowerIncForPdadc, 8)
+                                 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+                                                ht40PowerIncForPdadc, 0));
+               }
+
+               /* Dup/Ext power per rate */
+               REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+                         ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+                         | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+                         | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+                         | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+       }
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
+                                            struct ath9k_channel *chan)
+{
+       struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+       struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
+       u32 regChainOffset, regval;
+       u8 txRxAttenLocal;
+       int i;
+
+       pModal = &eep->modalHeader;
+
+       REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
+
+       for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+               regChainOffset = i * 0x1000;
+
+               REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+                         pModal->antCtrlChain[i]);
+
+               REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+                         (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset)
+                          & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+                              AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+                         SM(pModal->iqCalICh[i],
+                            AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+                         SM(pModal->iqCalQCh[i],
+                            AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+               txRxAttenLocal = pModal->txRxAttenCh[i];
+
+               REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+                             AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+                             pModal->bswMargin[i]);
+               REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+                             AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+                             pModal->bswAtten[i]);
+               REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+                             AR9280_PHY_RXGAIN_TXRX_ATTEN,
+                             txRxAttenLocal);
+               REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+                             AR9280_PHY_RXGAIN_TXRX_MARGIN,
+                             pModal->rxTxMarginCh[i]);
+       }
+
+
+       if (IS_CHAN_HT40(chan))
+               REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+                             AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
+       else
+               REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+                             AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
+
+       REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+                     AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
+
+       REG_WRITE(ah, AR_PHY_RF_CTL4,
+                 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+                 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+                 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+                 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+       REG_RMW_FIELD(ah, AR_PHY_RF_CTL3,
+                     AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
+
+       REG_RMW_FIELD(ah, AR_PHY_CCA,
+                     AR9280_PHY_CCA_THRESH62, pModal->thresh62);
+       REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
+                     AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62);
+
+       regval = REG_READ(ah, AR9287_AN_RF2G3_CH0);
+       regval &= ~(AR9287_AN_RF2G3_DB1 |
+                   AR9287_AN_RF2G3_DB2 |
+                   AR9287_AN_RF2G3_OB_CCK |
+                   AR9287_AN_RF2G3_OB_PSK |
+                   AR9287_AN_RF2G3_OB_QAM |
+                   AR9287_AN_RF2G3_OB_PAL_OFF);
+       regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
+                  SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
+                  SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
+                  SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
+                  SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
+                  SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
+
+       ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH0, regval);
+
+       regval = REG_READ(ah, AR9287_AN_RF2G3_CH1);
+       regval &= ~(AR9287_AN_RF2G3_DB1 |
+                   AR9287_AN_RF2G3_DB2 |
+                   AR9287_AN_RF2G3_OB_CCK |
+                   AR9287_AN_RF2G3_OB_PSK |
+                   AR9287_AN_RF2G3_OB_QAM |
+                   AR9287_AN_RF2G3_OB_PAL_OFF);
+       regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
+                  SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
+                  SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
+                  SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
+                  SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
+                  SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
+
+       ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH1, regval);
+
+       REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+                     AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart);
+       REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+                     AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn);
+
+       ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2,
+                                 AR9287_AN_TOP2_XPABIAS_LVL,
+                                 AR9287_AN_TOP2_XPABIAS_LVL_S,
+                                 pModal->xpaBiasLvl);
+}
+
+static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
+                                           u16 i, bool is2GHz)
+{
+#define EEP_MAP9287_SPURCHAN \
+       (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
+
+       struct ath_common *common = ath9k_hw_common(ah);
+       u16 spur_val = AR_NO_SPUR;
+
+       ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
+               i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+       switch (ah->config.spurmode) {
+       case SPUR_DISABLE:
+               break;
+       case SPUR_ENABLE_IOCTL:
+               spur_val = ah->config.spurchans[i][is2GHz];
+               ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+                       spur_val);
+               break;
+       case SPUR_ENABLE_EEPROM:
+               spur_val = EEP_MAP9287_SPURCHAN;
+               break;
+       }
+
+       return spur_val;
+
+#undef EEP_MAP9287_SPURCHAN
+}
+
+const struct eeprom_ops eep_ar9287_ops = {
+       .check_eeprom           = ath9k_hw_ar9287_check_eeprom,
+       .get_eeprom             = ath9k_hw_ar9287_get_eeprom,
+       .fill_eeprom            = ath9k_hw_ar9287_fill_eeprom,
+       .dump_eeprom            = ath9k_hw_ar9287_dump_eeprom,
+       .get_eeprom_ver         = ath9k_hw_ar9287_get_eeprom_ver,
+       .get_eeprom_rev         = ath9k_hw_ar9287_get_eeprom_rev,
+       .set_board_values       = ath9k_hw_ar9287_set_board_values,
+       .set_txpower            = ath9k_hw_ar9287_set_txpower,
+       .get_spur_channel       = ath9k_hw_ar9287_get_spur_channel
+};
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/eeprom_def.c b/drivers/net/wireless/ath/ath9k_btcoex/eeprom_def.c
new file mode 100644 (file)
index 0000000..b6163e2
--- /dev/null
@@ -0,0 +1,1426 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <asm/unaligned.h>
+#include "hw.h"
+#include "ar9002_phy.h"
+
+static void ath9k_get_txgain_index(struct ath_hw *ah,
+               struct ath9k_channel *chan,
+               struct calDataPerFreqOpLoop *rawDatasetOpLoop,
+               u8 *calChans,  u16 availPiers, u8 *pwr, u8 *pcdacIdx)
+{
+       u8 pcdac, i = 0;
+       u16 idxL = 0, idxR = 0, numPiers;
+       bool match;
+       struct chan_centers centers;
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+       for (numPiers = 0; numPiers < availPiers; numPiers++)
+               if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
+                       break;
+
+       match = ath9k_hw_get_lower_upper_index(
+                       (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+                       calChans, numPiers, &idxL, &idxR);
+       if (match) {
+               pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
+               *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
+       } else {
+               pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
+               *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
+                               rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
+       }
+
+       while (pcdac > ah->originalGain[i] &&
+                       i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
+               i++;
+
+       *pcdacIdx = i;
+}
+
+static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
+                               u32 initTxGain,
+                               int txPower,
+                               u8 *pPDADCValues)
+{
+       u32 i;
+       u32 offset;
+
+       REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
+                       AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+       REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
+                       AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+
+       REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
+                       AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
+
+       offset = txPower;
+       for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
+               if (i < offset)
+                       pPDADCValues[i] = 0x0;
+               else
+                       pPDADCValues[i] = 0xFF;
+}
+
+static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
+{
+       return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
+}
+
+static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
+{
+       return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
+}
+
+#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
+
+static bool __ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u16 *eep_data = (u16 *)&ah->eeprom.def;
+       int addr, ar5416_eep_start_loc = 0x100;
+
+       for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
+               if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc,
+                                        eep_data)) {
+                       ath_err(ath9k_hw_common(ah),
+                               "Unable to read eeprom region\n");
+                       return false;
+               }
+               eep_data++;
+       }
+       return true;
+}
+
+static bool __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah)
+{
+       u16 *eep_data = (u16 *)&ah->eeprom.def;
+
+       ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
+                                    0x100, SIZE_EEPROM_DEF);
+       return true;
+}
+
+static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (!ath9k_hw_use_flash(ah)) {
+               ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
+       }
+
+       if (common->bus_ops->ath_bus_type == ATH_USB)
+               return __ath9k_hw_usb_def_fill_eeprom(ah);
+       else
+               return __ath9k_hw_def_fill_eeprom(ah);
+}
+
+#undef SIZE_EEPROM_DEF
+
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
+                                      struct modal_eep_header *modal_hdr)
+{
+       PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
+       PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]);
+       PR_EEP("Chain2 Ant. Control", modal_hdr->antCtrlChain[2]);
+       PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
+       PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
+       PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
+       PR_EEP("Chain2 Ant. Gain", modal_hdr->antennaGainCh[2]);
+       PR_EEP("Switch Settle", modal_hdr->switchSettling);
+       PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
+       PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
+       PR_EEP("Chain2 TxRxAtten", modal_hdr->txRxAttenCh[2]);
+       PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
+       PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
+       PR_EEP("Chain2 RxTxMargin", modal_hdr->rxTxMarginCh[2]);
+       PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+       PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);
+       PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);
+       PR_EEP("Chain1 xlna Gain", modal_hdr->xlnaGainCh[1]);
+       PR_EEP("Chain2 xlna Gain", modal_hdr->xlnaGainCh[2]);
+       PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
+       PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
+       PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+       PR_EEP("CCA Threshold)", modal_hdr->thresh62);
+       PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+       PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
+       PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);
+       PR_EEP("xpdGain", modal_hdr->xpdGain);
+       PR_EEP("External PD", modal_hdr->xpd);
+       PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
+       PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
+       PR_EEP("Chain2 I Coefficient", modal_hdr->iqCalICh[2]);
+       PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
+       PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
+       PR_EEP("Chain2 Q Coefficient", modal_hdr->iqCalQCh[2]);
+       PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
+       PR_EEP("Chain0 OutputBias", modal_hdr->ob);
+       PR_EEP("Chain0 DriverBias", modal_hdr->db);
+       PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+       PR_EEP("2chain pwr decrease", modal_hdr->pwrDecreaseFor2Chain);
+       PR_EEP("3chain pwr decrease", modal_hdr->pwrDecreaseFor3Chain);
+       PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+       PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+       PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
+       PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
+       PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
+       PR_EEP("Chain2 bswAtten", modal_hdr->bswAtten[2]);
+       PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
+       PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
+       PR_EEP("Chain2 bswMargin", modal_hdr->bswMargin[2]);
+       PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
+       PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);
+       PR_EEP("Chain1 xatten2Db", modal_hdr->xatten2Db[1]);
+       PR_EEP("Chain2 xatten2Db", modal_hdr->xatten2Db[2]);
+       PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);
+       PR_EEP("Chain1 xatten2Margin", modal_hdr->xatten2Margin[1]);
+       PR_EEP("Chain2 xatten2Margin", modal_hdr->xatten2Margin[2]);
+       PR_EEP("Chain1 OutputBias", modal_hdr->ob_ch1);
+       PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1);
+       PR_EEP("LNA Control", modal_hdr->lna_ctl);
+       PR_EEP("XPA Bias Freq0", modal_hdr->xpaBiasLvlFreq[0]);
+       PR_EEP("XPA Bias Freq1", modal_hdr->xpaBiasLvlFreq[1]);
+       PR_EEP("XPA Bias Freq2", modal_hdr->xpaBiasLvlFreq[2]);
+
+       return len;
+}
+
+static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+                                   u8 *buf, u32 len, u32 size)
+{
+       struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+       struct base_eep_header *pBase = &eep->baseEepHeader;
+
+       if (!dump_base_hdr) {
+               len += snprintf(buf + len, size - len,
+                               "%20s :\n", "2GHz modal Header");
+               len = ath9k_def_dump_modal_eeprom(buf, len, size,
+                                                  &eep->modalHeader[0]);
+               len += snprintf(buf + len, size - len,
+                               "%20s :\n", "5GHz modal Header");
+               len = ath9k_def_dump_modal_eeprom(buf, len, size,
+                                                  &eep->modalHeader[1]);
+               goto out;
+       }
+
+       PR_EEP("Major Version", pBase->version >> 12);
+       PR_EEP("Minor Version", pBase->version & 0xFFF);
+       PR_EEP("Checksum", pBase->checksum);
+       PR_EEP("Length", pBase->length);
+       PR_EEP("RegDomain1", pBase->regDmn[0]);
+       PR_EEP("RegDomain2", pBase->regDmn[1]);
+       PR_EEP("TX Mask", pBase->txMask);
+       PR_EEP("RX Mask", pBase->rxMask);
+       PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
+       PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
+       PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_2G_HT20));
+       PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_2G_HT40));
+       PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_5G_HT20));
+       PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
+                                       AR5416_OPFLAGS_N_5G_HT40));
+       PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
+       PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
+       PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
+       PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
+       PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
+
+       len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+                       pBase->macAddr);
+
+out:
+       if (len > size)
+               len = size;
+
+       return len;
+}
+#else
+static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+                                   u8 *buf, u32 len, u32 size)
+{
+       return 0;
+}
+#endif
+
+
+static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
+{
+       struct ar5416_eeprom_def *eep =
+               (struct ar5416_eeprom_def *) &ah->eeprom.def;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u16 *eepdata, temp, magic, magic2;
+       u32 sum = 0, el;
+       bool need_swap = false;
+       int i, addr, size;
+
+       if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+               ath_err(common, "Reading Magic # failed\n");
+               return false;
+       }
+
+       if (!ath9k_hw_use_flash(ah)) {
+               ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
+
+               if (magic != AR5416_EEPROM_MAGIC) {
+                       magic2 = swab16(magic);
+
+                       if (magic2 == AR5416_EEPROM_MAGIC) {
+                               size = sizeof(struct ar5416_eeprom_def);
+                               need_swap = true;
+                               eepdata = (u16 *) (&ah->eeprom);
+
+                               for (addr = 0; addr < size / sizeof(u16); addr++) {
+                                       temp = swab16(*eepdata);
+                                       *eepdata = temp;
+                                       eepdata++;
+                               }
+                       } else {
+                               ath_err(common,
+                                       "Invalid EEPROM Magic. Endianness mismatch.\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       ath_dbg(common, EEPROM, "need_swap = %s\n",
+               need_swap ? "True" : "False");
+
+       if (need_swap)
+               el = swab16(ah->eeprom.def.baseEepHeader.length);
+       else
+               el = ah->eeprom.def.baseEepHeader.length;
+
+       if (el > sizeof(struct ar5416_eeprom_def))
+               el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
+       else
+               el = el / sizeof(u16);
+
+       eepdata = (u16 *)(&ah->eeprom);
+
+       for (i = 0; i < el; i++)
+               sum ^= *eepdata++;
+
+       if (need_swap) {
+               u32 integer, j;
+               u16 word;
+
+               ath_dbg(common, EEPROM,
+                       "EEPROM Endianness is not native.. Changing.\n");
+
+               word = swab16(eep->baseEepHeader.length);
+               eep->baseEepHeader.length = word;
+
+               word = swab16(eep->baseEepHeader.checksum);
+               eep->baseEepHeader.checksum = word;
+
+               word = swab16(eep->baseEepHeader.version);
+               eep->baseEepHeader.version = word;
+
+               word = swab16(eep->baseEepHeader.regDmn[0]);
+               eep->baseEepHeader.regDmn[0] = word;
+
+               word = swab16(eep->baseEepHeader.regDmn[1]);
+               eep->baseEepHeader.regDmn[1] = word;
+
+               word = swab16(eep->baseEepHeader.rfSilent);
+               eep->baseEepHeader.rfSilent = word;
+
+               word = swab16(eep->baseEepHeader.blueToothOptions);
+               eep->baseEepHeader.blueToothOptions = word;
+
+               word = swab16(eep->baseEepHeader.deviceCap);
+               eep->baseEepHeader.deviceCap = word;
+
+               for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
+                       struct modal_eep_header *pModal =
+                               &eep->modalHeader[j];
+                       integer = swab32(pModal->antCtrlCommon);
+                       pModal->antCtrlCommon = integer;
+
+                       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+                               integer = swab32(pModal->antCtrlChain[i]);
+                               pModal->antCtrlChain[i] = integer;
+                       }
+                       for (i = 0; i < 3; i++) {
+                               word = swab16(pModal->xpaBiasLvlFreq[i]);
+                               pModal->xpaBiasLvlFreq[i] = word;
+                       }
+
+                       for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+                               word = swab16(pModal->spurChans[i].spurChan);
+                               pModal->spurChans[i].spurChan = word;
+                       }
+               }
+       }
+
+       if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
+           ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+               ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+                       sum, ah->eep_ops->get_eeprom_ver(ah));
+               return -EINVAL;
+       }
+
+       /* Enable fixup for AR_AN_TOP2 if necessary */
+       if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
+           ((eep->baseEepHeader.version & 0xff) > 0x0a) &&
+           (eep->baseEepHeader.pwdclkind == 0))
+               ah->need_an_top2_fixup = true;
+
+       if ((common->bus_ops->ath_bus_type == ATH_USB) &&
+           (AR_SREV_9280(ah)))
+               eep->modalHeader[0].xpaBiasLvl = 0;
+
+       return 0;
+}
+
+static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
+                                  enum eeprom_param param)
+{
+       struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+       struct modal_eep_header *pModal = eep->modalHeader;
+       struct base_eep_header *pBase = &eep->baseEepHeader;
+       int band = 0;
+
+       switch (param) {
+       case EEP_NFTHRESH_5:
+               return pModal[0].noiseFloorThreshCh[0];
+       case EEP_NFTHRESH_2:
+               return pModal[1].noiseFloorThreshCh[0];
+       case EEP_MAC_LSW:
+               return get_unaligned_be16(pBase->macAddr);
+       case EEP_MAC_MID:
+               return get_unaligned_be16(pBase->macAddr + 2);
+       case EEP_MAC_MSW:
+               return get_unaligned_be16(pBase->macAddr + 4);
+       case EEP_REG_0:
+               return pBase->regDmn[0];
+       case EEP_OP_CAP:
+               return pBase->deviceCap;
+       case EEP_OP_MODE:
+               return pBase->opCapFlags;
+       case EEP_RF_SILENT:
+               return pBase->rfSilent;
+       case EEP_OB_5:
+               return pModal[0].ob;
+       case EEP_DB_5:
+               return pModal[0].db;
+       case EEP_OB_2:
+               return pModal[1].ob;
+       case EEP_DB_2:
+               return pModal[1].db;
+       case EEP_MINOR_REV:
+               return AR5416_VER_MASK;
+       case EEP_TX_MASK:
+               return pBase->txMask;
+       case EEP_RX_MASK:
+               return pBase->rxMask;
+       case EEP_FSTCLK_5G:
+               return pBase->fastClk5g;
+       case EEP_RXGAIN_TYPE:
+               return pBase->rxGainType;
+       case EEP_TXGAIN_TYPE:
+               return pBase->txGainType;
+       case EEP_OL_PWRCTRL:
+               if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+                       return pBase->openLoopPwrCntl ? true : false;
+               else
+                       return false;
+       case EEP_RC_CHAIN_MASK:
+               if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+                       return pBase->rcChainMask;
+               else
+                       return 0;
+       case EEP_DAC_HPWR_5G:
+               if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
+                       return pBase->dacHiPwrMode_5G;
+               else
+                       return 0;
+       case EEP_FRAC_N_5G:
+               if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
+                       return pBase->frac_n_5g;
+               else
+                       return 0;
+       case EEP_PWR_TABLE_OFFSET:
+               if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_21)
+                       return pBase->pwr_table_offset;
+               else
+                       return AR5416_PWR_TABLE_OFFSET_DB;
+       case EEP_ANTENNA_GAIN_2G:
+               band = 1;
+               /* fall through */
+       case EEP_ANTENNA_GAIN_5G:
+               return max_t(u8, max_t(u8,
+                       pModal[band].antennaGainCh[0],
+                       pModal[band].antennaGainCh[1]),
+                       pModal[band].antennaGainCh[2]);
+       default:
+               return 0;
+       }
+}
+
+static void ath9k_hw_def_set_gain(struct ath_hw *ah,
+                                 struct modal_eep_header *pModal,
+                                 struct ar5416_eeprom_def *eep,
+                                 u8 txRxAttenLocal, int regChainOffset, int i)
+{
+       if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
+               txRxAttenLocal = pModal->txRxAttenCh[i];
+
+               if (AR_SREV_9280_20_OR_LATER(ah)) {
+                       REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+                             AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+                             pModal->bswMargin[i]);
+                       REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+                             AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+                             pModal->bswAtten[i]);
+                       REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+                             AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+                             pModal->xatten2Margin[i]);
+                       REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+                             AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+                             pModal->xatten2Db[i]);
+               } else {
+                       REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+                         (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+                          ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
+                         | SM(pModal-> bswMargin[i],
+                              AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+                       REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+                         (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+                          ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
+                         | SM(pModal->bswAtten[i],
+                              AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+               }
+       }
+
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               REG_RMW_FIELD(ah,
+                     AR_PHY_RXGAIN + regChainOffset,
+                     AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+               REG_RMW_FIELD(ah,
+                     AR_PHY_RXGAIN + regChainOffset,
+                     AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
+       } else {
+               REG_WRITE(ah,
+                         AR_PHY_RXGAIN + regChainOffset,
+                         (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
+                          ~AR_PHY_RXGAIN_TXRX_ATTEN)
+                         | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
+               REG_WRITE(ah,
+                         AR_PHY_GAIN_2GHZ + regChainOffset,
+                         (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+                          ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
+                         SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
+       }
+}
+
+static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
+                                         struct ath9k_channel *chan)
+{
+       struct modal_eep_header *pModal;
+       struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+       int i, regChainOffset;
+       u8 txRxAttenLocal;
+
+       pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+       txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
+
+       REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon & 0xffff);
+
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               if (AR_SREV_9280(ah)) {
+                       if (i >= 2)
+                               break;
+               }
+
+               if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
+                       regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+               else
+                       regChainOffset = i * 0x1000;
+
+               REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+                         pModal->antCtrlChain[i]);
+
+               REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+                         (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
+                          ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+                            AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+                         SM(pModal->iqCalICh[i],
+                            AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+                         SM(pModal->iqCalQCh[i],
+                            AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+               ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
+                                     regChainOffset, i);
+       }
+
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               if (IS_CHAN_2GHZ(chan)) {
+                       ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+                                                 AR_AN_RF2G1_CH0_OB,
+                                                 AR_AN_RF2G1_CH0_OB_S,
+                                                 pModal->ob);
+                       ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+                                                 AR_AN_RF2G1_CH0_DB,
+                                                 AR_AN_RF2G1_CH0_DB_S,
+                                                 pModal->db);
+                       ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+                                                 AR_AN_RF2G1_CH1_OB,
+                                                 AR_AN_RF2G1_CH1_OB_S,
+                                                 pModal->ob_ch1);
+                       ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+                                                 AR_AN_RF2G1_CH1_DB,
+                                                 AR_AN_RF2G1_CH1_DB_S,
+                                                 pModal->db_ch1);
+               } else {
+                       ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+                                                 AR_AN_RF5G1_CH0_OB5,
+                                                 AR_AN_RF5G1_CH0_OB5_S,
+                                                 pModal->ob);
+                       ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+                                                 AR_AN_RF5G1_CH0_DB5,
+                                                 AR_AN_RF5G1_CH0_DB5_S,
+                                                 pModal->db);
+                       ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+                                                 AR_AN_RF5G1_CH1_OB5,
+                                                 AR_AN_RF5G1_CH1_OB5_S,
+                                                 pModal->ob_ch1);
+                       ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+                                                 AR_AN_RF5G1_CH1_DB5,
+                                                 AR_AN_RF5G1_CH1_DB5_S,
+                                                 pModal->db_ch1);
+               }
+               ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+                                         AR_AN_TOP2_XPABIAS_LVL,
+                                         AR_AN_TOP2_XPABIAS_LVL_S,
+                                         pModal->xpaBiasLvl);
+               ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+                                         AR_AN_TOP2_LOCALBIAS,
+                                         AR_AN_TOP2_LOCALBIAS_S,
+                                         !!(pModal->lna_ctl &
+                                            LNA_CTL_LOCAL_BIAS));
+               REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
+                             !!(pModal->lna_ctl & LNA_CTL_FORCE_XPA));
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+                     pModal->switchSettling);
+       REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+                     pModal->adcDesiredSize);
+
+       if (!AR_SREV_9280_20_OR_LATER(ah))
+               REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+                             AR_PHY_DESIRED_SZ_PGA,
+                             pModal->pgaDesiredSize);
+
+       REG_WRITE(ah, AR_PHY_RF_CTL4,
+                 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+                 | SM(pModal->txEndToXpaOff,
+                      AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+                 | SM(pModal->txFrameToXpaOn,
+                      AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+                 | SM(pModal->txFrameToXpaOn,
+                      AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+       REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+                     pModal->txEndToRxOn);
+
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+                             pModal->thresh62);
+               REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
+                             AR_PHY_EXT_CCA0_THRESH62,
+                             pModal->thresh62);
+       } else {
+               REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
+                             pModal->thresh62);
+               REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+                             AR_PHY_EXT_CCA_THRESH62,
+                             pModal->thresh62);
+       }
+
+       if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
+               REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+                             AR_PHY_TX_END_DATA_START,
+                             pModal->txFrameToDataStart);
+               REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+                             pModal->txFrameToPaOn);
+       }
+
+       if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
+               if (IS_CHAN_HT40(chan))
+                       REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+                                     AR_PHY_SETTLING_SWITCH,
+                                     pModal->swSettleHt40);
+       }
+
+       if (AR_SREV_9280_20_OR_LATER(ah) &&
+           AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+               REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
+                             AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
+                             pModal->miscBits);
+
+
+       if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
+               if (IS_CHAN_2GHZ(chan))
+                       REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+                                       eep->baseEepHeader.dacLpMode);
+               else if (eep->baseEepHeader.dacHiPwrMode_5G)
+                       REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
+               else
+                       REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+                                     eep->baseEepHeader.dacLpMode);
+
+               udelay(100);
+
+               REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
+                             pModal->miscBits >> 2);
+
+               REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
+                             AR_PHY_TX_DESIRED_SCALE_CCK,
+                             eep->baseEepHeader.desiredScaleCCK);
+       }
+}
+
+static void ath9k_hw_def_set_addac(struct ath_hw *ah,
+                                  struct ath9k_channel *chan)
+{
+#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
+       struct modal_eep_header *pModal;
+       struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+       u8 biaslevel;
+
+       if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
+               return;
+
+       if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
+               return;
+
+       pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+       if (pModal->xpaBiasLvl != 0xff) {
+               biaslevel = pModal->xpaBiasLvl;
+       } else {
+               u16 resetFreqBin, freqBin, freqCount = 0;
+               struct chan_centers centers;
+
+               ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+               resetFreqBin = FREQ2FBIN(centers.synth_center,
+                                        IS_CHAN_2GHZ(chan));
+               freqBin = XPA_LVL_FREQ(0) & 0xff;
+               biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
+
+               freqCount++;
+
+               while (freqCount < 3) {
+                       if (XPA_LVL_FREQ(freqCount) == 0x0)
+                               break;
+
+                       freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
+                       if (resetFreqBin >= freqBin)
+                               biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
+                       else
+                               break;
+                       freqCount++;
+               }
+       }
+
+       if (IS_CHAN_2GHZ(chan)) {
+               INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
+                                       7, 1) & (~0x18)) | biaslevel << 3;
+       } else {
+               INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
+                                       6, 1) & (~0xc0)) | biaslevel << 6;
+       }
+#undef XPA_LVL_FREQ
+}
+
+static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah,
+                               u16 *gb,
+                               u16 numXpdGain,
+                               u16 pdGainOverlap_t2,
+                               int8_t pwr_table_offset,
+                               int16_t *diff)
+
+{
+       u16 k;
+
+       /* Prior to writing the boundaries or the pdadc vs. power table
+        * into the chip registers the default starting point on the pdadc
+        * vs. power table needs to be checked and the curve boundaries
+        * adjusted accordingly
+        */
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               u16 gb_limit;
+
+               if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {
+                       /* get the difference in dB */
+                       *diff = (u16)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB);
+                       /* get the number of half dB steps */
+                       *diff *= 2;
+                       /* change the original gain boundary settings
+                        * by the number of half dB steps
+                        */
+                       for (k = 0; k < numXpdGain; k++)
+                               gb[k] = (u16)(gb[k] - *diff);
+               }
+               /* Because of a hardware limitation, ensure the gain boundary
+                * is not larger than (63 - overlap)
+                */
+               gb_limit = (u16)(MAX_RATE_POWER - pdGainOverlap_t2);
+
+               for (k = 0; k < numXpdGain; k++)
+                       gb[k] = (u16)min(gb_limit, gb[k]);
+       }
+
+       return *diff;
+}
+
+static void ath9k_adjust_pdadc_values(struct ath_hw *ah,
+                                     int8_t pwr_table_offset,
+                                     int16_t diff,
+                                     u8 *pdadcValues)
+{
+#define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff)
+       u16 k;
+
+       /* If this is a board that has a pwrTableOffset that differs from
+        * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the
+        * pdadc vs pwr table needs to be adjusted prior to writing to the
+        * chip.
+        */
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {
+                       /* shift the table to start at the new offset */
+                       for (k = 0; k < (u16)NUM_PDADC(diff); k++ ) {
+                               pdadcValues[k] = pdadcValues[k + diff];
+                       }
+
+                       /* fill the back of the table */
+                       for (k = (u16)NUM_PDADC(diff); k < NUM_PDADC(0); k++) {
+                               pdadcValues[k] = pdadcValues[NUM_PDADC(diff)];
+                       }
+               }
+       }
+#undef NUM_PDADC
+}
+
+static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
+                                 struct ath9k_channel *chan)
+{
+#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
+#define SM_PDGAIN_B(x, y) \
+               SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+       struct cal_data_per_freq *pRawDataset;
+       u8 *pCalBChans = NULL;
+       u16 pdGainOverlap_t2;
+       static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+       u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+       u16 numPiers, i, j;
+       int16_t diff = 0;
+       u16 numXpdGain, xpdMask;
+       u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
+       u32 reg32, regOffset, regChainOffset;
+       int16_t modalIdx;
+       int8_t pwr_table_offset;
+
+       modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
+       xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
+
+       pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET);
+
+       if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+           AR5416_EEP_MINOR_VER_2) {
+               pdGainOverlap_t2 =
+                       pEepData->modalHeader[modalIdx].pdGainOverlap;
+       } else {
+               pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+                                           AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+       }
+
+       if (IS_CHAN_2GHZ(chan)) {
+               pCalBChans = pEepData->calFreqPier2G;
+               numPiers = AR5416_NUM_2G_CAL_PIERS;
+       } else {
+               pCalBChans = pEepData->calFreqPier5G;
+               numPiers = AR5416_NUM_5G_CAL_PIERS;
+       }
+
+       if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
+               pRawDataset = pEepData->calPierData2G[0];
+               ah->initPDADC = ((struct calDataPerFreqOpLoop *)
+                                pRawDataset)->vpdPdg[0][0];
+       }
+
+       numXpdGain = 0;
+
+       for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+               if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+                       if (numXpdGain >= AR5416_NUM_PD_GAINS)
+                               break;
+                       xpdGainValues[numXpdGain] =
+                               (u16)(AR5416_PD_GAINS_IN_MASK - i);
+                       numXpdGain++;
+               }
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+                     (numXpdGain - 1) & 0x3);
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+                     xpdGainValues[0]);
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+                     xpdGainValues[1]);
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+                     xpdGainValues[2]);
+
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               if ((ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+                   (i != 0)) {
+                       regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+               } else
+                       regChainOffset = i * 0x1000;
+
+               if (pEepData->baseEepHeader.txMask & (1 << i)) {
+                       if (IS_CHAN_2GHZ(chan))
+                               pRawDataset = pEepData->calPierData2G[i];
+                       else
+                               pRawDataset = pEepData->calPierData5G[i];
+
+
+                       if (OLC_FOR_AR9280_20_LATER) {
+                               u8 pcdacIdx;
+                               u8 txPower;
+
+                               ath9k_get_txgain_index(ah, chan,
+                               (struct calDataPerFreqOpLoop *)pRawDataset,
+                               pCalBChans, numPiers, &txPower, &pcdacIdx);
+                               ath9k_olc_get_pdadcs(ah, pcdacIdx,
+                                                    txPower/2, pdadcValues);
+                       } else {
+                               ath9k_hw_get_gain_boundaries_pdadcs(ah,
+                                                       chan, pRawDataset,
+                                                       pCalBChans, numPiers,
+                                                       pdGainOverlap_t2,
+                                                       gainBoundaries,
+                                                       pdadcValues,
+                                                       numXpdGain);
+                       }
+
+                       diff = ath9k_change_gain_boundary_setting(ah,
+                                                          gainBoundaries,
+                                                          numXpdGain,
+                                                          pdGainOverlap_t2,
+                                                          pwr_table_offset,
+                                                          &diff);
+
+                       ENABLE_REGWRITE_BUFFER(ah);
+
+                       if (OLC_FOR_AR9280_20_LATER) {
+                               REG_WRITE(ah,
+                                       AR_PHY_TPCRG5 + regChainOffset,
+                                       SM(0x6,
+                                       AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+                                       SM_PD_GAIN(1) | SM_PD_GAIN(2) |
+                                       SM_PD_GAIN(3) | SM_PD_GAIN(4));
+                       } else {
+                               REG_WRITE(ah,
+                                       AR_PHY_TPCRG5 + regChainOffset,
+                                       SM(pdGainOverlap_t2,
+                                       AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
+                                       SM_PDGAIN_B(0, 1) |
+                                       SM_PDGAIN_B(1, 2) |
+                                       SM_PDGAIN_B(2, 3) |
+                                       SM_PDGAIN_B(3, 4));
+                       }
+
+                       ath9k_adjust_pdadc_values(ah, pwr_table_offset,
+                                                 diff, pdadcValues);
+
+                       regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+                       for (j = 0; j < 32; j++) {
+                               reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
+                               REG_WRITE(ah, regOffset, reg32);
+
+                               ath_dbg(common, EEPROM,
+                                       "PDADC (%d,%4x): %4.4x %8.8x\n",
+                                       i, regChainOffset, regOffset,
+                                       reg32);
+                               ath_dbg(common, EEPROM,
+                                       "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n",
+                                       i, 4 * j, pdadcValues[4 * j],
+                                       4 * j + 1, pdadcValues[4 * j + 1],
+                                       4 * j + 2, pdadcValues[4 * j + 2],
+                                       4 * j + 3, pdadcValues[4 * j + 3]);
+
+                               regOffset += 4;
+                       }
+                       REGWRITE_BUFFER_FLUSH(ah);
+               }
+       }
+
+#undef SM_PD_GAIN
+#undef SM_PDGAIN_B
+}
+
+static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
+                                                 struct ath9k_channel *chan,
+                                                 int16_t *ratesArray,
+                                                 u16 cfgCtl,
+                                                 u16 antenna_reduction,
+                                                 u16 powerLimit)
+{
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN   9 /* 10*log10(3)*2 */
+
+       struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+       u16 twiceMaxEdgePower;
+       int i;
+       struct cal_ctl_data *rep;
+       struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+               0, { 0, 0, 0, 0}
+       };
+       struct cal_target_power_leg targetPowerOfdmExt = {
+               0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+               0, { 0, 0, 0, 0 }
+       };
+       struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+               0, {0, 0, 0, 0}
+       };
+       u16 scaledPower = 0, minCtlPower;
+       static const u16 ctlModesFor11a[] = {
+               CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+       };
+       static const u16 ctlModesFor11g[] = {
+               CTL_11B, CTL_11G, CTL_2GHT20,
+               CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+       };
+       u16 numCtlModes;
+       const u16 *pCtlMode;
+       u16 ctlMode, freq;
+       struct chan_centers centers;
+       int tx_chainmask;
+       u16 twiceMinEdgePower;
+
+       tx_chainmask = ah->txchainmask;
+
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+       scaledPower = powerLimit - antenna_reduction;
+
+       switch (ar5416_get_ntxchains(tx_chainmask)) {
+       case 1:
+               break;
+       case 2:
+               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               else
+                       scaledPower = 0;
+               break;
+       case 3:
+               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               else
+                       scaledPower = 0;
+               break;
+       }
+
+       if (IS_CHAN_2GHZ(chan)) {
+               numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
+                       SUB_NUM_CTL_MODES_AT_2G_40;
+               pCtlMode = ctlModesFor11g;
+
+               ath9k_hw_get_legacy_target_powers(ah, chan,
+                       pEepData->calTargetPowerCck,
+                       AR5416_NUM_2G_CCK_TARGET_POWERS,
+                       &targetPowerCck, 4, false);
+               ath9k_hw_get_legacy_target_powers(ah, chan,
+                       pEepData->calTargetPower2G,
+                       AR5416_NUM_2G_20_TARGET_POWERS,
+                       &targetPowerOfdm, 4, false);
+               ath9k_hw_get_target_powers(ah, chan,
+                       pEepData->calTargetPower2GHT20,
+                       AR5416_NUM_2G_20_TARGET_POWERS,
+                       &targetPowerHt20, 8, false);
+
+               if (IS_CHAN_HT40(chan)) {
+                       numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+                       ath9k_hw_get_target_powers(ah, chan,
+                               pEepData->calTargetPower2GHT40,
+                               AR5416_NUM_2G_40_TARGET_POWERS,
+                               &targetPowerHt40, 8, true);
+                       ath9k_hw_get_legacy_target_powers(ah, chan,
+                               pEepData->calTargetPowerCck,
+                               AR5416_NUM_2G_CCK_TARGET_POWERS,
+                               &targetPowerCckExt, 4, true);
+                       ath9k_hw_get_legacy_target_powers(ah, chan,
+                               pEepData->calTargetPower2G,
+                               AR5416_NUM_2G_20_TARGET_POWERS,
+                               &targetPowerOfdmExt, 4, true);
+               }
+       } else {
+               numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
+                       SUB_NUM_CTL_MODES_AT_5G_40;
+               pCtlMode = ctlModesFor11a;
+
+               ath9k_hw_get_legacy_target_powers(ah, chan,
+                       pEepData->calTargetPower5G,
+                       AR5416_NUM_5G_20_TARGET_POWERS,
+                       &targetPowerOfdm, 4, false);
+               ath9k_hw_get_target_powers(ah, chan,
+                       pEepData->calTargetPower5GHT20,
+                       AR5416_NUM_5G_20_TARGET_POWERS,
+                       &targetPowerHt20, 8, false);
+
+               if (IS_CHAN_HT40(chan)) {
+                       numCtlModes = ARRAY_SIZE(ctlModesFor11a);
+                       ath9k_hw_get_target_powers(ah, chan,
+                               pEepData->calTargetPower5GHT40,
+                               AR5416_NUM_5G_40_TARGET_POWERS,
+                               &targetPowerHt40, 8, true);
+                       ath9k_hw_get_legacy_target_powers(ah, chan,
+                               pEepData->calTargetPower5G,
+                               AR5416_NUM_5G_20_TARGET_POWERS,
+                               &targetPowerOfdmExt, 4, true);
+               }
+       }
+
+       for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+               bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+                       (pCtlMode[ctlMode] == CTL_2GHT40);
+               if (isHt40CtlMode)
+                       freq = centers.synth_center;
+               else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+                       freq = centers.ext_center;
+               else
+                       freq = centers.ctl_center;
+
+               twiceMaxEdgePower = MAX_RATE_POWER;
+
+               for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+                       if ((((cfgCtl & ~CTL_MODE_M) |
+                             (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+                            pEepData->ctlIndex[i]) ||
+                           (((cfgCtl & ~CTL_MODE_M) |
+                             (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+                            ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
+                               rep = &(pEepData->ctlData[i]);
+
+                               twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
+                               rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
+                               IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
+
+                               if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+                                       twiceMaxEdgePower = min(twiceMaxEdgePower,
+                                                               twiceMinEdgePower);
+                               } else {
+                                       twiceMaxEdgePower = twiceMinEdgePower;
+                                       break;
+                               }
+                       }
+               }
+
+               minCtlPower = min(twiceMaxEdgePower, scaledPower);
+
+               switch (pCtlMode[ctlMode]) {
+               case CTL_11B:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+                               targetPowerCck.tPow2x[i] =
+                                       min((u16)targetPowerCck.tPow2x[i],
+                                           minCtlPower);
+                       }
+                       break;
+               case CTL_11A:
+               case CTL_11G:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+                               targetPowerOfdm.tPow2x[i] =
+                                       min((u16)targetPowerOfdm.tPow2x[i],
+                                           minCtlPower);
+                       }
+                       break;
+               case CTL_5GHT20:
+               case CTL_2GHT20:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+                               targetPowerHt20.tPow2x[i] =
+                                       min((u16)targetPowerHt20.tPow2x[i],
+                                           minCtlPower);
+                       }
+                       break;
+               case CTL_11B_EXT:
+                       targetPowerCckExt.tPow2x[0] = min((u16)
+                                       targetPowerCckExt.tPow2x[0],
+                                       minCtlPower);
+                       break;
+               case CTL_11A_EXT:
+               case CTL_11G_EXT:
+                       targetPowerOfdmExt.tPow2x[0] = min((u16)
+                                       targetPowerOfdmExt.tPow2x[0],
+                                       minCtlPower);
+                       break;
+               case CTL_5GHT40:
+               case CTL_2GHT40:
+                       for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+                               targetPowerHt40.tPow2x[i] =
+                                       min((u16)targetPowerHt40.tPow2x[i],
+                                           minCtlPower);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
+               ratesArray[rate18mb] = ratesArray[rate24mb] =
+               targetPowerOfdm.tPow2x[0];
+       ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+       ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+       ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+       ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+       for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+               ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+       if (IS_CHAN_2GHZ(chan)) {
+               ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+               ratesArray[rate2s] = ratesArray[rate2l] =
+                       targetPowerCck.tPow2x[1];
+               ratesArray[rate5_5s] = ratesArray[rate5_5l] =
+                       targetPowerCck.tPow2x[2];
+               ratesArray[rate11s] = ratesArray[rate11l] =
+                       targetPowerCck.tPow2x[3];
+       }
+       if (IS_CHAN_HT40(chan)) {
+               for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+                       ratesArray[rateHt40_0 + i] =
+                               targetPowerHt40.tPow2x[i];
+               }
+               ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+               ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+               ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+               if (IS_CHAN_2GHZ(chan)) {
+                       ratesArray[rateExtCck] =
+                               targetPowerCckExt.tPow2x[0];
+               }
+       }
+}
+
+static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
+                                   struct ath9k_channel *chan,
+                                   u16 cfgCtl,
+                                   u8 twiceAntennaReduction,
+                                   u8 powerLimit, bool test)
+{
+#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
+       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+       struct modal_eep_header *pModal =
+               &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
+       int16_t ratesArray[Ar5416RateSize];
+       u8 ht40PowerIncForPdadc = 2;
+       int i, cck_ofdm_delta = 0;
+
+       memset(ratesArray, 0, sizeof(ratesArray));
+
+       if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+           AR5416_EEP_MINOR_VER_2) {
+               ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+       }
+
+       ath9k_hw_set_def_power_per_rate_table(ah, chan,
+                                              &ratesArray[0], cfgCtl,
+                                              twiceAntennaReduction,
+                                              powerLimit);
+
+       ath9k_hw_set_def_power_cal_table(ah, chan);
+
+       regulatory->max_power_level = 0;
+       for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+               if (ratesArray[i] > MAX_RATE_POWER)
+                       ratesArray[i] = MAX_RATE_POWER;
+               if (ratesArray[i] > regulatory->max_power_level)
+                       regulatory->max_power_level = ratesArray[i];
+       }
+
+       switch(ar5416_get_ntxchains(ah->txchainmask)) {
+       case 1:
+               break;
+       case 2:
+               regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+               break;
+       case 3:
+               regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+               break;
+       default:
+               ath_dbg(ath9k_hw_common(ah), EEPROM,
+                       "Invalid chainmask configuration\n");
+               break;
+       }
+
+       if (test)
+               return;
+
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               for (i = 0; i < Ar5416RateSize; i++) {
+                       int8_t pwr_table_offset;
+
+                       pwr_table_offset = ah->eep_ops->get_eeprom(ah,
+                                                       EEP_PWR_TABLE_OFFSET);
+                       ratesArray[i] -= pwr_table_offset * 2;
+               }
+       }
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+                 ATH9K_POW_SM(ratesArray[rate18mb], 24)
+                 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+                 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+                 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+                 ATH9K_POW_SM(ratesArray[rate54mb], 24)
+                 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+                 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+                 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+       if (IS_CHAN_2GHZ(chan)) {
+               if (OLC_FOR_AR9280_20_LATER) {
+                       cck_ofdm_delta = 2;
+                       REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+                               ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
+                               | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
+                               | ATH9K_POW_SM(ratesArray[rateXr], 8)
+                               | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
+                       REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+                               ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
+                               | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
+                               | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
+                               | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
+               } else {
+                       REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+                               ATH9K_POW_SM(ratesArray[rate2s], 24)
+                               | ATH9K_POW_SM(ratesArray[rate2l], 16)
+                               | ATH9K_POW_SM(ratesArray[rateXr], 8)
+                               | ATH9K_POW_SM(ratesArray[rate1l], 0));
+                       REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+                               ATH9K_POW_SM(ratesArray[rate11s], 24)
+                               | ATH9K_POW_SM(ratesArray[rate11l], 16)
+                               | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+                               | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+               }
+       }
+
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+                 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+       REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+                 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+                 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+       if (IS_CHAN_HT40(chan)) {
+               REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+                         ATH9K_POW_SM(ratesArray[rateHt40_3] +
+                                      ht40PowerIncForPdadc, 24)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+                                        ht40PowerIncForPdadc, 16)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+                                        ht40PowerIncForPdadc, 8)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+                                        ht40PowerIncForPdadc, 0));
+               REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+                         ATH9K_POW_SM(ratesArray[rateHt40_7] +
+                                      ht40PowerIncForPdadc, 24)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+                                        ht40PowerIncForPdadc, 16)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+                                        ht40PowerIncForPdadc, 8)
+                         | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+                                        ht40PowerIncForPdadc, 0));
+               if (OLC_FOR_AR9280_20_LATER) {
+                       REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+                               ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+                               | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
+                               | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+                               | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
+               } else {
+                       REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+                               ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+                               | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+                               | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+                               | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+               }
+       }
+
+       REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
+                 ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
+                 | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
+{
+#define EEP_DEF_SPURCHAN \
+       (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       u16 spur_val = AR_NO_SPUR;
+
+       ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
+               i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+       switch (ah->config.spurmode) {
+       case SPUR_DISABLE:
+               break;
+       case SPUR_ENABLE_IOCTL:
+               spur_val = ah->config.spurchans[i][is2GHz];
+               ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+                       spur_val);
+               break;
+       case SPUR_ENABLE_EEPROM:
+               spur_val = EEP_DEF_SPURCHAN;
+               break;
+       }
+
+       return spur_val;
+
+#undef EEP_DEF_SPURCHAN
+}
+
+const struct eeprom_ops eep_def_ops = {
+       .check_eeprom           = ath9k_hw_def_check_eeprom,
+       .get_eeprom             = ath9k_hw_def_get_eeprom,
+       .fill_eeprom            = ath9k_hw_def_fill_eeprom,
+       .dump_eeprom            = ath9k_hw_def_dump_eeprom,
+       .get_eeprom_ver         = ath9k_hw_def_get_eeprom_ver,
+       .get_eeprom_rev         = ath9k_hw_def_get_eeprom_rev,
+       .set_board_values       = ath9k_hw_def_set_board_values,
+       .set_addac              = ath9k_hw_def_set_addac,
+       .set_txpower            = ath9k_hw_def_set_txpower,
+       .get_spur_channel       = ath9k_hw_def_get_spur_channel
+};
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/gpio.c b/drivers/net/wireless/ath/ath9k_btcoex/gpio.c
new file mode 100644 (file)
index 0000000..1d2906f
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+/********************************/
+/*      LED functions          */
+/********************************/
+
+#ifdef CONFIG_MAC80211_LEDS
+static void ath_led_brightness(struct led_classdev *led_cdev,
+                              enum led_brightness brightness)
+{
+       struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
+       ath9k_btcoex_ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF));
+}
+
+void ath_deinit_leds(struct ath_softc *sc)
+{
+       if (!sc->led_registered)
+               return;
+
+       ath_led_brightness(&sc->led_cdev, LED_OFF);
+       led_classdev_unregister(&sc->led_cdev);
+}
+
+void ath_init_leds(struct ath_softc *sc)
+{
+       int ret;
+
+       if (sc->sc_ah->led_pin < 0) {
+               if (AR_SREV_9287(sc->sc_ah))
+                       sc->sc_ah->led_pin = ATH_LED_PIN_9287;
+               else if (AR_SREV_9485(sc->sc_ah))
+                       sc->sc_ah->led_pin = ATH_LED_PIN_9485;
+               else if (AR_SREV_9300(sc->sc_ah))
+                       sc->sc_ah->led_pin = ATH_LED_PIN_9300;
+               else if (AR_SREV_9462(sc->sc_ah))
+                       sc->sc_ah->led_pin = ATH_LED_PIN_9462;
+               else
+                       sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
+       }
+
+       /* Configure gpio 1 for output */
+       ath9k_btcoex_ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
+                           AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+       /* LED off, active low */
+       ath9k_btcoex_ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
+
+       if (!led_blink)
+               sc->led_cdev.default_trigger =
+                       ieee80211_get_radio_led_name(sc->hw);
+
+       snprintf(sc->led_name, sizeof(sc->led_name),
+               "ath9k-%s", wiphy_name(sc->hw->wiphy));
+       sc->led_cdev.name = sc->led_name;
+       sc->led_cdev.brightness_set = ath_led_brightness;
+
+       ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
+       if (ret < 0)
+               return;
+
+       sc->led_registered = true;
+}
+#endif
+
+/*******************/
+/*     Rfkill     */
+/*******************/
+
+static bool ath_is_rfkill_set(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       bool is_blocked;
+
+       ath9k_ps_wakeup(sc);
+       is_blocked = ath9k_btcoex_ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
+                                 ah->rfkill_polarity;
+       ath9k_ps_restore(sc);
+
+       return is_blocked;
+}
+
+void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
+{
+       struct ath_softc *sc = hw->priv;
+       bool blocked = !!ath_is_rfkill_set(sc);
+
+       wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
+}
+
+void ath_start_rfkill_poll(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+               wiphy_rfkill_start_polling(sc->hw->wiphy);
+}
+
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+
+/******************/
+/*     BTCOEX     */
+/******************/
+
+/*
+ * Detects if there is any priority bt traffic
+ */
+static void ath_detect_bt_priority(struct ath_softc *sc)
+{
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_hw *ah = sc->sc_ah;
+
+       if (ath9k_btcoex_ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio))
+               btcoex->bt_priority_cnt++;
+
+       if (time_after(jiffies, btcoex->bt_priority_time +
+                       msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
+               clear_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
+               clear_bit(BT_OP_SCAN, &btcoex->op_flags);
+               /* Detect if colocated bt started scanning */
+               if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
+                       ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX,
+                               "BT scan detected\n");
+                       set_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
+                       set_bit(BT_OP_SCAN, &btcoex->op_flags);
+               } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
+                       ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX,
+                               "BT priority traffic detected\n");
+                       set_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
+               }
+
+               btcoex->bt_priority_cnt = 0;
+               btcoex->bt_priority_time = jiffies;
+       }
+}
+
+static void ath9k_gen_timer_start(struct ath_hw *ah,
+                                 struct ath_gen_timer *timer,
+                                 u32 trig_timeout,
+                                 u32 timer_period)
+{
+       ath9k_btcoex_ath9k_hw_gen_timer_start(ah, timer, trig_timeout, timer_period);
+
+       if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
+               ath9k_btcoex_ath9k_hw_disable_interrupts(ah);
+               ah->imask |= ATH9K_INT_GENTIMER;
+               ath9k_btcoex_ath9k_hw_set_interrupts(ah);
+               ath9k_btcoex_ath9k_hw_enable_interrupts(ah);
+       }
+}
+
+static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
+{
+       struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+
+       ath9k_btcoex_ath9k_hw_gen_timer_stop(ah, timer);
+
+       /* if no timer is enabled, turn off interrupt mask */
+       if (timer_table->timer_mask.val == 0) {
+               ath9k_btcoex_ath9k_hw_disable_interrupts(ah);
+               ah->imask &= ~ATH9K_INT_GENTIMER;
+               ath9k_btcoex_ath9k_hw_set_interrupts(ah);
+               ath9k_btcoex_ath9k_hw_enable_interrupts(ah);
+       }
+}
+
+/*
+ * This is the master bt coex timer which runs for every
+ * 45ms, bt traffic will be given priority during 55% of this
+ * period while wlan gets remaining 45%
+ */
+static void ath_btcoex_period_timer(unsigned long data)
+{
+       struct ath_softc *sc = (struct ath_softc *) data;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_mci_profile *mci = &btcoex->mci;
+       u32 timer_period;
+       bool is_btscan;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+       if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
+               spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+               goto skip_hw_wakeup;
+       }
+       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+
+       ath9k_ps_wakeup(sc);
+       if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
+               ath_detect_bt_priority(sc);
+       is_btscan = test_bit(BT_OP_SCAN, &btcoex->op_flags);
+
+       btcoex->bt_wait_time += btcoex->btcoex_period;
+       if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
+               if (ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
+                   (mci->num_pan || mci->num_other_acl))
+                       ah->btcoex_hw.mci.stomp_ftp =
+                               (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
+               else
+                       ah->btcoex_hw.mci.stomp_ftp = false;
+               btcoex->bt_wait_time = 0;
+               sc->rx.num_pkts = 0;
+       }
+
+       spin_lock_bh(&btcoex->btcoex_lock);
+
+       ath9k_btcoex_ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
+                             btcoex->bt_stomp_type);
+
+       ath9k_btcoex_ath9k_hw_btcoex_enable(ah);
+       spin_unlock_bh(&btcoex->btcoex_lock);
+
+       if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) {
+               if (btcoex->hw_timer_enabled)
+                       ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
+
+               timer_period = is_btscan ? btcoex->btscan_no_stomp :
+                                          btcoex->btcoex_no_stomp;
+               ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
+                                     timer_period * 10);
+               btcoex->hw_timer_enabled = true;
+       }
+
+       ath9k_ps_restore(sc);
+skip_hw_wakeup:
+       timer_period = btcoex->btcoex_period;
+       mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
+}
+
+/*
+ * Generic tsf based hw timer which configures weight
+ * registers to time slice between wlan and bt traffic
+ */
+static void ath_btcoex_no_stomp_timer(void *arg)
+{
+       struct ath_softc *sc = (struct ath_softc *)arg;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       ath_dbg(common, BTCOEX, "no stomp timer running\n");
+
+       ath9k_ps_wakeup(sc);
+       spin_lock_bh(&btcoex->btcoex_lock);
+
+       if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
+           test_bit(BT_OP_SCAN, &btcoex->op_flags))
+               ath9k_btcoex_ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
+        else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
+               ath9k_btcoex_ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
+
+       ath9k_btcoex_ath9k_hw_btcoex_enable(ah);
+       spin_unlock_bh(&btcoex->btcoex_lock);
+       ath9k_ps_restore(sc);
+}
+
+static int ath_init_btcoex_timer(struct ath_softc *sc)
+{
+       struct ath_btcoex *btcoex = &sc->btcoex;
+
+       btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
+       btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 1000 *
+               btcoex->btcoex_period / 100;
+       btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * 1000 *
+                                  btcoex->btcoex_period / 100;
+
+       setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
+                       (unsigned long) sc);
+
+       spin_lock_init(&btcoex->btcoex_lock);
+
+       btcoex->no_stomp_timer = ath9k_btcoex_ath_gen_timer_alloc(sc->sc_ah,
+                       ath_btcoex_no_stomp_timer,
+                       ath_btcoex_no_stomp_timer,
+                       (void *) sc, AR_FIRST_NDP_TIMER);
+
+       if (!btcoex->no_stomp_timer)
+               return -ENOMEM;
+
+       return 0;
+}
+
+/*
+ * (Re)start btcoex timers
+ */
+void ath9k_btcoex_timer_resume(struct ath_softc *sc)
+{
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_hw *ah = sc->sc_ah;
+
+       ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n");
+
+       /* make sure duty cycle timer is also stopped when resuming */
+       if (btcoex->hw_timer_enabled)
+               ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+
+       btcoex->bt_priority_cnt = 0;
+       btcoex->bt_priority_time = jiffies;
+       clear_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
+       clear_bit(BT_OP_SCAN, &btcoex->op_flags);
+
+       mod_timer(&btcoex->period_timer, jiffies);
+}
+
+
+/*
+ * Pause btcoex timer and bt duty cycle timer
+ */
+void ath9k_btcoex_timer_pause(struct ath_softc *sc)
+{
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_hw *ah = sc->sc_ah;
+
+       del_timer_sync(&btcoex->period_timer);
+
+       if (btcoex->hw_timer_enabled)
+               ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
+
+       btcoex->hw_timer_enabled = false;
+}
+
+void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
+{
+       struct ath_btcoex *btcoex = &sc->btcoex;
+
+       ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+}
+
+u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
+{
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_mci_profile *mci = &sc->btcoex.mci;
+       u16 aggr_limit = 0;
+
+       if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && mci->aggr_limit)
+               aggr_limit = (max_4ms_framelen * mci->aggr_limit) >> 4;
+       else if (test_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags))
+               aggr_limit = min((max_4ms_framelen * 3) / 8,
+                                (u32)ATH_AMPDU_LIMIT_MAX);
+
+       return aggr_limit;
+}
+
+void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status)
+{
+       struct ath_hw *ah = sc->sc_ah;
+
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
+               if (status & ATH9K_INT_GENTIMER)
+                       ath9k_btcoex_ath_gen_timer_isr(sc->sc_ah);
+
+       if (status & ATH9K_INT_MCI)
+               ath_mci_intr(sc);
+}
+
+void ath9k_start_btcoex(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+
+       if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
+           !ah->btcoex_hw.enabled) {
+               if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
+                       ath9k_btcoex_ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+                                                  AR_STOMP_LOW_WLAN_WGHT);
+               ath9k_btcoex_ath9k_hw_btcoex_enable(ah);
+
+               if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
+                       ath9k_btcoex_timer_resume(sc);
+       }
+}
+
+void ath9k_stop_btcoex(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+
+       if (ah->btcoex_hw.enabled &&
+           ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
+               if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
+                       ath9k_btcoex_timer_pause(sc);
+               ath9k_btcoex_ath9k_hw_btcoex_disable(ah);
+               if (AR_SREV_9462(ah))
+                       ath_mci_flush_profile(&sc->btcoex.mci);
+       }
+}
+
+void ath9k_deinit_btcoex(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+
+        if ((sc->btcoex.no_stomp_timer) &&
+           ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE)
+               ath9k_btcoex_ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
+
+       if (ath9k_hw_mci_is_enabled(ah))
+               ath_mci_cleanup(sc);
+}
+
+int ath9k_init_btcoex(struct ath_softc *sc)
+{
+       struct ath_txq *txq;
+       struct ath_hw *ah = sc->sc_ah;
+       int r;
+
+       ath9k_btcoex_ath9k_hw_btcoex_init_scheme(ah);
+
+       switch (ath9k_hw_get_btcoex_scheme(sc->sc_ah)) {
+       case ATH_BTCOEX_CFG_NONE:
+               break;
+       case ATH_BTCOEX_CFG_2WIRE:
+               ath9k_btcoex_ath9k_hw_btcoex_init_2wire(sc->sc_ah);
+               break;
+       case ATH_BTCOEX_CFG_3WIRE:
+               ath9k_btcoex_ath9k_hw_btcoex_init_3wire(sc->sc_ah);
+               r = ath_init_btcoex_timer(sc);
+               if (r)
+                       return -1;
+               txq = sc->tx.txq_map[WME_AC_BE];
+               ath9k_btcoex_ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
+               sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
+               if (ath9k_hw_mci_is_enabled(ah)) {
+                       sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
+                       INIT_LIST_HEAD(&sc->btcoex.mci.info);
+
+                       r = ath_mci_setup(sc);
+                       if (r)
+                               return r;
+
+                       ath9k_btcoex_ath9k_hw_btcoex_init_mci(ah);
+               }
+
+               break;
+       default:
+               WARN_ON(1);
+               break;
+       }
+
+       return 0;
+}
+
+#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/hw-ops.h b/drivers/net/wireless/ath/ath9k_btcoex/hw-ops.h
new file mode 100644 (file)
index 0000000..265bf77
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH9K_HW_OPS_H
+#define ATH9K_HW_OPS_H
+
+#include "hw.h"
+
+/* Hardware core and driver accessible callbacks */
+
+static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah,
+                                              bool power_off)
+{
+       if (!ah->aspm_enabled)
+               return;
+
+       ath9k_hw_ops(ah)->config_pci_powersave(ah, power_off);
+}
+
+static inline void ath9k_hw_rxena(struct ath_hw *ah)
+{
+       ath9k_hw_ops(ah)->rx_enable(ah);
+}
+
+static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds,
+                                         u32 link)
+{
+       ath9k_hw_ops(ah)->set_desc_link(ds, link);
+}
+
+static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
+                                     struct ath9k_channel *chan,
+                                     u8 rxchainmask,
+                                     bool longcal)
+{
+       return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
+}
+
+static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
+{
+       return ath9k_hw_ops(ah)->get_isr(ah, masked);
+}
+
+static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds,
+                                      struct ath_tx_info *i)
+{
+       return ath9k_hw_ops(ah)->set_txdesc(ah, ds, i);
+}
+
+static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
+                                     struct ath_tx_status *ts)
+{
+       return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
+}
+
+static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+               struct ath_hw_antcomb_conf *antconf)
+{
+       ath9k_hw_ops(ah)->antdiv_comb_conf_get(ah, antconf);
+}
+
+static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah,
+               struct ath_hw_antcomb_conf *antconf)
+{
+       ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf);
+}
+
+/* Private hardware call ops */
+
+/* PHY ops */
+
+static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah,
+                                      struct ath9k_channel *chan)
+{
+       return ath9k_hw_private_ops(ah)->rf_set_freq(ah, chan);
+}
+
+static inline void ath9k_hw_spur_mitigate_freq(struct ath_hw *ah,
+                                              struct ath9k_channel *chan)
+{
+       ath9k_hw_private_ops(ah)->spur_mitigate_freq(ah, chan);
+}
+
+static inline int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah)
+{
+       if (!ath9k_hw_private_ops(ah)->rf_alloc_ext_banks)
+               return 0;
+
+       return ath9k_hw_private_ops(ah)->rf_alloc_ext_banks(ah);
+}
+
+static inline void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah)
+{
+       if (!ath9k_hw_private_ops(ah)->rf_free_ext_banks)
+               return;
+
+       ath9k_hw_private_ops(ah)->rf_free_ext_banks(ah);
+}
+
+static inline bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
+                                       struct ath9k_channel *chan,
+                                       u16 modesIndex)
+{
+       if (!ath9k_hw_private_ops(ah)->set_rf_regs)
+               return true;
+
+       return ath9k_hw_private_ops(ah)->set_rf_regs(ah, chan, modesIndex);
+}
+
+static inline void ath9k_hw_init_bb(struct ath_hw *ah,
+                                   struct ath9k_channel *chan)
+{
+       return ath9k_hw_private_ops(ah)->init_bb(ah, chan);
+}
+
+static inline void ath9k_hw_set_channel_regs(struct ath_hw *ah,
+                                            struct ath9k_channel *chan)
+{
+       return ath9k_hw_private_ops(ah)->set_channel_regs(ah, chan);
+}
+
+static inline int ath9k_hw_process_ini(struct ath_hw *ah,
+                                       struct ath9k_channel *chan)
+{
+       return ath9k_hw_private_ops(ah)->process_ini(ah, chan);
+}
+
+static inline void ath9k_olc_init(struct ath_hw *ah)
+{
+       if (!ath9k_hw_private_ops(ah)->olc_init)
+               return;
+
+       return ath9k_hw_private_ops(ah)->olc_init(ah);
+}
+
+static inline void ath9k_hw_set_rfmode(struct ath_hw *ah,
+                                      struct ath9k_channel *chan)
+{
+       return ath9k_hw_private_ops(ah)->set_rfmode(ah, chan);
+}
+
+static inline void ath9k_hw_mark_phy_inactive(struct ath_hw *ah)
+{
+       return ath9k_hw_private_ops(ah)->mark_phy_inactive(ah);
+}
+
+static inline void ath9k_hw_set_delta_slope(struct ath_hw *ah,
+                                           struct ath9k_channel *chan)
+{
+       return ath9k_hw_private_ops(ah)->set_delta_slope(ah, chan);
+}
+
+static inline bool ath9k_hw_rfbus_req(struct ath_hw *ah)
+{
+       return ath9k_hw_private_ops(ah)->rfbus_req(ah);
+}
+
+static inline void ath9k_hw_rfbus_done(struct ath_hw *ah)
+{
+       return ath9k_hw_private_ops(ah)->rfbus_done(ah);
+}
+
+static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah)
+{
+       if (!ath9k_hw_private_ops(ah)->restore_chainmask)
+               return;
+
+       return ath9k_hw_private_ops(ah)->restore_chainmask(ah);
+}
+
+static inline bool ath9k_hw_ani_control(struct ath_hw *ah,
+                                       enum ath9k_ani_cmd cmd, int param)
+{
+       return ath9k_hw_private_ops(ah)->ani_control(ah, cmd, param);
+}
+
+static inline void ath9k_hw_do_getnf(struct ath_hw *ah,
+                                    int16_t nfarray[NUM_NF_READINGS])
+{
+       ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray);
+}
+
+static inline bool ath9k_hw_init_cal(struct ath_hw *ah,
+                                    struct ath9k_channel *chan)
+{
+       return ath9k_hw_private_ops(ah)->init_cal(ah, chan);
+}
+
+static inline void ath9k_hw_setup_calibration(struct ath_hw *ah,
+                                             struct ath9k_cal_list *currCal)
+{
+       ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
+}
+
+static inline int ath9k_hw_fast_chan_change(struct ath_hw *ah,
+                                           struct ath9k_channel *chan,
+                                           u8 *ini_reloaded)
+{
+       return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan,
+                                                         ini_reloaded);
+}
+
+static inline void ath9k_hw_set_radar_params(struct ath_hw *ah)
+{
+       if (!ath9k_hw_private_ops(ah)->set_radar_params)
+               return;
+
+       ath9k_hw_private_ops(ah)->set_radar_params(ah, &ah->radar_conf);
+}
+
+#endif /* ATH9K_HW_OPS_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/hw.c b/drivers/net/wireless/ath/ath9k_btcoex/hw.c
new file mode 100644 (file)
index 0000000..ff7da08
--- /dev/null
@@ -0,0 +1,3122 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "rc.h"
+#include "ar9003_mac.h"
+#include "ar9003_mci.h"
+
+static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
+
+MODULE_AUTHOR("Atheros Communications");
+MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
+MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static int __init ath9k_init(void)
+{
+       return 0;
+}
+module_init(ath9k_init);
+
+static void __exit ath9k_exit(void)
+{
+       return;
+}
+module_exit(ath9k_exit);
+
+/* Private hardware callbacks */
+
+static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
+{
+       ath9k_hw_private_ops(ah)->init_cal_settings(ah);
+}
+
+static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
+{
+       ath9k_hw_private_ops(ah)->init_mode_regs(ah);
+}
+
+static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah,
+                                       struct ath9k_channel *chan)
+{
+       return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan);
+}
+
+static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
+{
+       if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs)
+               return;
+
+       ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah);
+}
+
+static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah)
+{
+       /* You will not have this callback if using the old ANI */
+       if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs)
+               return;
+
+       ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah);
+}
+
+/********************/
+/* Helper Functions */
+/********************/
+
+static void ath9k_hw_set_clockrate(struct ath_hw *ah)
+{
+       struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+       struct ath_common *common = ath9k_hw_common(ah);
+       unsigned int clockrate;
+
+       /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */
+       if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah))
+               clockrate = 117;
+       else if (!ah->curchan) /* should really check for CCK instead */
+               clockrate = ATH9K_CLOCK_RATE_CCK;
+       else if (conf->channel->band == IEEE80211_BAND_2GHZ)
+               clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
+       else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
+               clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
+       else
+               clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
+
+       if (conf_is_ht40(conf))
+               clockrate *= 2;
+
+       if (ah->curchan) {
+               if (IS_CHAN_HALF_RATE(ah->curchan))
+                       clockrate /= 2;
+               if (IS_CHAN_QUARTER_RATE(ah->curchan))
+                       clockrate /= 4;
+       }
+
+       common->clockrate = clockrate;
+}
+
+static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       return usecs * common->clockrate;
+}
+
+bool ath9k_btcoex_ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
+{
+       int i;
+
+       BUG_ON(timeout < AH_TIME_QUANTUM);
+
+       for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) {
+               if ((REG_READ(ah, reg) & mask) == val)
+                       return true;
+
+               udelay(AH_TIME_QUANTUM);
+       }
+
+       ath_dbg(ath9k_hw_common(ah), ANY,
+               "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
+               timeout, reg, REG_READ(ah, reg), mask, val);
+
+       return false;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_wait);
+
+void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
+                         int column, unsigned int *writecnt)
+{
+       int r;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+       for (r = 0; r < array->ia_rows; r++) {
+               REG_WRITE(ah, INI_RA(array, r, 0),
+                         INI_RA(array, r, column));
+               DO_DELAY(*writecnt);
+       }
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+u32 ath9k_hw_reverse_bits(u32 val, u32 n)
+{
+       u32 retval;
+       int i;
+
+       for (i = 0, retval = 0; i < n; i++) {
+               retval = (retval << 1) | (val & 1);
+               val >>= 1;
+       }
+       return retval;
+}
+
+u16 ath9k_btcoex_ath9k_hw_computetxtime(struct ath_hw *ah,
+                          u8 phy, int kbps,
+                          u32 frameLen, u16 rateix,
+                          bool shortPreamble)
+{
+       u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
+
+       if (kbps == 0)
+               return 0;
+
+       switch (phy) {
+       case WLAN_RC_PHY_CCK:
+               phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
+               if (shortPreamble)
+                       phyTime >>= 1;
+               numBits = frameLen << 3;
+               txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
+               break;
+       case WLAN_RC_PHY_OFDM:
+               if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) {
+                       bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
+                       numBits = OFDM_PLCP_BITS + (frameLen << 3);
+                       numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+                       txTime = OFDM_SIFS_TIME_QUARTER
+                               + OFDM_PREAMBLE_TIME_QUARTER
+                               + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
+               } else if (ah->curchan &&
+                          IS_CHAN_HALF_RATE(ah->curchan)) {
+                       bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
+                       numBits = OFDM_PLCP_BITS + (frameLen << 3);
+                       numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+                       txTime = OFDM_SIFS_TIME_HALF +
+                               OFDM_PREAMBLE_TIME_HALF
+                               + (numSymbols * OFDM_SYMBOL_TIME_HALF);
+               } else {
+                       bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
+                       numBits = OFDM_PLCP_BITS + (frameLen << 3);
+                       numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+                       txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
+                               + (numSymbols * OFDM_SYMBOL_TIME);
+               }
+               break;
+       default:
+               ath_err(ath9k_hw_common(ah),
+                       "Unknown phy %u (rate ix %u)\n", phy, rateix);
+               txTime = 0;
+               break;
+       }
+
+       return txTime;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_computetxtime);
+
+void ath9k_hw_get_channel_centers(struct ath_hw *ah,
+                                 struct ath9k_channel *chan,
+                                 struct chan_centers *centers)
+{
+       int8_t extoff;
+
+       if (!IS_CHAN_HT40(chan)) {
+               centers->ctl_center = centers->ext_center =
+                       centers->synth_center = chan->channel;
+               return;
+       }
+
+       if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+           (chan->chanmode == CHANNEL_G_HT40PLUS)) {
+               centers->synth_center =
+                       chan->channel + HT40_CHANNEL_CENTER_SHIFT;
+               extoff = 1;
+       } else {
+               centers->synth_center =
+                       chan->channel - HT40_CHANNEL_CENTER_SHIFT;
+               extoff = -1;
+       }
+
+       centers->ctl_center =
+               centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT);
+       /* 25 MHz spacing is supported by hw but not on upper layers */
+       centers->ext_center =
+               centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
+}
+
+/******************/
+/* Chip Revisions */
+/******************/
+
+static void ath9k_hw_read_revisions(struct ath_hw *ah)
+{
+       u32 val;
+
+       switch (ah->hw_version.devid) {
+       case AR5416_AR9100_DEVID:
+               ah->hw_version.macVersion = AR_SREV_VERSION_9100;
+               break;
+       case AR9300_DEVID_AR9330:
+               ah->hw_version.macVersion = AR_SREV_VERSION_9330;
+               if (ah->get_mac_revision) {
+                       ah->hw_version.macRev = ah->get_mac_revision();
+               } else {
+                       val = REG_READ(ah, AR_SREV);
+                       ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+               }
+               return;
+       case AR9300_DEVID_AR9340:
+               ah->hw_version.macVersion = AR_SREV_VERSION_9340;
+               val = REG_READ(ah, AR_SREV);
+               ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+               return;
+       }
+
+       val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
+
+       if (val == 0xFF) {
+               val = REG_READ(ah, AR_SREV);
+               ah->hw_version.macVersion =
+                       (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
+               ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+
+               if (AR_SREV_9462(ah))
+                       ah->is_pciexpress = true;
+               else
+                       ah->is_pciexpress = (val &
+                                            AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
+       } else {
+               if (!AR_SREV_9100(ah))
+                       ah->hw_version.macVersion = MS(val, AR_SREV_VERSION);
+
+               ah->hw_version.macRev = val & AR_SREV_REVISION;
+
+               if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)
+                       ah->is_pciexpress = true;
+       }
+}
+
+/************************************/
+/* HW Attach, Detach, Init Routines */
+/************************************/
+
+static void ath9k_hw_disablepcie(struct ath_hw *ah)
+{
+       if (!AR_SREV_5416(ah))
+               return;
+
+       REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+       REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+       REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
+       REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
+       REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
+       REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
+       REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+       REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+       REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
+
+       REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+}
+
+/* This should work for all families including legacy */
+static bool ath9k_hw_chip_test(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 regAddr[2] = { AR_STA_ID0 };
+       u32 regHold[2];
+       static const u32 patternData[4] = {
+               0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999
+       };
+       int i, j, loop_max;
+
+       if (!AR_SREV_9300_20_OR_LATER(ah)) {
+               loop_max = 2;
+               regAddr[1] = AR_PHY_BASE + (8 << 2);
+       } else
+               loop_max = 1;
+
+       for (i = 0; i < loop_max; i++) {
+               u32 addr = regAddr[i];
+               u32 wrData, rdData;
+
+               regHold[i] = REG_READ(ah, addr);
+               for (j = 0; j < 0x100; j++) {
+                       wrData = (j << 16) | j;
+                       REG_WRITE(ah, addr, wrData);
+                       rdData = REG_READ(ah, addr);
+                       if (rdData != wrData) {
+                               ath_err(common,
+                                       "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+                                       addr, wrData, rdData);
+                               return false;
+                       }
+               }
+               for (j = 0; j < 4; j++) {
+                       wrData = patternData[j];
+                       REG_WRITE(ah, addr, wrData);
+                       rdData = REG_READ(ah, addr);
+                       if (wrData != rdData) {
+                               ath_err(common,
+                                       "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+                                       addr, wrData, rdData);
+                               return false;
+                       }
+               }
+               REG_WRITE(ah, regAddr[i], regHold[i]);
+       }
+       udelay(100);
+
+       return true;
+}
+
+static void ath9k_hw_init_config(struct ath_hw *ah)
+{
+       int i;
+
+       ah->config.dma_beacon_response_time = 2;
+       ah->config.sw_beacon_response_time = 10;
+       ah->config.additional_swba_backoff = 0;
+       ah->config.ack_6mb = 0x0;
+       ah->config.cwm_ignore_extcca = 0;
+       ah->config.pcie_clock_req = 0;
+       ah->config.pcie_waen = 0;
+       ah->config.analog_shiftreg = 1;
+       ah->config.enable_ani = true;
+
+       for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+               ah->config.spurchans[i][0] = AR_NO_SPUR;
+               ah->config.spurchans[i][1] = AR_NO_SPUR;
+       }
+
+       /* PAPRD needs some more work to be enabled */
+       ah->config.paprd_disable = 1;
+
+       ah->config.rx_intr_mitigation = true;
+       ah->config.pcieSerDesWrite = true;
+
+       /*
+        * We need this for PCI devices only (Cardbus, PCI, miniPCI)
+        * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
+        * This means we use it for all AR5416 devices, and the few
+        * minor PCI AR9280 devices out there.
+        *
+        * Serialization is required because these devices do not handle
+        * well the case of two concurrent reads/writes due to the latency
+        * involved. During one read/write another read/write can be issued
+        * on another CPU while the previous read/write may still be working
+        * on our hardware, if we hit this case the hardware poops in a loop.
+        * We prevent this by serializing reads and writes.
+        *
+        * This issue is not present on PCI-Express devices or pre-AR5416
+        * devices (legacy, 802.11abg).
+        */
+       if (num_possible_cpus() > 1)
+               ah->config.serialize_regmode = SER_REG_MODE_AUTO;
+}
+
+static void ath9k_hw_init_defaults(struct ath_hw *ah)
+{
+       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+
+       regulatory->country_code = CTRY_DEFAULT;
+       regulatory->power_limit = MAX_RATE_POWER;
+
+       ah->hw_version.magic = AR5416_MAGIC;
+       ah->hw_version.subvendorid = 0;
+
+       ah->atim_window = 0;
+       ah->sta_id1_defaults =
+               AR_STA_ID1_CRPT_MIC_ENABLE |
+               AR_STA_ID1_MCAST_KSRCH;
+       if (AR_SREV_9100(ah))
+               ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
+       ah->enable_32kHz_clock = DONT_USE_32KHZ;
+       ah->slottime = ATH9K_SLOT_TIME_9;
+       ah->globaltxtimeout = (u32) -1;
+       ah->power_mode = ATH9K_PM_UNDEFINED;
+       ah->htc_reset_init = true;
+}
+
+static int ath9k_hw_init_macaddr(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 sum;
+       int i;
+       u16 eeval;
+       static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
+
+       sum = 0;
+       for (i = 0; i < 3; i++) {
+               eeval = ah->eep_ops->get_eeprom(ah, EEP_MAC[i]);
+               sum += eeval;
+               common->macaddr[2 * i] = eeval >> 8;
+               common->macaddr[2 * i + 1] = eeval & 0xff;
+       }
+       if (sum == 0 || sum == 0xffff * 3)
+               return -EADDRNOTAVAIL;
+
+       return 0;
+}
+
+static int ath9k_hw_post_init(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       int ecode;
+
+       if (common->bus_ops->ath_bus_type != ATH_USB) {
+               if (!ath9k_hw_chip_test(ah))
+                       return -ENODEV;
+       }
+
+       if (!AR_SREV_9300_20_OR_LATER(ah)) {
+               ecode = ar9002_hw_rf_claim(ah);
+               if (ecode != 0)
+                       return ecode;
+       }
+
+       ecode = ath9k_hw_eeprom_init(ah);
+       if (ecode != 0)
+               return ecode;
+
+       ath_dbg(ath9k_hw_common(ah), CONFIG, "Eeprom VER: %d, REV: %d\n",
+               ah->eep_ops->get_eeprom_ver(ah),
+               ah->eep_ops->get_eeprom_rev(ah));
+
+       ecode = ath9k_hw_rf_alloc_ext_banks(ah);
+       if (ecode) {
+               ath_err(ath9k_hw_common(ah),
+                       "Failed allocating banks for external radio\n");
+               ath9k_hw_rf_free_ext_banks(ah);
+               return ecode;
+       }
+
+       if (ah->config.enable_ani) {
+               ath9k_hw_ani_setup(ah);
+               ath9k_hw_ani_init(ah);
+       }
+
+       return 0;
+}
+
+static void ath9k_hw_attach_ops(struct ath_hw *ah)
+{
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ar9003_hw_attach_ops(ah);
+       else
+               ar9002_hw_attach_ops(ah);
+}
+
+/* Called for all hardware families */
+static int __ath9k_hw_init(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       int r = 0;
+
+       ath9k_hw_read_revisions(ah);
+
+       /*
+        * Read back AR_WA into a permanent copy and set bits 14 and 17.
+        * We need to do this to avoid RMW of this register. We cannot
+        * read the reg when chip is asleep.
+        */
+       ah->WARegVal = REG_READ(ah, AR_WA);
+       ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
+                        AR_WA_ASPM_TIMER_BASED_DISABLE);
+
+       if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
+               ath_err(common, "Couldn't reset chip\n");
+               return -EIO;
+       }
+
+       if (AR_SREV_9462(ah))
+               ah->WARegVal &= ~AR_WA_D3_L1_DISABLE;
+
+       ath9k_hw_init_defaults(ah);
+       ath9k_hw_init_config(ah);
+
+       ath9k_hw_attach_ops(ah);
+
+       if (!ath9k_btcoex_ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
+               ath_err(common, "Couldn't wakeup chip\n");
+               return -EIO;
+       }
+
+       if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
+               if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
+                   ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
+                    !ah->is_pciexpress)) {
+                       ah->config.serialize_regmode =
+                               SER_REG_MODE_ON;
+               } else {
+                       ah->config.serialize_regmode =
+                               SER_REG_MODE_OFF;
+               }
+       }
+
+       ath_dbg(common, RESET, "serialize_regmode is %d\n",
+               ah->config.serialize_regmode);
+
+       if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+               ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1;
+       else
+               ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
+
+       switch (ah->hw_version.macVersion) {
+       case AR_SREV_VERSION_5416_PCI:
+       case AR_SREV_VERSION_5416_PCIE:
+       case AR_SREV_VERSION_9160:
+       case AR_SREV_VERSION_9100:
+       case AR_SREV_VERSION_9280:
+       case AR_SREV_VERSION_9285:
+       case AR_SREV_VERSION_9287:
+       case AR_SREV_VERSION_9271:
+       case AR_SREV_VERSION_9300:
+       case AR_SREV_VERSION_9330:
+       case AR_SREV_VERSION_9485:
+       case AR_SREV_VERSION_9340:
+       case AR_SREV_VERSION_9462:
+               break;
+       default:
+               ath_err(common,
+                       "Mac Chip Rev 0x%02x.%x is not supported by this driver\n",
+                       ah->hw_version.macVersion, ah->hw_version.macRev);
+               return -EOPNOTSUPP;
+       }
+
+       if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) ||
+           AR_SREV_9330(ah))
+               ah->is_pciexpress = false;
+
+       ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
+       ath9k_hw_init_cal_settings(ah);
+
+       ah->ani_function = ATH9K_ANI_ALL;
+       if (AR_SREV_9280_20_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+               ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
+
+       /* disable ANI for 9340 */
+       if (AR_SREV_9340(ah))
+               ah->config.enable_ani = false;
+
+       ath9k_hw_init_mode_regs(ah);
+
+       if (!ah->is_pciexpress)
+               ath9k_hw_disablepcie(ah);
+
+       r = ath9k_hw_post_init(ah);
+       if (r)
+               return r;
+
+       ath9k_hw_init_mode_gain_regs(ah);
+       r = ath9k_hw_fill_cap_info(ah);
+       if (r)
+               return r;
+
+       r = ath9k_hw_init_macaddr(ah);
+       if (r) {
+               ath_err(common, "Failed to initialize MAC address\n");
+               return r;
+       }
+
+       if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+               ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
+       else
+               ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
+
+       if (AR_SREV_9330(ah))
+               ah->bb_watchdog_timeout_ms = 85;
+       else
+               ah->bb_watchdog_timeout_ms = 25;
+
+       common->state = ATH_HW_INITIALIZED;
+
+       return 0;
+}
+
+int ath9k_btcoex_ath9k_hw_init(struct ath_hw *ah)
+{
+       int ret;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       /* These are all the AR5008/AR9001/AR9002 hardware family of chipsets */
+       switch (ah->hw_version.devid) {
+       case AR5416_DEVID_PCI:
+       case AR5416_DEVID_PCIE:
+       case AR5416_AR9100_DEVID:
+       case AR9160_DEVID_PCI:
+       case AR9280_DEVID_PCI:
+       case AR9280_DEVID_PCIE:
+       case AR9285_DEVID_PCIE:
+       case AR9287_DEVID_PCI:
+       case AR9287_DEVID_PCIE:
+       case AR2427_DEVID_PCIE:
+       case AR9300_DEVID_PCIE:
+       case AR9300_DEVID_AR9485_PCIE:
+       case AR9300_DEVID_AR9330:
+       case AR9300_DEVID_AR9340:
+       case AR9300_DEVID_AR9580:
+       case AR9300_DEVID_AR9462:
+               break;
+       default:
+               if (common->bus_ops->ath_bus_type == ATH_USB)
+                       break;
+               ath_err(common, "Hardware device ID 0x%04x not supported\n",
+                       ah->hw_version.devid);
+               return -EOPNOTSUPP;
+       }
+
+       ret = __ath9k_hw_init(ah);
+       if (ret) {
+               ath_err(common,
+                       "Unable to initialize hardware; initialization status: %d\n",
+                       ret);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_init);
+
+static void ath9k_hw_init_qos(struct ath_hw *ah)
+{
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
+       REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
+
+       REG_WRITE(ah, AR_QOS_NO_ACK,
+                 SM(2, AR_QOS_NO_ACK_TWO_BIT) |
+                 SM(5, AR_QOS_NO_ACK_BIT_OFF) |
+                 SM(0, AR_QOS_NO_ACK_BYTE_OFF));
+
+       REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
+       REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
+       REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
+       REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
+       REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+u32 ath9k_btcoex_ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)
+{
+       REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
+       udelay(100);
+       REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
+
+       while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0)
+               udelay(100);
+
+       return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ar9003_get_pll_sqsum_dvc);
+
+static void ath9k_hw_init_pll(struct ath_hw *ah,
+                             struct ath9k_channel *chan)
+{
+       u32 pll;
+
+       if (AR_SREV_9485(ah)) {
+
+               /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_BB_DPLL2_PLL_PWD, 0x1);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_DPLL2_KD, 0x40);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_DPLL2_KI, 0x4);
+
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
+                             AR_CH0_BB_DPLL1_REFDIV, 0x5);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
+                             AR_CH0_BB_DPLL1_NINI, 0x58);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
+                             AR_CH0_BB_DPLL1_NFRAC, 0x0);
+
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_BB_DPLL2_OUTDIV, 0x1);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1);
+
+               /* program BB PLL phase_shift to 0x6 */
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
+                             AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6);
+
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_BB_DPLL2_PLL_PWD, 0x0);
+               udelay(1000);
+       } else if (AR_SREV_9330(ah)) {
+               u32 ddr_dpll2, pll_control2, kd;
+
+               if (ah->is_clk_25mhz) {
+                       ddr_dpll2 = 0x18e82f01;
+                       pll_control2 = 0xe04a3d;
+                       kd = 0x1d;
+               } else {
+                       ddr_dpll2 = 0x19e82f01;
+                       pll_control2 = 0x886666;
+                       kd = 0x3d;
+               }
+
+               /* program DDR PLL ki and kd value */
+               REG_WRITE(ah, AR_CH0_DDR_DPLL2, ddr_dpll2);
+
+               /* program DDR PLL phase_shift */
+               REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
+                             AR_CH0_DPLL3_PHASE_SHIFT, 0x1);
+
+               REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+               udelay(1000);
+
+               /* program refdiv, nint, frac to RTC register */
+               REG_WRITE(ah, AR_RTC_PLL_CONTROL2, pll_control2);
+
+               /* program BB PLL kd and ki value */
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KD, kd);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KI, 0x06);
+
+               /* program BB PLL phase_shift */
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
+                             AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);
+       } else if (AR_SREV_9340(ah)) {
+               u32 regval, pll2_divint, pll2_divfrac, refdiv;
+
+               REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+               udelay(1000);
+
+               REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16);
+               udelay(100);
+
+               if (ah->is_clk_25mhz) {
+                       pll2_divint = 0x54;
+                       pll2_divfrac = 0x1eb85;
+                       refdiv = 3;
+               } else {
+                       pll2_divint = 88;
+                       pll2_divfrac = 0;
+                       refdiv = 5;
+               }
+
+               regval = REG_READ(ah, AR_PHY_PLL_MODE);
+               regval |= (0x1 << 16);
+               REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
+               udelay(100);
+
+               REG_WRITE(ah, AR_PHY_PLL_CONTROL, (refdiv << 27) |
+                         (pll2_divint << 18) | pll2_divfrac);
+               udelay(100);
+
+               regval = REG_READ(ah, AR_PHY_PLL_MODE);
+               regval = (regval & 0x80071fff) | (0x1 << 30) | (0x1 << 13) |
+                        (0x4 << 26) | (0x18 << 19);
+               REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
+               REG_WRITE(ah, AR_PHY_PLL_MODE,
+                         REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff);
+               udelay(1000);
+       }
+
+       pll = ath9k_hw_compute_pll_control(ah, chan);
+
+       REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
+
+       if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
+               udelay(1000);
+
+       /* Switch the core clock for ar9271 to 117Mhz */
+       if (AR_SREV_9271(ah)) {
+               udelay(500);
+               REG_WRITE(ah, 0x50040, 0x304);
+       }
+
+       udelay(RTC_PLL_SETTLE_DELAY);
+
+       REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
+
+       if (AR_SREV_9340(ah)) {
+               if (ah->is_clk_25mhz) {
+                       REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
+                       REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
+                       REG_WRITE(ah,  AR_SLP32_INC, 0x0001e7ae);
+               } else {
+                       REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1);
+                       REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
+                       REG_WRITE(ah,  AR_SLP32_INC, 0x0001e800);
+               }
+               udelay(100);
+       }
+}
+
+static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
+                                         enum nl80211_iftype opmode)
+{
+       u32 sync_default = AR_INTR_SYNC_DEFAULT;
+       u32 imr_reg = AR_IMR_TXERR |
+               AR_IMR_TXURN |
+               AR_IMR_RXERR |
+               AR_IMR_RXORN |
+               AR_IMR_BCNMISC;
+
+       if (AR_SREV_9340(ah))
+               sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               imr_reg |= AR_IMR_RXOK_HP;
+               if (ah->config.rx_intr_mitigation)
+                       imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+               else
+                       imr_reg |= AR_IMR_RXOK_LP;
+
+       } else {
+               if (ah->config.rx_intr_mitigation)
+                       imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+               else
+                       imr_reg |= AR_IMR_RXOK;
+       }
+
+       if (ah->config.tx_intr_mitigation)
+               imr_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR;
+       else
+               imr_reg |= AR_IMR_TXOK;
+
+       if (opmode == NL80211_IFTYPE_AP)
+               imr_reg |= AR_IMR_MIB;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_IMR, imr_reg);
+       ah->imrs2_reg |= AR_IMR_S2_GTT;
+       REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
+
+       if (!AR_SREV_9100(ah)) {
+               REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
+               REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default);
+               REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
+       }
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0);
+               REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK, 0);
+               REG_WRITE(ah, AR_INTR_PRIO_SYNC_ENABLE, 0);
+               REG_WRITE(ah, AR_INTR_PRIO_SYNC_MASK, 0);
+       }
+}
+
+static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us)
+{
+       u32 val = ath9k_hw_mac_to_clks(ah, us - 2);
+       val = min(val, (u32) 0xFFFF);
+       REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val);
+}
+
+static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
+{
+       u32 val = ath9k_hw_mac_to_clks(ah, us);
+       val = min(val, (u32) 0xFFFF);
+       REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val);
+}
+
+static void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
+{
+       u32 val = ath9k_hw_mac_to_clks(ah, us);
+       val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK));
+       REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val);
+}
+
+static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
+{
+       u32 val = ath9k_hw_mac_to_clks(ah, us);
+       val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS));
+       REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val);
+}
+
+static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
+{
+       if (tu > 0xFFFF) {
+               ath_dbg(ath9k_hw_common(ah), XMIT, "bad global tx timeout %u\n",
+                       tu);
+               ah->globaltxtimeout = (u32) -1;
+               return false;
+       } else {
+               REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
+               ah->globaltxtimeout = tu;
+               return true;
+       }
+}
+
+void ath9k_btcoex_ath9k_hw_init_global_settings(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_conf *conf = &common->hw->conf;
+       const struct ath9k_channel *chan = ah->curchan;
+       int acktimeout, ctstimeout;
+       int slottime;
+       int sifstime;
+       int rx_lat = 0, tx_lat = 0, eifs = 0;
+       u32 reg;
+
+       ath_dbg(ath9k_hw_common(ah), RESET, "ah->misc_mode 0x%x\n",
+               ah->misc_mode);
+
+       if (!chan)
+               return;
+
+       if (ah->misc_mode != 0)
+               REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
+
+       if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+               rx_lat = 41;
+       else
+               rx_lat = 37;
+       tx_lat = 54;
+
+       if (IS_CHAN_HALF_RATE(chan)) {
+               eifs = 175;
+               rx_lat *= 2;
+               tx_lat *= 2;
+               if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+                   tx_lat += 11;
+
+               slottime = 13;
+               sifstime = 32;
+       } else if (IS_CHAN_QUARTER_RATE(chan)) {
+               eifs = 340;
+               rx_lat = (rx_lat * 4) - 1;
+               tx_lat *= 4;
+               if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+                   tx_lat += 22;
+
+               slottime = 21;
+               sifstime = 64;
+       } else {
+               if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
+                       eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO;
+                       reg = AR_USEC_ASYNC_FIFO;
+               } else {
+                       eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/
+                               common->clockrate;
+                       reg = REG_READ(ah, AR_USEC);
+               }
+               rx_lat = MS(reg, AR_USEC_RX_LAT);
+               tx_lat = MS(reg, AR_USEC_TX_LAT);
+
+               slottime = ah->slottime;
+               if (IS_CHAN_5GHZ(chan))
+                       sifstime = 16;
+               else
+                       sifstime = 10;
+       }
+
+       /* As defined by IEEE 802.11-2007 17.3.8.6 */
+       acktimeout = slottime + sifstime + 3 * ah->coverage_class;
+       ctstimeout = acktimeout;
+
+       /*
+        * Workaround for early ACK timeouts, add an offset to match the
+        * initval's 64us ack timeout value. Use 48us for the CTS timeout.
+        * This was initially only meant to work around an issue with delayed
+        * BA frames in some implementations, but it has been found to fix ACK
+        * timeout issues in other cases as well.
+        */
+       if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) {
+               acktimeout += 64 - sifstime - ah->slottime;
+               ctstimeout += 48 - sifstime - ah->slottime;
+       }
+
+
+       ath9k_hw_set_sifs_time(ah, sifstime);
+       ath9k_hw_setslottime(ah, slottime);
+       ath9k_hw_set_ack_timeout(ah, acktimeout);
+       ath9k_hw_set_cts_timeout(ah, ctstimeout);
+       if (ah->globaltxtimeout != (u32) -1)
+               ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
+
+       REG_WRITE(ah, AR_D_GBL_IFS_EIFS, ath9k_hw_mac_to_clks(ah, eifs));
+       REG_RMW(ah, AR_USEC,
+               (common->clockrate - 1) |
+               SM(rx_lat, AR_USEC_RX_LAT) |
+               SM(tx_lat, AR_USEC_TX_LAT),
+               AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC);
+
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_init_global_settings);
+
+void ath9k_btcoex_ath9k_hw_deinit(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (common->state < ATH_HW_INITIALIZED)
+               goto free_hw;
+
+       ath9k_btcoex_ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
+
+free_hw:
+       ath9k_hw_rf_free_ext_banks(ah);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_deinit);
+
+/*******/
+/* INI */
+/*******/
+
+u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan)
+{
+       u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band);
+
+       if (IS_CHAN_B(chan))
+               ctl |= CTL_11B;
+       else if (IS_CHAN_G(chan))
+               ctl |= CTL_11G;
+       else
+               ctl |= CTL_11A;
+
+       return ctl;
+}
+
+/****************************************/
+/* Reset and Channel Switching Routines */
+/****************************************/
+
+static inline void ath9k_hw_set_dma(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       /*
+        * set AHB_MODE not to do cacheline prefetches
+       */
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN);
+
+       /*
+        * let mac dma reads be in 128 byte chunks
+        */
+       REG_RMW(ah, AR_TXCFG, AR_TXCFG_DMASZ_128B, AR_TXCFG_DMASZ_MASK);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       /*
+        * Restore TX Trigger Level to its pre-reset value.
+        * The initial value depends on whether aggregation is enabled, and is
+        * adjusted whenever underruns are detected.
+        */
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       /*
+        * let mac dma writes be in 128 byte chunks
+        */
+       REG_RMW(ah, AR_RXCFG, AR_RXCFG_DMASZ_128B, AR_RXCFG_DMASZ_MASK);
+
+       /*
+        * Setup receive FIFO threshold to hold off TX activities
+        */
+       REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_HP, 0x1);
+               REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_LP, 0x1);
+
+               ath9k_btcoex_ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
+                       ah->caps.rx_status_len);
+       }
+
+       /*
+        * reduce the number of usable entries in PCU TXBUF to avoid
+        * wrap around issues.
+        */
+       if (AR_SREV_9285(ah)) {
+               /* For AR9285 the number of Fifos are reduced to half.
+                * So set the usable tx buf size also to half to
+                * avoid data/delimiter underruns
+                */
+               REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+                         AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
+       } else if (!AR_SREV_9271(ah)) {
+               REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+                         AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+       }
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ath9k_hw_reset_txstatus_ring(ah);
+}
+
+static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
+{
+       u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC;
+       u32 set = AR_STA_ID1_KSRCH_MODE;
+
+       switch (opmode) {
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_MESH_POINT:
+               set |= AR_STA_ID1_ADHOC;
+               REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+               break;
+       case NL80211_IFTYPE_AP:
+               set |= AR_STA_ID1_STA_AP;
+               /* fall through */
+       case NL80211_IFTYPE_STATION:
+               REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+               break;
+       default:
+               if (!ah->is_monitoring)
+                       set = 0;
+               break;
+       }
+       REG_RMW(ah, AR_STA_ID1, set, mask);
+}
+
+void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
+                                  u32 *coef_mantissa, u32 *coef_exponent)
+{
+       u32 coef_exp, coef_man;
+
+       for (coef_exp = 31; coef_exp > 0; coef_exp--)
+               if ((coef_scaled >> coef_exp) & 0x1)
+                       break;
+
+       coef_exp = 14 - (coef_exp - COEF_SCALE_S);
+
+       coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
+
+       *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
+       *coef_exponent = coef_exp - 16;
+}
+
+static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
+{
+       u32 rst_flags;
+       u32 tmpReg;
+
+       if (AR_SREV_9100(ah)) {
+               REG_RMW_FIELD(ah, AR_RTC_DERIVED_CLK,
+                             AR_RTC_DERIVED_CLK_PERIOD, 1);
+               (void)REG_READ(ah, AR_RTC_DERIVED_CLK);
+       }
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_WRITE(ah, AR_WA, ah->WARegVal);
+               udelay(10);
+       }
+
+       REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+                 AR_RTC_FORCE_WAKE_ON_INT);
+
+       if (AR_SREV_9100(ah)) {
+               rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
+                       AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
+       } else {
+               tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
+               if (tmpReg &
+                   (AR_INTR_SYNC_LOCAL_TIMEOUT |
+                    AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+                       u32 val;
+                       REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+
+                       val = AR_RC_HOSTIF;
+                       if (!AR_SREV_9300_20_OR_LATER(ah))
+                               val |= AR_RC_AHB;
+                       REG_WRITE(ah, AR_RC, val);
+
+               } else if (!AR_SREV_9300_20_OR_LATER(ah))
+                       REG_WRITE(ah, AR_RC, AR_RC_AHB);
+
+               rst_flags = AR_RTC_RC_MAC_WARM;
+               if (type == ATH9K_RESET_COLD)
+                       rst_flags |= AR_RTC_RC_MAC_COLD;
+       }
+
+       if (AR_SREV_9330(ah)) {
+               int npend = 0;
+               int i;
+
+               /* AR9330 WAR:
+                * call external reset function to reset WMAC if:
+                * - doing a cold reset
+                * - we have pending frames in the TX queues
+                */
+
+               for (i = 0; i < AR_NUM_QCU; i++) {
+                       npend = ath9k_btcoex_ath9k_hw_numtxpending(ah, i);
+                       if (npend)
+                               break;
+               }
+
+               if (ah->external_reset &&
+                   (npend || type == ATH9K_RESET_COLD)) {
+                       int reset_err = 0;
+
+                       ath_dbg(ath9k_hw_common(ah), RESET,
+                               "reset MAC via external reset\n");
+
+                       reset_err = ah->external_reset();
+                       if (reset_err) {
+                               ath_err(ath9k_hw_common(ah),
+                                       "External reset failed, err=%d\n",
+                                       reset_err);
+                               return false;
+                       }
+
+                       REG_WRITE(ah, AR_RTC_RESET, 1);
+               }
+       }
+
+       if (ath9k_hw_mci_is_enabled(ah))
+               ar9003_mci_check_gpm_offset(ah);
+
+       REG_WRITE(ah, AR_RTC_RC, rst_flags);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       udelay(50);
+
+       REG_WRITE(ah, AR_RTC_RC, 0);
+       if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
+               ath_dbg(ath9k_hw_common(ah), RESET, "RTC stuck in MAC reset\n");
+               return false;
+       }
+
+       if (!AR_SREV_9100(ah))
+               REG_WRITE(ah, AR_RC, 0);
+
+       if (AR_SREV_9100(ah))
+               udelay(50);
+
+       return true;
+}
+
+static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
+{
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_WRITE(ah, AR_WA, ah->WARegVal);
+               udelay(10);
+       }
+
+       REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+                 AR_RTC_FORCE_WAKE_ON_INT);
+
+       if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+               REG_WRITE(ah, AR_RC, AR_RC_AHB);
+
+       REG_WRITE(ah, AR_RTC_RESET, 0);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               udelay(2);
+
+       if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+               REG_WRITE(ah, AR_RC, 0);
+
+       REG_WRITE(ah, AR_RTC_RESET, 1);
+
+       if (!ath9k_btcoex_ath9k_hw_wait(ah,
+                          AR_RTC_STATUS,
+                          AR_RTC_STATUS_M,
+                          AR_RTC_STATUS_ON,
+                          AH_WAIT_TIMEOUT)) {
+               ath_dbg(ath9k_hw_common(ah), RESET, "RTC not waking up\n");
+               return false;
+       }
+
+       return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
+}
+
+static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
+{
+       bool ret = false;
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_WRITE(ah, AR_WA, ah->WARegVal);
+               udelay(10);
+       }
+
+       REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+                 AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+       switch (type) {
+       case ATH9K_RESET_POWER_ON:
+               ret = ath9k_hw_set_reset_power_on(ah);
+               break;
+       case ATH9K_RESET_WARM:
+       case ATH9K_RESET_COLD:
+               ret = ath9k_hw_set_reset(ah, type);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static bool ath9k_hw_chip_reset(struct ath_hw *ah,
+                               struct ath9k_channel *chan)
+{
+       int reset_type = ATH9K_RESET_WARM;
+
+       if (AR_SREV_9280(ah)) {
+               if (ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+                       reset_type = ATH9K_RESET_POWER_ON;
+               else
+                       reset_type = ATH9K_RESET_COLD;
+       }
+
+       if (!ath9k_hw_set_reset_reg(ah, reset_type))
+               return false;
+
+       if (!ath9k_btcoex_ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+               return false;
+
+       ah->chip_fullsleep = false;
+       ath9k_hw_init_pll(ah, chan);
+       ath9k_hw_set_rfmode(ah, chan);
+
+       return true;
+}
+
+static bool ath9k_hw_channel_change(struct ath_hw *ah,
+                                   struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 qnum;
+       int r;
+       bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+       bool band_switch, mode_diff;
+       u8 ini_reloaded;
+
+       band_switch = (chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ)) !=
+                     (ah->curchan->channelFlags & (CHANNEL_2GHZ |
+                                                   CHANNEL_5GHZ));
+       mode_diff = (chan->chanmode != ah->curchan->chanmode);
+
+       for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
+               if (ath9k_btcoex_ath9k_hw_numtxpending(ah, qnum)) {
+                       ath_dbg(common, QUEUE,
+                               "Transmit frames pending on queue %d\n", qnum);
+                       return false;
+               }
+       }
+
+       if (!ath9k_hw_rfbus_req(ah)) {
+               ath_err(common, "Could not kill baseband RX\n");
+               return false;
+       }
+
+       if (edma && (band_switch || mode_diff)) {
+               ath9k_hw_mark_phy_inactive(ah);
+               udelay(5);
+
+               ath9k_hw_init_pll(ah, NULL);
+
+               if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) {
+                       ath_err(common, "Failed to do fast channel change\n");
+                       return false;
+               }
+       }
+
+       ath9k_hw_set_channel_regs(ah, chan);
+
+       r = ath9k_hw_rf_set_freq(ah, chan);
+       if (r) {
+               ath_err(common, "Failed to set channel\n");
+               return false;
+       }
+       ath9k_hw_set_clockrate(ah);
+       ath9k_hw_apply_txpower(ah, chan, false);
+       ath9k_hw_rfbus_done(ah);
+
+       if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+               ath9k_hw_set_delta_slope(ah, chan);
+
+       ath9k_hw_spur_mitigate_freq(ah, chan);
+
+       if (edma && (band_switch || mode_diff)) {
+               ah->ah_flags |= AH_FASTCC;
+               if (band_switch || ini_reloaded)
+                       ah->eep_ops->set_board_values(ah, chan);
+
+               ath9k_hw_init_bb(ah, chan);
+
+               if (band_switch || ini_reloaded)
+                       ath9k_hw_init_cal(ah, chan);
+               ah->ah_flags &= ~AH_FASTCC;
+       }
+
+       return true;
+}
+
+static void ath9k_hw_apply_gpio_override(struct ath_hw *ah)
+{
+       u32 gpio_mask = ah->gpio_mask;
+       int i;
+
+       for (i = 0; gpio_mask; i++, gpio_mask >>= 1) {
+               if (!(gpio_mask & 1))
+                       continue;
+
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, i, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+               ath9k_btcoex_ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i)));
+       }
+}
+
+bool ath9k_btcoex_ath9k_hw_check_alive(struct ath_hw *ah)
+{
+       int count = 50;
+       u32 reg;
+
+       if (AR_SREV_9285_12_OR_LATER(ah))
+               return true;
+
+       do {
+               reg = REG_READ(ah, AR_OBS_BUS_1);
+
+               if ((reg & 0x7E7FFFEF) == 0x00702400)
+                       continue;
+
+               switch (reg & 0x7E000B00) {
+               case 0x1E000000:
+               case 0x52000B00:
+               case 0x18000B00:
+                       continue;
+               default:
+                       return true;
+               }
+       } while (count-- > 0);
+
+       return false;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_check_alive);
+
+/*
+ * Fast channel change:
+ * (Change synthesizer based on channel freq without resetting chip)
+ *
+ * Don't do FCC when
+ *   - Flag is not set
+ *   - Chip is just coming out of full sleep
+ *   - Channel to be set is same as current channel
+ *   - Channel flags are different, (eg.,moving from 2GHz to 5GHz channel)
+ */
+static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       int ret;
+
+       if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
+               goto fail;
+
+       if (ah->chip_fullsleep)
+               goto fail;
+
+       if (!ah->curchan)
+               goto fail;
+
+       if (chan->channel == ah->curchan->channel)
+               goto fail;
+
+       if ((chan->channelFlags & CHANNEL_ALL) !=
+           (ah->curchan->channelFlags & CHANNEL_ALL))
+               goto fail;
+
+       if (!ath9k_btcoex_ath9k_hw_check_alive(ah))
+               goto fail;
+
+       /*
+        * For AR9462, make sure that calibration data for
+        * re-using are present.
+        */
+       if (AR_SREV_9462(ah) && (ah->caldata &&
+                                (!ah->caldata->done_txiqcal_once ||
+                                 !ah->caldata->done_txclcal_once ||
+                                 !ah->caldata->rtt_done)))
+               goto fail;
+
+       ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n",
+               ah->curchan->channel, chan->channel);
+
+       ret = ath9k_hw_channel_change(ah, chan);
+       if (!ret)
+               goto fail;
+
+       ath9k_hw_loadnf(ah, ah->curchan);
+       ath9k_hw_start_nfcal(ah, true);
+
+       if (ath9k_hw_mci_is_enabled(ah))
+               ar9003_mci_2g5g_switch(ah, false);
+
+       if (AR_SREV_9271(ah))
+               ar9002_hw_load_ani_reg(ah, chan);
+
+       return 0;
+fail:
+       return -EINVAL;
+}
+
+int ath9k_btcoex_ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+                  struct ath9k_hw_cal_data *caldata, bool fastcc)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 saveLedState;
+       u32 saveDefAntenna;
+       u32 macStaId1;
+       u64 tsf = 0;
+       int i, r;
+       bool start_mci_reset = false;
+       bool save_fullsleep = ah->chip_fullsleep;
+
+       if (ath9k_hw_mci_is_enabled(ah)) {
+               start_mci_reset = ar9003_mci_start_reset(ah, chan);
+               if (start_mci_reset)
+                       return 0;
+       }
+
+       if (!ath9k_btcoex_ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+               return -EIO;
+
+       if (ah->curchan && !ah->chip_fullsleep)
+               ath9k_btcoex_ath9k_hw_getnf(ah, ah->curchan);
+
+       ah->caldata = caldata;
+       if (caldata &&
+           (chan->channel != caldata->channel ||
+            (chan->channelFlags & ~CHANNEL_CW_INT) !=
+            (caldata->channelFlags & ~CHANNEL_CW_INT))) {
+               /* Operating channel changed, reset channel calibration data */
+               memset(caldata, 0, sizeof(*caldata));
+               ath9k_init_nfcal_hist_buffer(ah, chan);
+       }
+       ah->noise = ath9k_btcoex_ath9k_hw_getchan_noise(ah, chan);
+
+       if (fastcc) {
+               r = ath9k_hw_do_fastcc(ah, chan);
+               if (!r)
+                       return r;
+       }
+
+       if (ath9k_hw_mci_is_enabled(ah))
+               ar9003_mci_stop_bt(ah, save_fullsleep);
+
+       saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
+       if (saveDefAntenna == 0)
+               saveDefAntenna = 1;
+
+       macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
+
+       /* For chips on which RTC reset is done, save TSF before it gets cleared */
+       if (AR_SREV_9100(ah) ||
+           (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)))
+               tsf = ath9k_btcoex_ath9k_hw_gettsf64(ah);
+
+       saveLedState = REG_READ(ah, AR_CFG_LED) &
+               (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
+                AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
+
+       ath9k_hw_mark_phy_inactive(ah);
+
+       ah->paprd_table_write_done = false;
+
+       /* Only required on the first reset */
+       if (AR_SREV_9271(ah) && ah->htc_reset_init) {
+               REG_WRITE(ah,
+                         AR9271_RESET_POWER_DOWN_CONTROL,
+                         AR9271_RADIO_RF_RST);
+               udelay(50);
+       }
+
+       if (!ath9k_hw_chip_reset(ah, chan)) {
+               ath_err(common, "Chip reset failed\n");
+               return -EINVAL;
+       }
+
+       /* Only required on the first reset */
+       if (AR_SREV_9271(ah) && ah->htc_reset_init) {
+               ah->htc_reset_init = false;
+               REG_WRITE(ah,
+                         AR9271_RESET_POWER_DOWN_CONTROL,
+                         AR9271_GATE_MAC_CTL);
+               udelay(50);
+       }
+
+       /* Restore TSF */
+       if (tsf)
+               ath9k_btcoex_ath9k_hw_settsf64(ah, tsf);
+
+       if (AR_SREV_9280_20_OR_LATER(ah))
+               REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
+
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               ar9002_hw_enable_async_fifo(ah);
+
+       r = ath9k_hw_process_ini(ah, chan);
+       if (r)
+               return r;
+
+       if (ath9k_hw_mci_is_enabled(ah))
+               ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep);
+
+       /*
+        * Some AR91xx SoC devices frequently fail to accept TSF writes
+        * right after the chip reset. When that happens, write a new
+        * value after the initvals have been applied, with an offset
+        * based on measured time difference
+        */
+       if (AR_SREV_9100(ah) && (ath9k_btcoex_ath9k_hw_gettsf64(ah) < tsf)) {
+               tsf += 1500;
+               ath9k_btcoex_ath9k_hw_settsf64(ah, tsf);
+       }
+
+       /* Setup MFP options for CCMP */
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
+                * frames when constructing CCMP AAD. */
+               REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
+                             0xc7ff);
+               ah->sw_mgmt_crypto = false;
+       } else if (AR_SREV_9160_10_OR_LATER(ah)) {
+               /* Disable hardware crypto for management frames */
+               REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
+                           AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
+               REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+                           AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
+               ah->sw_mgmt_crypto = true;
+       } else
+               ah->sw_mgmt_crypto = true;
+
+       if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+               ath9k_hw_set_delta_slope(ah, chan);
+
+       ath9k_hw_spur_mitigate_freq(ah, chan);
+       ah->eep_ops->set_board_values(ah, chan);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
+       REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
+                 | macStaId1
+                 | AR_STA_ID1_RTS_USE_DEF
+                 | (ah->config.
+                    ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
+                 | ah->sta_id1_defaults);
+       ath_hw_setbssidmask(common);
+       REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+       ath9k_btcoex_ath9k_hw_write_associd(ah);
+       REG_WRITE(ah, AR_ISR, ~0);
+       REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       ath9k_hw_set_operating_mode(ah, ah->opmode);
+
+       r = ath9k_hw_rf_set_freq(ah, chan);
+       if (r)
+               return r;
+
+       ath9k_hw_set_clockrate(ah);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       for (i = 0; i < AR_NUM_DCU; i++)
+               REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       ah->intr_txqs = 0;
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+               ath9k_btcoex_ath9k_hw_resettxqueue(ah, i);
+
+       ath9k_hw_init_interrupt_masks(ah, ah->opmode);
+       ath9k_hw_ani_cache_ini_regs(ah);
+       ath9k_hw_init_qos(ah);
+
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+               ath9k_btcoex_ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
+
+       ath9k_btcoex_ath9k_hw_init_global_settings(ah);
+
+       if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
+               REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
+                           AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
+               REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
+                             AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
+               REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+                           AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
+       }
+
+       REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
+
+       ath9k_hw_set_dma(ah);
+
+       if (!ath9k_hw_mci_is_enabled(ah))
+               REG_WRITE(ah, AR_OBS, 8);
+
+       if (ah->config.rx_intr_mitigation) {
+               REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
+               REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
+       }
+
+       if (ah->config.tx_intr_mitigation) {
+               REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300);
+               REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750);
+       }
+
+       ath9k_hw_init_bb(ah, chan);
+
+       if (caldata) {
+               caldata->done_txiqcal_once = false;
+               caldata->done_txclcal_once = false;
+       }
+       if (!ath9k_hw_init_cal(ah, chan))
+               return -EIO;
+
+       if (ath9k_hw_mci_is_enabled(ah) &&
+           ar9003_mci_end_reset(ah, chan, caldata))
+               return -EIO;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       ath9k_hw_restore_chainmask(ah);
+       REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       /*
+        * For big endian systems turn on swapping for descriptors
+        */
+       if (AR_SREV_9100(ah)) {
+               u32 mask;
+               mask = REG_READ(ah, AR_CFG);
+               if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
+                       ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n",
+                               mask);
+               } else {
+                       mask =
+                               INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
+                       REG_WRITE(ah, AR_CFG, mask);
+                       ath_dbg(common, RESET, "Setting CFG 0x%x\n",
+                               REG_READ(ah, AR_CFG));
+               }
+       } else {
+               if (common->bus_ops->ath_bus_type == ATH_USB) {
+                       /* Configure AR9271 target WLAN */
+                       if (AR_SREV_9271(ah))
+                               REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
+                       else
+                               REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+               }
+#ifdef __BIG_ENDIAN
+               else if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+                       REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
+               else
+                       REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+#endif
+       }
+
+       if (ath9k_hw_btcoex_is_enabled(ah))
+               ath9k_btcoex_ath9k_hw_btcoex_enable(ah);
+
+       if (ath9k_hw_mci_is_enabled(ah))
+               ar9003_mci_check_bt(ah);
+
+       ath9k_hw_loadnf(ah, chan);
+       ath9k_hw_start_nfcal(ah, true);
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               ar9003_hw_bb_watchdog_config(ah);
+
+               ath9k_btcoex_ar9003_hw_disable_phy_restart(ah);
+       }
+
+       ath9k_hw_apply_gpio_override(ah);
+
+       return 0;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_reset);
+
+/******************************/
+/* Power Management (Chipset) */
+/******************************/
+
+/*
+ * Notify Power Mgt is disabled in self-generated frames.
+ * If requested, force chip to sleep.
+ */
+static void ath9k_set_power_sleep(struct ath_hw *ah)
+{
+       REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+
+       if (AR_SREV_9462(ah)) {
+               REG_CLR_BIT(ah, AR_TIMER_MODE, 0xff);
+               REG_CLR_BIT(ah, AR_NDP2_TIMER_MODE, 0xff);
+               REG_CLR_BIT(ah, AR_SLP32_INC, 0xfffff);
+               /* xxx Required for WLAN only case ? */
+               REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
+               udelay(100);
+       }
+
+       /*
+        * Clear the RTC force wake bit to allow the
+        * mac to go to sleep.
+        */
+       REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+
+       if (ath9k_hw_mci_is_enabled(ah))
+               udelay(100);
+
+       if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+               REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+
+       /* Shutdown chip. Active low */
+       if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) {
+               REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
+               udelay(2);
+       }
+
+       /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
+}
+
+/*
+ * Notify Power Management is enabled in self-generating
+ * frames. If request, set power mode of chip to
+ * auto/normal.  Duration in units of 128us (1/8 TU).
+ */
+static void ath9k_set_power_network_sleep(struct ath_hw *ah)
+{
+       struct ath9k_hw_capabilities *pCap = &ah->caps;
+
+       REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+
+       if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+               /* Set WakeOnInterrupt bit; clear ForceWake bit */
+               REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+                         AR_RTC_FORCE_WAKE_ON_INT);
+       } else {
+
+               /* When chip goes into network sleep, it could be waken
+                * up by MCI_INT interrupt caused by BT's HW messages
+                * (LNA_xxx, CONT_xxx) which chould be in a very fast
+                * rate (~100us). This will cause chip to leave and
+                * re-enter network sleep mode frequently, which in
+                * consequence will have WLAN MCI HW to generate lots of
+                * SYS_WAKING and SYS_SLEEPING messages which will make
+                * BT CPU to busy to process.
+                */
+               if (ath9k_hw_mci_is_enabled(ah))
+                       REG_CLR_BIT(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
+                                   AR_MCI_INTERRUPT_RX_HW_MSG_MASK);
+               /*
+                * Clear the RTC force wake bit to allow the
+                * mac to go to sleep.
+                */
+               REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+
+               if (ath9k_hw_mci_is_enabled(ah))
+                       udelay(30);
+       }
+
+       /* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
+}
+
+static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
+{
+       u32 val;
+       int i;
+
+       /* Set Bits 14 and 17 of AR_WA before powering on the chip. */
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_WRITE(ah, AR_WA, ah->WARegVal);
+               udelay(10);
+       }
+
+       if ((REG_READ(ah, AR_RTC_STATUS) &
+            AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
+               if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
+                       return false;
+               }
+               if (!AR_SREV_9300_20_OR_LATER(ah))
+                       ath9k_hw_init_pll(ah, NULL);
+       }
+       if (AR_SREV_9100(ah))
+               REG_SET_BIT(ah, AR_RTC_RESET,
+                           AR_RTC_RESET_EN);
+
+       REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+                   AR_RTC_FORCE_WAKE_EN);
+       udelay(50);
+
+       if (ath9k_hw_mci_is_enabled(ah))
+               ar9003_mci_set_power_awake(ah);
+
+       for (i = POWER_UP_TIME / 50; i > 0; i--) {
+               val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
+               if (val == AR_RTC_STATUS_ON)
+                       break;
+               udelay(50);
+               REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+                           AR_RTC_FORCE_WAKE_EN);
+       }
+       if (i == 0) {
+               ath_err(ath9k_hw_common(ah),
+                       "Failed to wakeup in %uus\n",
+                       POWER_UP_TIME / 20);
+               return false;
+       }
+
+       REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+
+       return true;
+}
+
+bool ath9k_btcoex_ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       int status = true;
+       static const char *modes[] = {
+               "AWAKE",
+               "FULL-SLEEP",
+               "NETWORK SLEEP",
+               "UNDEFINED"
+       };
+
+       if (ah->power_mode == mode)
+               return status;
+
+       ath_dbg(common, RESET, "%s -> %s\n",
+               modes[ah->power_mode], modes[mode]);
+
+       switch (mode) {
+       case ATH9K_PM_AWAKE:
+               status = ath9k_hw_set_power_awake(ah);
+               break;
+       case ATH9K_PM_FULL_SLEEP:
+               if (ath9k_hw_mci_is_enabled(ah))
+                       ar9003_mci_set_full_sleep(ah);
+
+               ath9k_set_power_sleep(ah);
+               ah->chip_fullsleep = true;
+               break;
+       case ATH9K_PM_NETWORK_SLEEP:
+               ath9k_set_power_network_sleep(ah);
+               break;
+       default:
+               ath_err(common, "Unknown power mode %u\n", mode);
+               return false;
+       }
+       ah->power_mode = mode;
+
+       /*
+        * XXX: If this warning never comes up after a while then
+        * simply keep the ATH_DBG_WARN_ON_ONCE() but make
+        * ath9k_btcoex_ath9k_hw_setpower() return type void.
+        */
+
+       if (!(ah->ah_flags & AH_UNPLUGGED))
+               ATH_DBG_WARN_ON_ONCE(!status);
+
+       return status;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_setpower);
+
+/*******************/
+/* Beacon Handling */
+/*******************/
+
+void ath9k_btcoex_ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
+{
+       int flags = 0;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       switch (ah->opmode) {
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_MESH_POINT:
+               REG_SET_BIT(ah, AR_TXCFG,
+                           AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
+               REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon +
+                         TU_TO_USEC(ah->atim_window ? ah->atim_window : 1));
+               flags |= AR_NDP_TIMER_EN;
+       case NL80211_IFTYPE_AP:
+               REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon);
+               REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon -
+                         TU_TO_USEC(ah->config.dma_beacon_response_time));
+               REG_WRITE(ah, AR_NEXT_SWBA, next_beacon -
+                         TU_TO_USEC(ah->config.sw_beacon_response_time));
+               flags |=
+                       AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
+               break;
+       default:
+               ath_dbg(ath9k_hw_common(ah), BEACON,
+                       "%s: unsupported opmode: %d\n", __func__, ah->opmode);
+               return;
+               break;
+       }
+
+       REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period);
+       REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period);
+       REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period);
+       REG_WRITE(ah, AR_NDP_PERIOD, beacon_period);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       REG_SET_BIT(ah, AR_TIMER_MODE, flags);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_beaconinit);
+
+void ath9k_btcoex_ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
+                                   const struct ath9k_beacon_state *bs)
+{
+       u32 nextTbtt, beaconintval, dtimperiod, beacontimeout;
+       struct ath9k_hw_capabilities *pCap = &ah->caps;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
+
+       REG_WRITE(ah, AR_BEACON_PERIOD,
+                 TU_TO_USEC(bs->bs_intval));
+       REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
+                 TU_TO_USEC(bs->bs_intval));
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       REG_RMW_FIELD(ah, AR_RSSI_THR,
+                     AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
+
+       beaconintval = bs->bs_intval;
+
+       if (bs->bs_sleepduration > beaconintval)
+               beaconintval = bs->bs_sleepduration;
+
+       dtimperiod = bs->bs_dtimperiod;
+       if (bs->bs_sleepduration > dtimperiod)
+               dtimperiod = bs->bs_sleepduration;
+
+       if (beaconintval == dtimperiod)
+               nextTbtt = bs->bs_nextdtim;
+       else
+               nextTbtt = bs->bs_nexttbtt;
+
+       ath_dbg(common, BEACON, "next DTIM %d\n", bs->bs_nextdtim);
+       ath_dbg(common, BEACON, "next beacon %d\n", nextTbtt);
+       ath_dbg(common, BEACON, "beacon period %d\n", beaconintval);
+       ath_dbg(common, BEACON, "DTIM period %d\n", dtimperiod);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_NEXT_DTIM,
+                 TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
+       REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
+
+       REG_WRITE(ah, AR_SLEEP1,
+                 SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
+                 | AR_SLEEP1_ASSUME_DTIM);
+
+       if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)
+               beacontimeout = (BEACON_TIMEOUT_VAL << 3);
+       else
+               beacontimeout = MIN_BEACON_TIMEOUT_VAL;
+
+       REG_WRITE(ah, AR_SLEEP2,
+                 SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
+
+       REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
+       REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       REG_SET_BIT(ah, AR_TIMER_MODE,
+                   AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
+                   AR_DTIM_TIMER_EN);
+
+       /* TSF Out of Range Threshold */
+       REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_set_sta_beacon_timers);
+
+/*******************/
+/* HW Capabilities */
+/*******************/
+
+static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask)
+{
+       eeprom_chainmask &= chip_chainmask;
+       if (eeprom_chainmask)
+               return eeprom_chainmask;
+       else
+               return chip_chainmask;
+}
+
+/**
+ * ath9k_hw_dfs_tested - checks if DFS has been tested with used chipset
+ * @ah: the atheros hardware data structure
+ *
+ * We enable DFS support upstream on chipsets which have passed a series
+ * of tests. The testing requirements are going to be documented. Desired
+ * test requirements are documented at:
+ *
+ * http://wireless.kernel.org/en/users/Drivers/ath9k/dfs
+ *
+ * Once a new chipset gets properly tested an individual commit can be used
+ * to document the testing for DFS for that chipset.
+ */
+static bool ath9k_hw_dfs_tested(struct ath_hw *ah)
+{
+
+       switch (ah->hw_version.macVersion) {
+       /* AR9580 will likely be our first target to get testing on */
+       case AR_SREV_VERSION_9580:
+       default:
+               return false;
+       }
+}
+
+int ath9k_hw_fill_cap_info(struct ath_hw *ah)
+{
+       struct ath9k_hw_capabilities *pCap = &ah->caps;
+       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ath_common *common = ath9k_hw_common(ah);
+       unsigned int chip_chainmask;
+
+       u16 eeval;
+       u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
+
+       eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
+       regulatory->current_rd = eeval;
+
+       if (ah->opmode != NL80211_IFTYPE_AP &&
+           ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
+               if (regulatory->current_rd == 0x64 ||
+                   regulatory->current_rd == 0x65)
+                       regulatory->current_rd += 5;
+               else if (regulatory->current_rd == 0x41)
+                       regulatory->current_rd = 0x43;
+               ath_dbg(common, REGULATORY, "regdomain mapped to 0x%x\n",
+                       regulatory->current_rd);
+       }
+
+       eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
+       if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
+               ath_err(common,
+                       "no band has been marked as supported in EEPROM\n");
+               return -EINVAL;
+       }
+
+       if (eeval & AR5416_OPFLAGS_11A)
+               pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
+
+       if (eeval & AR5416_OPFLAGS_11G)
+               pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
+
+       if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah))
+               chip_chainmask = 1;
+       else if (AR_SREV_9462(ah))
+               chip_chainmask = 3;
+       else if (!AR_SREV_9280_20_OR_LATER(ah))
+               chip_chainmask = 7;
+       else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah))
+               chip_chainmask = 3;
+       else
+               chip_chainmask = 7;
+
+       pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
+       /*
+        * For AR9271 we will temporarilly uses the rx chainmax as read from
+        * the EEPROM.
+        */
+       if ((ah->hw_version.devid == AR5416_DEVID_PCI) &&
+           !(eeval & AR5416_OPFLAGS_11A) &&
+           !(AR_SREV_9271(ah)))
+               /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */
+               pCap->rx_chainmask = ath9k_btcoex_ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7;
+       else if (AR_SREV_9100(ah))
+               pCap->rx_chainmask = 0x7;
+       else
+               /* Use rx_chainmask from EEPROM. */
+               pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
+
+       pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
+       pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
+       ah->txchainmask = pCap->tx_chainmask;
+       ah->rxchainmask = pCap->rx_chainmask;
+
+       ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
+
+       /* enable key search for every frame in an aggregate */
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
+
+       common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
+
+       if (ah->hw_version.devid != AR2427_DEVID_PCIE)
+               pCap->hw_caps |= ATH9K_HW_CAP_HT;
+       else
+               pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
+
+       if (AR_SREV_9271(ah))
+               pCap->num_gpio_pins = AR9271_NUM_GPIO;
+       else if (AR_DEVID_7010(ah))
+               pCap->num_gpio_pins = AR7010_NUM_GPIO;
+       else if (AR_SREV_9300_20_OR_LATER(ah))
+               pCap->num_gpio_pins = AR9300_NUM_GPIO;
+       else if (AR_SREV_9287_11_OR_LATER(ah))
+               pCap->num_gpio_pins = AR9287_NUM_GPIO;
+       else if (AR_SREV_9285_12_OR_LATER(ah))
+               pCap->num_gpio_pins = AR9285_NUM_GPIO;
+       else if (AR_SREV_9280_20_OR_LATER(ah))
+               pCap->num_gpio_pins = AR928X_NUM_GPIO;
+       else
+               pCap->num_gpio_pins = AR_NUM_GPIO;
+
+       if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah))
+               pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
+       else
+               pCap->rts_aggr_limit = (8 * 1024);
+
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+       ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT);
+       if (ah->rfsilent & EEP_RFSILENT_ENABLED) {
+               ah->rfkill_gpio =
+                       MS(ah->rfsilent, EEP_RFSILENT_GPIO_SEL);
+               ah->rfkill_polarity =
+                       MS(ah->rfsilent, EEP_RFSILENT_POLARITY);
+
+               pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
+       }
+#endif
+       if (AR_SREV_9271(ah) || AR_SREV_9300_20_OR_LATER(ah))
+               pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
+       else
+               pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
+
+       if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
+               pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
+       else
+               pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
+               if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah))
+                       pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
+
+               pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
+               pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH;
+               pCap->rx_status_len = sizeof(struct ar9003_rxs);
+               pCap->tx_desc_len = sizeof(struct ar9003_txc);
+               pCap->txs_len = sizeof(struct ar9003_txs);
+               if (!ah->config.paprd_disable &&
+                   ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
+                       pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
+       } else {
+               pCap->tx_desc_len = sizeof(struct ath_desc);
+               if (AR_SREV_9280_20(ah))
+                       pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
+       }
+
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
+
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ah->ent_mode = REG_READ(ah, AR_ENT_OTP);
+
+       if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
+               pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
+
+       if (AR_SREV_9285(ah))
+               if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) {
+                       ant_div_ctl1 =
+                               ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
+                       if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1))
+                               pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
+               }
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE))
+                       pCap->hw_caps |= ATH9K_HW_CAP_APM;
+       }
+
+
+       if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
+               ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
+               /*
+                * enable the diversity-combining algorithm only when
+                * both enable_lna_div and enable_fast_div are set
+                *              Table for Diversity
+                * ant_div_alt_lnaconf          bit 0-1
+                * ant_div_main_lnaconf         bit 2-3
+                * ant_div_alt_gaintb           bit 4
+                * ant_div_main_gaintb          bit 5
+                * enable_ant_div_lnadiv        bit 6
+                * enable_ant_fast_div          bit 7
+                */
+               if ((ant_div_ctl1 >> 0x6) == 0x3)
+                       pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
+       }
+
+       if (AR_SREV_9485_10(ah)) {
+               pCap->pcie_lcr_extsync_en = true;
+               pCap->pcie_lcr_offset = 0x80;
+       }
+
+       if (ath9k_hw_dfs_tested(ah))
+               pCap->hw_caps |= ATH9K_HW_CAP_DFS;
+
+       tx_chainmask = pCap->tx_chainmask;
+       rx_chainmask = pCap->rx_chainmask;
+       while (tx_chainmask || rx_chainmask) {
+               if (tx_chainmask & BIT(0))
+                       pCap->max_txchains++;
+               if (rx_chainmask & BIT(0))
+                       pCap->max_rxchains++;
+
+               tx_chainmask >>= 1;
+               rx_chainmask >>= 1;
+       }
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               ah->enabled_cals |= TX_IQ_CAL;
+               if (AR_SREV_9485_OR_LATER(ah))
+                       ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
+       }
+
+       if (AR_SREV_9462(ah)) {
+
+               if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE))
+                       pCap->hw_caps |= ATH9K_HW_CAP_MCI;
+
+               if (AR_SREV_9462_20(ah))
+                       pCap->hw_caps |= ATH9K_HW_CAP_RTT;
+
+       }
+
+
+       return 0;
+}
+
+/****************************/
+/* GPIO / RFKILL / Antennae */
+/****************************/
+
+static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah,
+                                        u32 gpio, u32 type)
+{
+       int addr;
+       u32 gpio_shift, tmp;
+
+       if (gpio > 11)
+               addr = AR_GPIO_OUTPUT_MUX3;
+       else if (gpio > 5)
+               addr = AR_GPIO_OUTPUT_MUX2;
+       else
+               addr = AR_GPIO_OUTPUT_MUX1;
+
+       gpio_shift = (gpio % 6) * 5;
+
+       if (AR_SREV_9280_20_OR_LATER(ah)
+           || (addr != AR_GPIO_OUTPUT_MUX1)) {
+               REG_RMW(ah, addr, (type << gpio_shift),
+                       (0x1f << gpio_shift));
+       } else {
+               tmp = REG_READ(ah, addr);
+               tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
+               tmp &= ~(0x1f << gpio_shift);
+               tmp |= (type << gpio_shift);
+               REG_WRITE(ah, addr, tmp);
+       }
+}
+
+void ath9k_btcoex_ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio)
+{
+       u32 gpio_shift;
+
+       BUG_ON(gpio >= ah->caps.num_gpio_pins);
+
+       if (AR_DEVID_7010(ah)) {
+               gpio_shift = gpio;
+               REG_RMW(ah, AR7010_GPIO_OE,
+                       (AR7010_GPIO_OE_AS_INPUT << gpio_shift),
+                       (AR7010_GPIO_OE_MASK << gpio_shift));
+               return;
+       }
+
+       gpio_shift = gpio << 1;
+       REG_RMW(ah,
+               AR_GPIO_OE_OUT,
+               (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
+               (AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_cfg_gpio_input);
+
+u32 ath9k_btcoex_ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
+{
+#define MS_REG_READ(x, y) \
+       (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y)))
+
+       if (gpio >= ah->caps.num_gpio_pins)
+               return 0xffffffff;
+
+       if (AR_DEVID_7010(ah)) {
+               u32 val;
+               val = REG_READ(ah, AR7010_GPIO_IN);
+               return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0;
+       } else if (AR_SREV_9300_20_OR_LATER(ah))
+               return (MS(REG_READ(ah, AR_GPIO_IN), AR9300_GPIO_IN_VAL) &
+                       AR_GPIO_BIT(gpio)) != 0;
+       else if (AR_SREV_9271(ah))
+               return MS_REG_READ(AR9271, gpio) != 0;
+       else if (AR_SREV_9287_11_OR_LATER(ah))
+               return MS_REG_READ(AR9287, gpio) != 0;
+       else if (AR_SREV_9285_12_OR_LATER(ah))
+               return MS_REG_READ(AR9285, gpio) != 0;
+       else if (AR_SREV_9280_20_OR_LATER(ah))
+               return MS_REG_READ(AR928X, gpio) != 0;
+       else
+               return MS_REG_READ(AR, gpio) != 0;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_gpio_get);
+
+void ath9k_btcoex_ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
+                        u32 ah_signal_type)
+{
+       u32 gpio_shift;
+
+       if (AR_DEVID_7010(ah)) {
+               gpio_shift = gpio;
+               REG_RMW(ah, AR7010_GPIO_OE,
+                       (AR7010_GPIO_OE_AS_OUTPUT << gpio_shift),
+                       (AR7010_GPIO_OE_MASK << gpio_shift));
+               return;
+       }
+
+       ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
+       gpio_shift = 2 * gpio;
+       REG_RMW(ah,
+               AR_GPIO_OE_OUT,
+               (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
+               (AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_cfg_output);
+
+void ath9k_btcoex_ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
+{
+       if (AR_DEVID_7010(ah)) {
+               val = val ? 0 : 1;
+               REG_RMW(ah, AR7010_GPIO_OUT, ((val&1) << gpio),
+                       AR_GPIO_BIT(gpio));
+               return;
+       }
+
+       if (AR_SREV_9271(ah))
+               val = ~val;
+
+       REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
+               AR_GPIO_BIT(gpio));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_set_gpio);
+
+void ath9k_btcoex_ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
+{
+       REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_setantenna);
+
+/*********************/
+/* General Operation */
+/*********************/
+
+u32 ath9k_btcoex_ath9k_hw_getrxfilter(struct ath_hw *ah)
+{
+       u32 bits = REG_READ(ah, AR_RX_FILTER);
+       u32 phybits = REG_READ(ah, AR_PHY_ERR);
+
+       if (phybits & AR_PHY_ERR_RADAR)
+               bits |= ATH9K_RX_FILTER_PHYRADAR;
+       if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
+               bits |= ATH9K_RX_FILTER_PHYERR;
+
+       return bits;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_getrxfilter);
+
+void ath9k_btcoex_ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
+{
+       u32 phybits;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       if (AR_SREV_9462(ah))
+               bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
+
+       REG_WRITE(ah, AR_RX_FILTER, bits);
+
+       phybits = 0;
+       if (bits & ATH9K_RX_FILTER_PHYRADAR)
+               phybits |= AR_PHY_ERR_RADAR;
+       if (bits & ATH9K_RX_FILTER_PHYERR)
+               phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
+       REG_WRITE(ah, AR_PHY_ERR, phybits);
+
+       if (phybits)
+               REG_SET_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA);
+       else
+               REG_CLR_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_setrxfilter);
+
+bool ath9k_btcoex_ath9k_hw_phy_disable(struct ath_hw *ah)
+{
+       if (ath9k_hw_mci_is_enabled(ah))
+               ar9003_mci_bt_gain_ctrl(ah);
+
+       if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
+               return false;
+
+       ath9k_hw_init_pll(ah, NULL);
+       ah->htc_reset_init = true;
+       return true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_phy_disable);
+
+bool ath9k_btcoex_ath9k_hw_disable(struct ath_hw *ah)
+{
+       if (!ath9k_btcoex_ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+               return false;
+
+       if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD))
+               return false;
+
+       ath9k_hw_init_pll(ah, NULL);
+       return true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_disable);
+
+static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       enum eeprom_param gain_param;
+
+       if (IS_CHAN_2GHZ(chan))
+               gain_param = EEP_ANTENNA_GAIN_2G;
+       else
+               gain_param = EEP_ANTENNA_GAIN_5G;
+
+       return ah->eep_ops->get_eeprom(ah, gain_param);
+}
+
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
+                           bool test)
+{
+       struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+       struct ieee80211_channel *channel;
+       int chan_pwr, new_pwr, max_gain;
+       int ant_gain, ant_reduction = 0;
+
+       if (!chan)
+               return;
+
+       channel = chan->chan;
+       chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
+       new_pwr = min_t(int, chan_pwr, reg->power_limit);
+       max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
+
+       ant_gain = get_antenna_gain(ah, chan);
+       if (ant_gain > max_gain)
+               ant_reduction = ant_gain - max_gain;
+
+       ah->eep_ops->set_txpower(ah, chan,
+                                ath9k_regd_get_ctl(reg, chan),
+                                ant_reduction, new_pwr, test);
+}
+
+void ath9k_btcoex_ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
+{
+       struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+       struct ath9k_channel *chan = ah->curchan;
+       struct ieee80211_channel *channel = chan->chan;
+
+       reg->power_limit = min_t(u32, limit, MAX_RATE_POWER);
+       if (test)
+               channel->max_power = MAX_RATE_POWER / 2;
+
+       ath9k_hw_apply_txpower(ah, chan, test);
+
+       if (test)
+               channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_set_txpowerlimit);
+
+void ath9k_btcoex_ath9k_hw_setopmode(struct ath_hw *ah)
+{
+       ath9k_hw_set_operating_mode(ah, ah->opmode);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_setopmode);
+
+void ath9k_btcoex_ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1)
+{
+       REG_WRITE(ah, AR_MCAST_FIL0, filter0);
+       REG_WRITE(ah, AR_MCAST_FIL1, filter1);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_setmcastfilter);
+
+void ath9k_btcoex_ath9k_hw_write_associd(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(common->curbssid));
+       REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(common->curbssid + 4) |
+                 ((common->curaid & 0x3fff) << AR_BSS_ID1_AID_S));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_write_associd);
+
+#define ATH9K_MAX_TSF_READ 10
+
+u64 ath9k_btcoex_ath9k_hw_gettsf64(struct ath_hw *ah)
+{
+       u32 tsf_lower, tsf_upper1, tsf_upper2;
+       int i;
+
+       tsf_upper1 = REG_READ(ah, AR_TSF_U32);
+       for (i = 0; i < ATH9K_MAX_TSF_READ; i++) {
+               tsf_lower = REG_READ(ah, AR_TSF_L32);
+               tsf_upper2 = REG_READ(ah, AR_TSF_U32);
+               if (tsf_upper2 == tsf_upper1)
+                       break;
+               tsf_upper1 = tsf_upper2;
+       }
+
+       WARN_ON( i == ATH9K_MAX_TSF_READ );
+
+       return (((u64)tsf_upper1 << 32) | tsf_lower);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_gettsf64);
+
+void ath9k_btcoex_ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64)
+{
+       REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
+       REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_settsf64);
+
+void ath9k_btcoex_ath9k_hw_reset_tsf(struct ath_hw *ah)
+{
+       if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0,
+                          AH_TSF_WRITE_TIMEOUT))
+               ath_dbg(ath9k_hw_common(ah), RESET,
+                       "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
+
+       REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_reset_tsf);
+
+void ath9k_btcoex_ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set)
+{
+       if (set)
+               ah->misc_mode |= AR_PCU_TX_ADD_TSF;
+       else
+               ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_set_tsfadjust);
+
+void ath9k_hw_set11nmac2040(struct ath_hw *ah)
+{
+       struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+       u32 macmode;
+
+       if (conf_is_ht40(conf) && !ah->config.cwm_ignore_extcca)
+               macmode = AR_2040_JOINED_RX_CLEAR;
+       else
+               macmode = 0;
+
+       REG_WRITE(ah, AR_2040_MODE, macmode);
+}
+
+/* HW Generic timers configuration */
+
+static const struct ath_gen_timer_configuration gen_tmr_configuration[] =
+{
+       {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
+       {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
+       {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
+       {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
+       {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
+       {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
+       {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
+       {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
+       {AR_NEXT_NDP2_TIMER, AR_NDP2_PERIOD, AR_NDP2_TIMER_MODE, 0x0001},
+       {AR_NEXT_NDP2_TIMER + 1*4, AR_NDP2_PERIOD + 1*4,
+                               AR_NDP2_TIMER_MODE, 0x0002},
+       {AR_NEXT_NDP2_TIMER + 2*4, AR_NDP2_PERIOD + 2*4,
+                               AR_NDP2_TIMER_MODE, 0x0004},
+       {AR_NEXT_NDP2_TIMER + 3*4, AR_NDP2_PERIOD + 3*4,
+                               AR_NDP2_TIMER_MODE, 0x0008},
+       {AR_NEXT_NDP2_TIMER + 4*4, AR_NDP2_PERIOD + 4*4,
+                               AR_NDP2_TIMER_MODE, 0x0010},
+       {AR_NEXT_NDP2_TIMER + 5*4, AR_NDP2_PERIOD + 5*4,
+                               AR_NDP2_TIMER_MODE, 0x0020},
+       {AR_NEXT_NDP2_TIMER + 6*4, AR_NDP2_PERIOD + 6*4,
+                               AR_NDP2_TIMER_MODE, 0x0040},
+       {AR_NEXT_NDP2_TIMER + 7*4, AR_NDP2_PERIOD + 7*4,
+                               AR_NDP2_TIMER_MODE, 0x0080}
+};
+
+/* HW generic timer primitives */
+
+/* compute and clear index of rightmost 1 */
+static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask)
+{
+       u32 b;
+
+       b = *mask;
+       b &= (0-b);
+       *mask &= ~b;
+       b *= debruijn32;
+       b >>= 27;
+
+       return timer_table->gen_timer_index[b];
+}
+
+u32 ath9k_btcoex_ath9k_hw_gettsf32(struct ath_hw *ah)
+{
+       return REG_READ(ah, AR_TSF_L32);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_gettsf32);
+
+struct ath_gen_timer *ath9k_btcoex_ath_gen_timer_alloc(struct ath_hw *ah,
+                                         void (*trigger)(void *),
+                                         void (*overflow)(void *),
+                                         void *arg,
+                                         u8 timer_index)
+{
+       struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+       struct ath_gen_timer *timer;
+
+       timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
+
+       if (timer == NULL) {
+               ath_err(ath9k_hw_common(ah),
+                       "Failed to allocate memory for hw timer[%d]\n",
+                       timer_index);
+               return NULL;
+       }
+
+       /* allocate a hardware generic timer slot */
+       timer_table->timers[timer_index] = timer;
+       timer->index = timer_index;
+       timer->trigger = trigger;
+       timer->overflow = overflow;
+       timer->arg = arg;
+
+       return timer;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath_gen_timer_alloc);
+
+void ath9k_btcoex_ath9k_hw_gen_timer_start(struct ath_hw *ah,
+                             struct ath_gen_timer *timer,
+                             u32 trig_timeout,
+                             u32 timer_period)
+{
+       struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+       u32 tsf, timer_next;
+
+       BUG_ON(!timer_period);
+
+       set_bit(timer->index, &timer_table->timer_mask.timer_bits);
+
+       tsf = ath9k_btcoex_ath9k_hw_gettsf32(ah);
+
+       timer_next = tsf + trig_timeout;
+
+       ath_dbg(ath9k_hw_common(ah), HWTIMER,
+               "current tsf %x period %x timer_next %x\n",
+               tsf, timer_period, timer_next);
+
+       /*
+        * Program generic timer registers
+        */
+       REG_WRITE(ah, gen_tmr_configuration[timer->index].next_addr,
+                timer_next);
+       REG_WRITE(ah, gen_tmr_configuration[timer->index].period_addr,
+                 timer_period);
+       REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
+                   gen_tmr_configuration[timer->index].mode_mask);
+
+       if (AR_SREV_9462(ah)) {
+               /*
+                * Starting from AR9462, each generic timer can select which tsf
+                * to use. But we still follow the old rule, 0 - 7 use tsf and
+                * 8 - 15  use tsf2.
+                */
+               if ((timer->index < AR_GEN_TIMER_BANK_1_LEN))
+                       REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
+                                      (1 << timer->index));
+               else
+                       REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
+                                      (1 << timer->index));
+       }
+
+       /* Enable both trigger and thresh interrupt masks */
+       REG_SET_BIT(ah, AR_IMR_S5,
+               (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
+               SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_gen_timer_start);
+
+void ath9k_btcoex_ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
+{
+       struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+
+       if ((timer->index < AR_FIRST_NDP_TIMER) ||
+               (timer->index >= ATH_MAX_GEN_TIMER)) {
+               return;
+       }
+
+       /* Clear generic timer enable bits. */
+       REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
+                       gen_tmr_configuration[timer->index].mode_mask);
+
+       /* Disable both trigger and thresh interrupt masks */
+       REG_CLR_BIT(ah, AR_IMR_S5,
+               (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
+               SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
+
+       clear_bit(timer->index, &timer_table->timer_mask.timer_bits);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_gen_timer_stop);
+
+void ath9k_btcoex_ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer)
+{
+       struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+
+       /* free the hardware generic timer slot */
+       timer_table->timers[timer->index] = NULL;
+       kfree(timer);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath_gen_timer_free);
+
+/*
+ * Generic Timer Interrupts handling
+ */
+void ath9k_btcoex_ath_gen_timer_isr(struct ath_hw *ah)
+{
+       struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+       struct ath_gen_timer *timer;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 trigger_mask, thresh_mask, index;
+
+       /* get hardware generic timer interrupt status */
+       trigger_mask = ah->intr_gen_timer_trigger;
+       thresh_mask = ah->intr_gen_timer_thresh;
+       trigger_mask &= timer_table->timer_mask.val;
+       thresh_mask &= timer_table->timer_mask.val;
+
+       trigger_mask &= ~thresh_mask;
+
+       while (thresh_mask) {
+               index = rightmost_index(timer_table, &thresh_mask);
+               timer = timer_table->timers[index];
+               BUG_ON(!timer);
+               ath_dbg(common, HWTIMER, "TSF overflow for Gen timer %d\n",
+                       index);
+               timer->overflow(timer->arg);
+       }
+
+       while (trigger_mask) {
+               index = rightmost_index(timer_table, &trigger_mask);
+               timer = timer_table->timers[index];
+               BUG_ON(!timer);
+               ath_dbg(common, HWTIMER,
+                       "Gen timer[%d] trigger\n", index);
+               timer->trigger(timer->arg);
+       }
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath_gen_timer_isr);
+
+/********/
+/* HTC  */
+/********/
+
+static struct {
+       u32 version;
+       const char * name;
+} ath_mac_bb_names[] = {
+       /* Devices with external radios */
+       { AR_SREV_VERSION_5416_PCI,     "5416" },
+       { AR_SREV_VERSION_5416_PCIE,    "5418" },
+       { AR_SREV_VERSION_9100,         "9100" },
+       { AR_SREV_VERSION_9160,         "9160" },
+       /* Single-chip solutions */
+       { AR_SREV_VERSION_9280,         "9280" },
+       { AR_SREV_VERSION_9285,         "9285" },
+       { AR_SREV_VERSION_9287,         "9287" },
+       { AR_SREV_VERSION_9271,         "9271" },
+       { AR_SREV_VERSION_9300,         "9300" },
+       { AR_SREV_VERSION_9330,         "9330" },
+       { AR_SREV_VERSION_9340,         "9340" },
+       { AR_SREV_VERSION_9485,         "9485" },
+       { AR_SREV_VERSION_9462,         "9462" },
+};
+
+/* For devices with external radios */
+static struct {
+       u16 version;
+       const char * name;
+} ath_rf_names[] = {
+       { 0,                            "5133" },
+       { AR_RAD5133_SREV_MAJOR,        "5133" },
+       { AR_RAD5122_SREV_MAJOR,        "5122" },
+       { AR_RAD2133_SREV_MAJOR,        "2133" },
+       { AR_RAD2122_SREV_MAJOR,        "2122" }
+};
+
+/*
+ * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
+ */
+static const char *ath9k_hw_mac_bb_name(u32 mac_bb_version)
+{
+       int i;
+
+       for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
+               if (ath_mac_bb_names[i].version == mac_bb_version) {
+                       return ath_mac_bb_names[i].name;
+               }
+       }
+
+       return "????";
+}
+
+/*
+ * Return the RF name. "????" is returned if the RF is unknown.
+ * Used for devices with external radios.
+ */
+static const char *ath9k_hw_rf_name(u16 rf_version)
+{
+       int i;
+
+       for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
+               if (ath_rf_names[i].version == rf_version) {
+                       return ath_rf_names[i].name;
+               }
+       }
+
+       return "????";
+}
+
+void ath9k_btcoex_ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len)
+{
+       int used;
+
+       /* chipsets >= AR9280 are single-chip */
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               used = snprintf(hw_name, len,
+                              "Atheros AR%s Rev:%x",
+                              ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
+                              ah->hw_version.macRev);
+       }
+       else {
+               used = snprintf(hw_name, len,
+                              "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x",
+                              ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
+                              ah->hw_version.macRev,
+                              ath9k_hw_rf_name((ah->hw_version.analog5GhzRev &
+                                               AR_RADIO_SREV_MAJOR)),
+                              ah->hw_version.phyRev);
+       }
+
+       hw_name[used] = '\0';
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_name);
+
+static bool ath9k_hw_check_dcs(u32 dma_dbg, int num_dcu_states,
+                              int *hang_state, int *hang_pos)
+{
+       static u32 dcu_chain_state[] = {5, 6, 9}; /* DCU chain stuck states */
+       u32 chain_state, dcs_pos, i;
+
+       for (dcs_pos = 0; dcs_pos < num_dcu_states; dcs_pos++) {
+               chain_state = (dma_dbg >> (5 * dcs_pos)) & 0x1f;
+               for (i = 0; i < 3; i++) {
+                       if (chain_state == dcu_chain_state[i]) {
+                               *hang_state = chain_state;
+                               *hang_pos = dcs_pos;
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+#define DCU_COMPLETE_STATE        1
+#define DCU_COMPLETE_STATE_MASK 0x3
+#define NUM_STATUS_READS         50
+bool ath9k_btcoex_ath9k_hw_detect_mac_hang(struct ath_hw *ah)
+{
+       u32 chain_state, comp_state, dcs_reg = AR_DMADBG_4;
+       u32 i, hang_pos, hang_state;
+
+       comp_state = REG_READ(ah, AR_DMADBG_6);
+
+       if ((comp_state & DCU_COMPLETE_STATE_MASK) != DCU_COMPLETE_STATE) {
+               ath_dbg(ath9k_hw_common(ah), RX_STUCK,
+                       "MAC Hang signature not found at DCU complete\n");
+               return false;
+       }
+
+       chain_state = REG_READ(ah, dcs_reg);
+       if (ath9k_hw_check_dcs(chain_state, 6, &hang_state, &hang_pos))
+               goto hang_check_iter;
+
+       dcs_reg = AR_DMADBG_5;
+       chain_state = REG_READ(ah, dcs_reg);
+       if (ath9k_hw_check_dcs(chain_state, 4, &hang_state, &hang_pos))
+               goto hang_check_iter;
+
+       ath_dbg(ath9k_hw_common(ah), RX_STUCK,
+               "MAC Hang signature 1 not found\n");
+       return false;
+
+hang_check_iter:
+       ath_dbg(ath9k_hw_common(ah), RX_STUCK,
+               "DCU registers: chain %08x complete %08x Hang: state %d pos %d\n",
+               chain_state, comp_state, hang_state, hang_pos);
+
+       for (i = 0; i < NUM_STATUS_READS; i++) {
+               chain_state = REG_READ(ah, dcs_reg);
+               chain_state = (chain_state >> (5 * hang_pos)) & 0x1f;
+               comp_state = REG_READ(ah, AR_DMADBG_6);
+
+               if (((comp_state & DCU_COMPLETE_STATE_MASK) !=
+                     DCU_COMPLETE_STATE) ||
+                   (chain_state != hang_state))
+                       return false;
+       }
+
+       ath_dbg(ath9k_hw_common(ah), RX_STUCK,
+               "MAC Hang signature 1 found\n");
+
+       return true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_detect_mac_hang);
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/hw.h b/drivers/net/wireless/ath/ath9k_btcoex/hw.h
new file mode 100644 (file)
index 0000000..b1e1311
--- /dev/null
@@ -0,0 +1,1070 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HW_H
+#define HW_H
+
+#include <linux/if_ether.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "mac.h"
+#include "ani.h"
+#include "eeprom.h"
+#include "calib.h"
+#include "reg.h"
+#include "phy.h"
+#include "btcoex.h"
+
+#include "../regd.h"
+
+#define ATHEROS_VENDOR_ID      0x168c
+
+#define AR5416_DEVID_PCI       0x0023
+#define AR5416_DEVID_PCIE      0x0024
+#define AR9160_DEVID_PCI       0x0027
+#define AR9280_DEVID_PCI       0x0029
+#define AR9280_DEVID_PCIE      0x002a
+#define AR9285_DEVID_PCIE      0x002b
+#define AR2427_DEVID_PCIE      0x002c
+#define AR9287_DEVID_PCI       0x002d
+#define AR9287_DEVID_PCIE      0x002e
+#define AR9300_DEVID_PCIE      0x0030
+#define AR9300_DEVID_AR9340    0x0031
+#define AR9300_DEVID_AR9485_PCIE 0x0032
+#define AR9300_DEVID_AR9580    0x0033
+#define AR9300_DEVID_AR9462    0x0034
+#define AR9300_DEVID_AR9330    0x0035
+
+#define AR5416_AR9100_DEVID    0x000b
+
+#define        AR_SUBVENDOR_ID_NOG     0x0e11
+#define AR_SUBVENDOR_ID_NEW_A  0x7065
+#define AR5416_MAGIC           0x19641014
+
+#define AR9280_COEX2WIRE_SUBSYSID      0x309b
+#define AT9285_COEX3WIRE_SA_SUBSYSID   0x30aa
+#define AT9285_COEX3WIRE_DA_SUBSYSID   0x30ab
+
+#define ATH_AMPDU_LIMIT_MAX        (64 * 1024 - 1)
+
+#define        ATH_DEFAULT_NOISE_FLOOR -95
+
+#define ATH9K_RSSI_BAD                 -128
+
+#define ATH9K_NUM_CHANNELS     38
+
+/* Register read/write primitives */
+#define REG_WRITE(_ah, _reg, _val) \
+       (_ah)->reg_ops.write((_ah), (_val), (_reg))
+
+#define REG_READ(_ah, _reg) \
+       (_ah)->reg_ops.read((_ah), (_reg))
+
+#define REG_READ_MULTI(_ah, _addr, _val, _cnt)         \
+       (_ah)->reg_ops.multi_read((_ah), (_addr), (_val), (_cnt))
+
+#define REG_RMW(_ah, _reg, _set, _clr) \
+       (_ah)->reg_ops.rmw((_ah), (_reg), (_set), (_clr))
+
+#define ENABLE_REGWRITE_BUFFER(_ah)                                    \
+       do {                                                            \
+               if ((_ah)->reg_ops.enable_write_buffer) \
+                       (_ah)->reg_ops.enable_write_buffer((_ah)); \
+       } while (0)
+
+#define REGWRITE_BUFFER_FLUSH(_ah)                                     \
+       do {                                                            \
+               if ((_ah)->reg_ops.write_flush)         \
+                       (_ah)->reg_ops.write_flush((_ah));      \
+       } while (0)
+
+#define PR_EEP(_s, _val)                                               \
+       do {                                                            \
+               len += snprintf(buf + len, size - len, "%20s : %10d\n", \
+                               _s, (_val));                            \
+       } while (0)
+
+#define SM(_v, _f)  (((_v) << _f##_S) & _f)
+#define MS(_v, _f)  (((_v) & _f) >> _f##_S)
+#define REG_RMW_FIELD(_a, _r, _f, _v) \
+       REG_RMW(_a, _r, (((_v) << _f##_S) & _f), (_f))
+#define REG_READ_FIELD(_a, _r, _f) \
+       (((REG_READ(_a, _r) & _f) >> _f##_S))
+#define REG_SET_BIT(_a, _r, _f) \
+       REG_RMW(_a, _r, (_f), 0)
+#define REG_CLR_BIT(_a, _r, _f) \
+       REG_RMW(_a, _r, 0, (_f))
+
+#define DO_DELAY(x) do {                                       \
+               if (((++(x) % 64) == 0) &&                      \
+                   (ath9k_hw_common(ah)->bus_ops->ath_bus_type \
+                       != ATH_USB))                            \
+                       udelay(1);                              \
+       } while (0)
+
+#define REG_WRITE_ARRAY(iniarray, column, regWr) \
+       ath9k_hw_write_array(ah, iniarray, column, &(regWr))
+
+#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT             0
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     2
+#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME           3
+#define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL  4
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    5
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      6
+#define AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA      0x16
+#define AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK       0x17
+#define AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA        0x18
+#define AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK         0x19
+#define AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX           0x14
+#define AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX           0x13
+#define AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX           9
+#define AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX           8
+#define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE      0x1d
+#define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA        0x1e
+
+#define AR_GPIOD_MASK               0x00001FFF
+#define AR_GPIO_BIT(_gpio)          (1 << (_gpio))
+
+#define BASE_ACTIVATE_DELAY         100
+#define RTC_PLL_SETTLE_DELAY        (AR_SREV_9340(ah) ? 1000 : 100)
+#define COEF_SCALE_S                24
+#define HT40_CHANNEL_CENTER_SHIFT   10
+
+#define ATH9K_ANTENNA0_CHAINMASK    0x1
+#define ATH9K_ANTENNA1_CHAINMASK    0x2
+
+#define ATH9K_NUM_DMA_DEBUG_REGS    8
+#define ATH9K_NUM_QUEUES            10
+
+#define MAX_RATE_POWER              63
+#define AH_WAIT_TIMEOUT             100000 /* (us) */
+#define AH_TSF_WRITE_TIMEOUT        100    /* (us) */
+#define AH_TIME_QUANTUM             10
+#define AR_KEYTABLE_SIZE            128
+#define POWER_UP_TIME               10000
+#define SPUR_RSSI_THRESH            40
+#define UPPER_5G_SUB_BAND_START                5700
+#define MID_5G_SUB_BAND_START          5400
+
+#define CAB_TIMEOUT_VAL             10
+#define BEACON_TIMEOUT_VAL          10
+#define MIN_BEACON_TIMEOUT_VAL      1
+#define SLEEP_SLOP                  3
+
+#define INIT_CONFIG_STATUS          0x00000000
+#define INIT_RSSI_THR               0x00000700
+#define INIT_BCON_CNTRL_REG         0x00000000
+
+#define TU_TO_USEC(_tu)             ((_tu) << 10)
+
+#define ATH9K_HW_RX_HP_QDEPTH  16
+#define ATH9K_HW_RX_LP_QDEPTH  128
+
+#define PAPRD_GAIN_TABLE_ENTRIES       32
+#define PAPRD_TABLE_SZ                 24
+#define PAPRD_IDEAL_AGC2_PWR_RANGE     0xe0
+
+enum ath_hw_txq_subtype {
+       ATH_TXQ_AC_BE = 0,
+       ATH_TXQ_AC_BK = 1,
+       ATH_TXQ_AC_VI = 2,
+       ATH_TXQ_AC_VO = 3,
+};
+
+enum ath_ini_subsys {
+       ATH_INI_PRE = 0,
+       ATH_INI_CORE,
+       ATH_INI_POST,
+       ATH_INI_NUM_SPLIT,
+};
+
+enum ath9k_hw_caps {
+       ATH9K_HW_CAP_HT                         = BIT(0),
+       ATH9K_HW_CAP_RFSILENT                   = BIT(1),
+       ATH9K_HW_CAP_AUTOSLEEP                  = BIT(2),
+       ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(3),
+       ATH9K_HW_CAP_EDMA                       = BIT(4),
+       ATH9K_HW_CAP_RAC_SUPPORTED              = BIT(5),
+       ATH9K_HW_CAP_LDPC                       = BIT(6),
+       ATH9K_HW_CAP_FASTCLOCK                  = BIT(7),
+       ATH9K_HW_CAP_SGI_20                     = BIT(8),
+       ATH9K_HW_CAP_PAPRD                      = BIT(9),
+       ATH9K_HW_CAP_ANT_DIV_COMB               = BIT(10),
+       ATH9K_HW_CAP_2GHZ                       = BIT(11),
+       ATH9K_HW_CAP_5GHZ                       = BIT(12),
+       ATH9K_HW_CAP_APM                        = BIT(13),
+       ATH9K_HW_CAP_RTT                        = BIT(14),
+       ATH9K_HW_CAP_MCI                        = BIT(15),
+       ATH9K_HW_CAP_DFS                        = BIT(16),
+};
+
+struct ath9k_hw_capabilities {
+       u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
+       u16 rts_aggr_limit;
+       u8 tx_chainmask;
+       u8 rx_chainmask;
+       u8 max_txchains;
+       u8 max_rxchains;
+       u8 num_gpio_pins;
+       u8 rx_hp_qdepth;
+       u8 rx_lp_qdepth;
+       u8 rx_status_len;
+       u8 tx_desc_len;
+       u8 txs_len;
+       u16 pcie_lcr_offset;
+       bool pcie_lcr_extsync_en;
+};
+
+struct ath9k_ops_config {
+       int dma_beacon_response_time;
+       int sw_beacon_response_time;
+       int additional_swba_backoff;
+       int ack_6mb;
+       u32 cwm_ignore_extcca;
+       bool pcieSerDesWrite;
+       u8 pcie_clock_req;
+       u32 pcie_waen;
+       u8 analog_shiftreg;
+       u8 paprd_disable;
+       u32 ofdm_trig_low;
+       u32 ofdm_trig_high;
+       u32 cck_trig_high;
+       u32 cck_trig_low;
+       u32 enable_ani;
+       int serialize_regmode;
+       bool rx_intr_mitigation;
+       bool tx_intr_mitigation;
+#define SPUR_DISABLE           0
+#define SPUR_ENABLE_IOCTL      1
+#define SPUR_ENABLE_EEPROM     2
+#define AR_SPUR_5413_1         1640
+#define AR_SPUR_5413_2         1200
+#define AR_NO_SPUR             0x8000
+#define AR_BASE_FREQ_2GHZ      2300
+#define AR_BASE_FREQ_5GHZ      4900
+#define AR_SPUR_FEEQ_BOUND_HT40 19
+#define AR_SPUR_FEEQ_BOUND_HT20 10
+       int spurmode;
+       u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
+       u8 max_txtrig_level;
+       u16 ani_poll_interval; /* ANI poll interval in ms */
+};
+
+enum ath9k_int {
+       ATH9K_INT_RX = 0x00000001,
+       ATH9K_INT_RXDESC = 0x00000002,
+       ATH9K_INT_RXHP = 0x00000001,
+       ATH9K_INT_RXLP = 0x00000002,
+       ATH9K_INT_RXNOFRM = 0x00000008,
+       ATH9K_INT_RXEOL = 0x00000010,
+       ATH9K_INT_RXORN = 0x00000020,
+       ATH9K_INT_TX = 0x00000040,
+       ATH9K_INT_TXDESC = 0x00000080,
+       ATH9K_INT_TIM_TIMER = 0x00000100,
+       ATH9K_INT_MCI = 0x00000200,
+       ATH9K_INT_BB_WATCHDOG = 0x00000400,
+       ATH9K_INT_TXURN = 0x00000800,
+       ATH9K_INT_MIB = 0x00001000,
+       ATH9K_INT_RXPHY = 0x00004000,
+       ATH9K_INT_RXKCM = 0x00008000,
+       ATH9K_INT_SWBA = 0x00010000,
+       ATH9K_INT_BMISS = 0x00040000,
+       ATH9K_INT_BNR = 0x00100000,
+       ATH9K_INT_TIM = 0x00200000,
+       ATH9K_INT_DTIM = 0x00400000,
+       ATH9K_INT_DTIMSYNC = 0x00800000,
+       ATH9K_INT_GPIO = 0x01000000,
+       ATH9K_INT_CABEND = 0x02000000,
+       ATH9K_INT_TSFOOR = 0x04000000,
+       ATH9K_INT_GENTIMER = 0x08000000,
+       ATH9K_INT_CST = 0x10000000,
+       ATH9K_INT_GTT = 0x20000000,
+       ATH9K_INT_FATAL = 0x40000000,
+       ATH9K_INT_GLOBAL = 0x80000000,
+       ATH9K_INT_BMISC = ATH9K_INT_TIM |
+               ATH9K_INT_DTIM |
+               ATH9K_INT_DTIMSYNC |
+               ATH9K_INT_TSFOOR |
+               ATH9K_INT_CABEND,
+       ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM |
+               ATH9K_INT_RXDESC |
+               ATH9K_INT_RXEOL |
+               ATH9K_INT_RXORN |
+               ATH9K_INT_TXURN |
+               ATH9K_INT_TXDESC |
+               ATH9K_INT_MIB |
+               ATH9K_INT_RXPHY |
+               ATH9K_INT_RXKCM |
+               ATH9K_INT_SWBA |
+               ATH9K_INT_BMISS |
+               ATH9K_INT_GPIO,
+       ATH9K_INT_NOCARD = 0xffffffff
+};
+
+#define CHANNEL_CW_INT    0x00002
+#define CHANNEL_CCK       0x00020
+#define CHANNEL_OFDM      0x00040
+#define CHANNEL_2GHZ      0x00080
+#define CHANNEL_5GHZ      0x00100
+#define CHANNEL_PASSIVE   0x00200
+#define CHANNEL_DYN       0x00400
+#define CHANNEL_HALF      0x04000
+#define CHANNEL_QUARTER   0x08000
+#define CHANNEL_HT20      0x10000
+#define CHANNEL_HT40PLUS  0x20000
+#define CHANNEL_HT40MINUS 0x40000
+
+#define CHANNEL_A           (CHANNEL_5GHZ|CHANNEL_OFDM)
+#define CHANNEL_B           (CHANNEL_2GHZ|CHANNEL_CCK)
+#define CHANNEL_G           (CHANNEL_2GHZ|CHANNEL_OFDM)
+#define CHANNEL_G_HT20      (CHANNEL_2GHZ|CHANNEL_HT20)
+#define CHANNEL_A_HT20      (CHANNEL_5GHZ|CHANNEL_HT20)
+#define CHANNEL_G_HT40PLUS  (CHANNEL_2GHZ|CHANNEL_HT40PLUS)
+#define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS)
+#define CHANNEL_A_HT40PLUS  (CHANNEL_5GHZ|CHANNEL_HT40PLUS)
+#define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS)
+#define CHANNEL_ALL                            \
+       (CHANNEL_OFDM|                          \
+        CHANNEL_CCK|                           \
+        CHANNEL_2GHZ |                         \
+        CHANNEL_5GHZ |                         \
+        CHANNEL_HT20 |                         \
+        CHANNEL_HT40PLUS |                     \
+        CHANNEL_HT40MINUS)
+
+#define MAX_RTT_TABLE_ENTRY     6
+#define MAX_IQCAL_MEASUREMENT  8
+#define MAX_CL_TAB_ENTRY       16
+
+struct ath9k_hw_cal_data {
+       u16 channel;
+       u32 channelFlags;
+       int32_t CalValid;
+       int8_t iCoff;
+       int8_t qCoff;
+       bool rtt_done;
+       bool paprd_done;
+       bool nfcal_pending;
+       bool nfcal_interference;
+       bool done_txiqcal_once;
+       bool done_txclcal_once;
+       u16 small_signal_gain[AR9300_MAX_CHAINS];
+       u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
+       u32 num_measures[AR9300_MAX_CHAINS];
+       int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS];
+       u32 tx_clcal[AR9300_MAX_CHAINS][MAX_CL_TAB_ENTRY];
+       u32 rtt_table[AR9300_MAX_CHAINS][MAX_RTT_TABLE_ENTRY];
+       struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
+};
+
+struct ath9k_channel {
+       struct ieee80211_channel *chan;
+       struct ar5416AniState ani;
+       u16 channel;
+       u32 channelFlags;
+       u32 chanmode;
+       s16 noisefloor;
+};
+
+#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
+       (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
+       (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
+       (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS))
+#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
+#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
+#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
+#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
+#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
+#define IS_CHAN_A_FAST_CLOCK(_ah, _c)                  \
+       ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) &&  \
+        ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK))
+
+/* These macros check chanmode and not channelFlags */
+#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
+#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) ||        \
+                         ((_c)->chanmode == CHANNEL_G_HT20))
+#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) ||    \
+                         ((_c)->chanmode == CHANNEL_A_HT40MINUS) ||    \
+                         ((_c)->chanmode == CHANNEL_G_HT40PLUS) ||     \
+                         ((_c)->chanmode == CHANNEL_G_HT40MINUS))
+#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c)))
+
+enum ath9k_power_mode {
+       ATH9K_PM_AWAKE = 0,
+       ATH9K_PM_FULL_SLEEP,
+       ATH9K_PM_NETWORK_SLEEP,
+       ATH9K_PM_UNDEFINED
+};
+
+enum ser_reg_mode {
+       SER_REG_MODE_OFF = 0,
+       SER_REG_MODE_ON = 1,
+       SER_REG_MODE_AUTO = 2,
+};
+
+enum ath9k_rx_qtype {
+       ATH9K_RX_QUEUE_HP,
+       ATH9K_RX_QUEUE_LP,
+       ATH9K_RX_QUEUE_MAX,
+};
+
+struct ath9k_beacon_state {
+       u32 bs_nexttbtt;
+       u32 bs_nextdtim;
+       u32 bs_intval;
+#define ATH9K_TSFOOR_THRESHOLD    0x00004240 /* 16k us */
+       u32 bs_dtimperiod;
+       u16 bs_cfpperiod;
+       u16 bs_cfpmaxduration;
+       u32 bs_cfpnext;
+       u16 bs_timoffset;
+       u16 bs_bmissthreshold;
+       u32 bs_sleepduration;
+       u32 bs_tsfoor_threshold;
+};
+
+struct chan_centers {
+       u16 synth_center;
+       u16 ctl_center;
+       u16 ext_center;
+};
+
+enum {
+       ATH9K_RESET_POWER_ON,
+       ATH9K_RESET_WARM,
+       ATH9K_RESET_COLD,
+};
+
+struct ath9k_hw_version {
+       u32 magic;
+       u16 devid;
+       u16 subvendorid;
+       u32 macVersion;
+       u16 macRev;
+       u16 phyRev;
+       u16 analog5GhzRev;
+       u16 analog2GhzRev;
+       enum ath_usb_dev usbdev;
+};
+
+/* Generic TSF timer definitions */
+
+#define ATH_MAX_GEN_TIMER      16
+
+#define AR_GENTMR_BIT(_index)  (1 << (_index))
+
+/*
+ * Using de Bruijin sequence to look up 1's index in a 32 bit number
+ * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
+ */
+#define debruijn32 0x077CB531U
+
+struct ath_gen_timer_configuration {
+       u32 next_addr;
+       u32 period_addr;
+       u32 mode_addr;
+       u32 mode_mask;
+};
+
+struct ath_gen_timer {
+       void (*trigger)(void *arg);
+       void (*overflow)(void *arg);
+       void *arg;
+       u8 index;
+};
+
+struct ath_gen_timer_table {
+       u32 gen_timer_index[32];
+       struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER];
+       union {
+               unsigned long timer_bits;
+               u16 val;
+       } timer_mask;
+};
+
+struct ath_hw_antcomb_conf {
+       u8 main_lna_conf;
+       u8 alt_lna_conf;
+       u8 fast_div_bias;
+       u8 main_gaintb;
+       u8 alt_gaintb;
+       int lna1_lna2_delta;
+       u8 div_group;
+};
+
+/**
+ * struct ath_hw_radar_conf - radar detection initialization parameters
+ *
+ * @pulse_inband: threshold for checking the ratio of in-band power
+ *     to total power for short radar pulses (half dB steps)
+ * @pulse_inband_step: threshold for checking an in-band power to total
+ *     power ratio increase for short radar pulses (half dB steps)
+ * @pulse_height: threshold for detecting the beginning of a short
+ *     radar pulse (dB step)
+ * @pulse_rssi: threshold for detecting if a short radar pulse is
+ *     gone (dB step)
+ * @pulse_maxlen: maximum pulse length (0.8 us steps)
+ *
+ * @radar_rssi: RSSI threshold for starting long radar detection (dB steps)
+ * @radar_inband: threshold for checking the ratio of in-band power
+ *     to total power for long radar pulses (half dB steps)
+ * @fir_power: threshold for detecting the end of a long radar pulse (dB)
+ *
+ * @ext_channel: enable extension channel radar detection
+ */
+struct ath_hw_radar_conf {
+       unsigned int pulse_inband;
+       unsigned int pulse_inband_step;
+       unsigned int pulse_height;
+       unsigned int pulse_rssi;
+       unsigned int pulse_maxlen;
+
+       unsigned int radar_rssi;
+       unsigned int radar_inband;
+       int fir_power;
+
+       bool ext_channel;
+};
+
+/**
+ * struct ath_hw_private_ops - callbacks used internally by hardware code
+ *
+ * This structure contains private callbacks designed to only be used internally
+ * by the hardware core.
+ *
+ * @init_cal_settings: setup types of calibrations supported
+ * @init_cal: starts actual calibration
+ *
+ * @init_mode_regs: Initializes mode registers
+ * @init_mode_gain_regs: Initialize TX/RX gain registers
+ *
+ * @rf_set_freq: change frequency
+ * @spur_mitigate_freq: spur mitigation
+ * @rf_alloc_ext_banks:
+ * @rf_free_ext_banks:
+ * @set_rf_regs:
+ * @compute_pll_control: compute the PLL control value to use for
+ *     AR_RTC_PLL_CONTROL for a given channel
+ * @setup_calibration: set up calibration
+ * @iscal_supported: used to query if a type of calibration is supported
+ *
+ * @ani_cache_ini_regs: cache the values for ANI from the initial
+ *     register settings through the register initialization.
+ */
+struct ath_hw_private_ops {
+       /* Calibration ops */
+       void (*init_cal_settings)(struct ath_hw *ah);
+       bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan);
+
+       void (*init_mode_regs)(struct ath_hw *ah);
+       void (*init_mode_gain_regs)(struct ath_hw *ah);
+       void (*setup_calibration)(struct ath_hw *ah,
+                                 struct ath9k_cal_list *currCal);
+
+       /* PHY ops */
+       int (*rf_set_freq)(struct ath_hw *ah,
+                          struct ath9k_channel *chan);
+       void (*spur_mitigate_freq)(struct ath_hw *ah,
+                                  struct ath9k_channel *chan);
+       int (*rf_alloc_ext_banks)(struct ath_hw *ah);
+       void (*rf_free_ext_banks)(struct ath_hw *ah);
+       bool (*set_rf_regs)(struct ath_hw *ah,
+                           struct ath9k_channel *chan,
+                           u16 modesIndex);
+       void (*set_channel_regs)(struct ath_hw *ah, struct ath9k_channel *chan);
+       void (*init_bb)(struct ath_hw *ah,
+                       struct ath9k_channel *chan);
+       int (*process_ini)(struct ath_hw *ah, struct ath9k_channel *chan);
+       void (*olc_init)(struct ath_hw *ah);
+       void (*set_rfmode)(struct ath_hw *ah, struct ath9k_channel *chan);
+       void (*mark_phy_inactive)(struct ath_hw *ah);
+       void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan);
+       bool (*rfbus_req)(struct ath_hw *ah);
+       void (*rfbus_done)(struct ath_hw *ah);
+       void (*restore_chainmask)(struct ath_hw *ah);
+       u32 (*compute_pll_control)(struct ath_hw *ah,
+                                  struct ath9k_channel *chan);
+       bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
+                           int param);
+       void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
+       void (*set_radar_params)(struct ath_hw *ah,
+                                struct ath_hw_radar_conf *conf);
+       int (*fast_chan_change)(struct ath_hw *ah, struct ath9k_channel *chan,
+                               u8 *ini_reloaded);
+
+       /* ANI */
+       void (*ani_cache_ini_regs)(struct ath_hw *ah);
+};
+
+/**
+ * struct ath_hw_ops - callbacks used by hardware code and driver code
+ *
+ * This structure contains callbacks designed to to be used internally by
+ * hardware code and also by the lower level driver.
+ *
+ * @config_pci_powersave:
+ * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
+ */
+struct ath_hw_ops {
+       void (*config_pci_powersave)(struct ath_hw *ah,
+                                    bool power_off);
+       void (*rx_enable)(struct ath_hw *ah);
+       void (*set_desc_link)(void *ds, u32 link);
+       bool (*calibrate)(struct ath_hw *ah,
+                         struct ath9k_channel *chan,
+                         u8 rxchainmask,
+                         bool longcal);
+       bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
+       void (*set_txdesc)(struct ath_hw *ah, void *ds,
+                          struct ath_tx_info *i);
+       int (*proc_txdesc)(struct ath_hw *ah, void *ds,
+                          struct ath_tx_status *ts);
+       void (*antdiv_comb_conf_get)(struct ath_hw *ah,
+                       struct ath_hw_antcomb_conf *antconf);
+       void (*antdiv_comb_conf_set)(struct ath_hw *ah,
+                       struct ath_hw_antcomb_conf *antconf);
+
+};
+
+struct ath_nf_limits {
+       s16 max;
+       s16 min;
+       s16 nominal;
+};
+
+enum ath_cal_list {
+       TX_IQ_CAL         =     BIT(0),
+       TX_IQ_ON_AGC_CAL  =     BIT(1),
+       TX_CL_CAL         =     BIT(2),
+};
+
+/* ah_flags */
+#define AH_USE_EEPROM   0x1
+#define AH_UNPLUGGED    0x2 /* The card has been physically removed. */
+#define AH_FASTCC       0x4
+
+struct ath_hw {
+       struct ath_ops reg_ops;
+
+       struct ieee80211_hw *hw;
+       struct ath_common common;
+       struct ath9k_hw_version hw_version;
+       struct ath9k_ops_config config;
+       struct ath9k_hw_capabilities caps;
+       struct ath9k_channel channels[ATH9K_NUM_CHANNELS];
+       struct ath9k_channel *curchan;
+
+       union {
+               struct ar5416_eeprom_def def;
+               struct ar5416_eeprom_4k map4k;
+               struct ar9287_eeprom map9287;
+               struct ar9300_eeprom ar9300_eep;
+       } eeprom;
+       const struct eeprom_ops *eep_ops;
+
+       bool sw_mgmt_crypto;
+       bool is_pciexpress;
+       bool aspm_enabled;
+       bool is_monitoring;
+       bool need_an_top2_fixup;
+       u16 tx_trig_level;
+
+       u32 nf_regs[6];
+       struct ath_nf_limits nf_2g;
+       struct ath_nf_limits nf_5g;
+       u16 rfsilent;
+       u32 rfkill_gpio;
+       u32 rfkill_polarity;
+       u32 ah_flags;
+
+       bool htc_reset_init;
+
+       enum nl80211_iftype opmode;
+       enum ath9k_power_mode power_mode;
+
+       s8 noise;
+       struct ath9k_hw_cal_data *caldata;
+       struct ath9k_pacal_info pacal_info;
+       struct ar5416Stats stats;
+       struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
+
+       int16_t curchan_rad_index;
+       enum ath9k_int imask;
+       u32 imrs2_reg;
+       u32 txok_interrupt_mask;
+       u32 txerr_interrupt_mask;
+       u32 txdesc_interrupt_mask;
+       u32 txeol_interrupt_mask;
+       u32 txurn_interrupt_mask;
+       atomic_t intr_ref_cnt;
+       bool chip_fullsleep;
+       u32 atim_window;
+       u32 modes_index;
+
+       /* Calibration */
+       u32 supp_cals;
+       struct ath9k_cal_list iq_caldata;
+       struct ath9k_cal_list adcgain_caldata;
+       struct ath9k_cal_list adcdc_caldata;
+       struct ath9k_cal_list tempCompCalData;
+       struct ath9k_cal_list *cal_list;
+       struct ath9k_cal_list *cal_list_last;
+       struct ath9k_cal_list *cal_list_curr;
+#define totalPowerMeasI meas0.unsign
+#define totalPowerMeasQ meas1.unsign
+#define totalIqCorrMeas meas2.sign
+#define totalAdcIOddPhase  meas0.unsign
+#define totalAdcIEvenPhase meas1.unsign
+#define totalAdcQOddPhase  meas2.unsign
+#define totalAdcQEvenPhase meas3.unsign
+#define totalAdcDcOffsetIOddPhase  meas0.sign
+#define totalAdcDcOffsetIEvenPhase meas1.sign
+#define totalAdcDcOffsetQOddPhase  meas2.sign
+#define totalAdcDcOffsetQEvenPhase meas3.sign
+       union {
+               u32 unsign[AR5416_MAX_CHAINS];
+               int32_t sign[AR5416_MAX_CHAINS];
+       } meas0;
+       union {
+               u32 unsign[AR5416_MAX_CHAINS];
+               int32_t sign[AR5416_MAX_CHAINS];
+       } meas1;
+       union {
+               u32 unsign[AR5416_MAX_CHAINS];
+               int32_t sign[AR5416_MAX_CHAINS];
+       } meas2;
+       union {
+               u32 unsign[AR5416_MAX_CHAINS];
+               int32_t sign[AR5416_MAX_CHAINS];
+       } meas3;
+       u16 cal_samples;
+       u8 enabled_cals;
+
+       u32 sta_id1_defaults;
+       u32 misc_mode;
+       enum {
+               AUTO_32KHZ,
+               USE_32KHZ,
+               DONT_USE_32KHZ,
+       } enable_32kHz_clock;
+
+       /* Private to hardware code */
+       struct ath_hw_private_ops private_ops;
+       /* Accessed by the lower level driver */
+       struct ath_hw_ops ops;
+
+       /* Used to program the radio on non single-chip devices */
+       u32 *analogBank0Data;
+       u32 *analogBank1Data;
+       u32 *analogBank2Data;
+       u32 *analogBank3Data;
+       u32 *analogBank6Data;
+       u32 *analogBank6TPCData;
+       u32 *analogBank7Data;
+       u32 *bank6Temp;
+
+       u8 txpower_limit;
+       int coverage_class;
+       u32 slottime;
+       u32 globaltxtimeout;
+
+       /* ANI */
+       u32 proc_phyerr;
+       u32 aniperiod;
+       int totalSizeDesired[5];
+       int coarse_high[5];
+       int coarse_low[5];
+       int firpwr[5];
+       enum ath9k_ani_cmd ani_function;
+
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+       struct ath_btcoex_hw btcoex_hw;
+#endif
+
+       u32 intr_txqs;
+       u8 txchainmask;
+       u8 rxchainmask;
+
+       struct ath_hw_radar_conf radar_conf;
+
+       u32 originalGain[22];
+       int initPDADC;
+       int PDADCdelta;
+       int led_pin;
+       u32 gpio_mask;
+       u32 gpio_val;
+
+       struct ar5416IniArray iniModes;
+       struct ar5416IniArray iniCommon;
+       struct ar5416IniArray iniBank0;
+       struct ar5416IniArray iniBB_RfGain;
+       struct ar5416IniArray iniBank1;
+       struct ar5416IniArray iniBank2;
+       struct ar5416IniArray iniBank3;
+       struct ar5416IniArray iniBank6;
+       struct ar5416IniArray iniBank6TPC;
+       struct ar5416IniArray iniBank7;
+       struct ar5416IniArray iniAddac;
+       struct ar5416IniArray iniPcieSerdes;
+       struct ar5416IniArray iniPcieSerdesLowPower;
+       struct ar5416IniArray iniModesFastClock;
+       struct ar5416IniArray iniAdditional;
+       struct ar5416IniArray iniModesRxGain;
+       struct ar5416IniArray iniModesTxGain;
+       struct ar5416IniArray iniCckfirNormal;
+       struct ar5416IniArray iniCckfirJapan2484;
+       struct ar5416IniArray ini_japan2484;
+       struct ar5416IniArray iniModes_9271_ANI_reg;
+       struct ar5416IniArray ini_radio_post_sys2ant;
+
+       struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT];
+       struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT];
+       struct ar5416IniArray iniRadio[ATH_INI_NUM_SPLIT];
+       struct ar5416IniArray iniSOC[ATH_INI_NUM_SPLIT];
+
+       u32 intr_gen_timer_trigger;
+       u32 intr_gen_timer_thresh;
+       struct ath_gen_timer_table hw_gen_timers;
+
+       struct ar9003_txs *ts_ring;
+       void *ts_start;
+       u32 ts_paddr_start;
+       u32 ts_paddr_end;
+       u16 ts_tail;
+       u16 ts_size;
+
+       u32 bb_watchdog_last_status;
+       u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */
+       u8 bb_hang_rx_ofdm; /* true if bb hang due to rx_ofdm */
+
+       unsigned int paprd_target_power;
+       unsigned int paprd_training_power;
+       unsigned int paprd_ratemask;
+       unsigned int paprd_ratemask_ht40;
+       bool paprd_table_write_done;
+       u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
+       u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
+       /*
+        * Store the permanent value of Reg 0x4004in WARegVal
+        * so we dont have to R/M/W. We should not be reading
+        * this register when in sleep states.
+        */
+       u32 WARegVal;
+
+       /* Enterprise mode cap */
+       u32 ent_mode;
+
+       bool is_clk_25mhz;
+       int (*get_mac_revision)(void);
+       int (*external_reset)(void);
+};
+
+struct ath_bus_ops {
+       enum ath_bus_type ath_bus_type;
+       void (*read_cachesize)(struct ath_common *common, int *csz);
+       bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
+       void (*bt_coex_prep)(struct ath_common *common);
+       void (*extn_synch_en)(struct ath_common *common);
+       void (*aspm_init)(struct ath_common *common);
+};
+
+static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
+{
+       return &ah->common;
+}
+
+static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)
+{
+       return &(ath9k_hw_common(ah)->regulatory);
+}
+
+static inline struct ath_hw_private_ops *ath9k_hw_private_ops(struct ath_hw *ah)
+{
+       return &ah->private_ops;
+}
+
+static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah)
+{
+       return &ah->ops;
+}
+
+static inline u8 get_streams(int mask)
+{
+       return !!(mask & BIT(0)) + !!(mask & BIT(1)) + !!(mask & BIT(2));
+}
+
+/* Initialization, Detach, Reset */
+const char *ath9k_hw_probe(u16 vendorid, u16 devid);
+void ath9k_btcoex_ath9k_hw_deinit(struct ath_hw *ah);
+int ath9k_btcoex_ath9k_hw_init(struct ath_hw *ah);
+int ath9k_btcoex_ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+                  struct ath9k_hw_cal_data *caldata, bool fastcc);
+int ath9k_hw_fill_cap_info(struct ath_hw *ah);
+u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
+
+/* GPIO / RFKILL / Antennae */
+void ath9k_btcoex_ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);
+u32 ath9k_btcoex_ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
+void ath9k_btcoex_ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
+                        u32 ah_signal_type);
+void ath9k_btcoex_ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
+void ath9k_btcoex_ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
+
+/* General Operation */
+bool ath9k_btcoex_ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
+void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
+                         int column, unsigned int *writecnt);
+u32 ath9k_hw_reverse_bits(u32 val, u32 n);
+u16 ath9k_btcoex_ath9k_hw_computetxtime(struct ath_hw *ah,
+                          u8 phy, int kbps,
+                          u32 frameLen, u16 rateix, bool shortPreamble);
+void ath9k_hw_get_channel_centers(struct ath_hw *ah,
+                                 struct ath9k_channel *chan,
+                                 struct chan_centers *centers);
+u32 ath9k_btcoex_ath9k_hw_getrxfilter(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
+bool ath9k_btcoex_ath9k_hw_phy_disable(struct ath_hw *ah);
+bool ath9k_btcoex_ath9k_hw_disable(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test);
+void ath9k_btcoex_ath9k_hw_setopmode(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
+void ath9k_btcoex_ath9k_hw_write_associd(struct ath_hw *ah);
+u32 ath9k_btcoex_ath9k_hw_gettsf32(struct ath_hw *ah);
+u64 ath9k_btcoex_ath9k_hw_gettsf64(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
+void ath9k_btcoex_ath9k_hw_reset_tsf(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set);
+void ath9k_btcoex_ath9k_hw_init_global_settings(struct ath_hw *ah);
+u32 ath9k_btcoex_ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
+void ath9k_hw_set11nmac2040(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
+void ath9k_btcoex_ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
+                                   const struct ath9k_beacon_state *bs);
+bool ath9k_btcoex_ath9k_hw_check_alive(struct ath_hw *ah);
+
+bool ath9k_btcoex_ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
+
+/* Generic hw timer primitives */
+struct ath_gen_timer *ath9k_btcoex_ath_gen_timer_alloc(struct ath_hw *ah,
+                                         void (*trigger)(void *),
+                                         void (*overflow)(void *),
+                                         void *arg,
+                                         u8 timer_index);
+void ath9k_btcoex_ath9k_hw_gen_timer_start(struct ath_hw *ah,
+                             struct ath_gen_timer *timer,
+                             u32 timer_next,
+                             u32 timer_period);
+void ath9k_btcoex_ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer);
+
+void ath9k_btcoex_ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
+void ath9k_btcoex_ath_gen_timer_isr(struct ath_hw *hw);
+
+void ath9k_btcoex_ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
+
+/* PHY */
+void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
+                                  u32 *coef_mantissa, u32 *coef_exponent);
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
+                           bool test);
+
+/*
+ * Code Specific to AR5008, AR9001 or AR9002,
+ * we stuff these here to avoid callbacks for AR9003.
+ */
+int ar9002_hw_rf_claim(struct ath_hw *ah);
+void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
+
+/*
+ * Code specific to AR9003, we stuff these here to avoid callbacks
+ * for older families
+ */
+void ar9003_hw_bb_watchdog_config(struct ath_hw *ah);
+void ar9003_hw_bb_watchdog_read(struct ath_hw *ah);
+void ath9k_btcoex_ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah);
+void ath9k_btcoex_ar9003_hw_disable_phy_restart(struct ath_hw *ah);
+void ath9k_btcoex_ar9003_hw_dump_ani_reg(struct ath_hw *ah);
+void ath9k_btcoex_ar9003_paprd_enable(struct ath_hw *ah, bool val);
+void ath9k_btcoex_ar9003_paprd_populate_single_table(struct ath_hw *ah,
+                                       struct ath9k_hw_cal_data *caldata,
+                                       int chain);
+int ath9k_btcoex_ar9003_paprd_create_curve(struct ath_hw *ah,
+                             struct ath9k_hw_cal_data *caldata, int chain);
+int ath9k_btcoex_ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain);
+int ath9k_btcoex_ar9003_paprd_init_table(struct ath_hw *ah);
+bool ath9k_btcoex_ar9003_paprd_is_done(struct ath_hw *ah);
+void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains);
+
+/* Hardware family op attach helpers */
+void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
+void ar9002_hw_attach_phy_ops(struct ath_hw *ah);
+void ar9003_hw_attach_phy_ops(struct ath_hw *ah);
+
+void ar9002_hw_attach_calib_ops(struct ath_hw *ah);
+void ar9003_hw_attach_calib_ops(struct ath_hw *ah);
+
+void ar9002_hw_attach_ops(struct ath_hw *ah);
+void ar9003_hw_attach_ops(struct ath_hw *ah);
+
+void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
+bool ath9k_btcoex_ath9k_hw_detect_mac_hang(struct ath_hw *ah);
+
+void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
+void ath9k_btcoex_ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
+
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah)
+{
+       return ah->btcoex_hw.enabled;
+}
+static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah)
+{
+       return ah->common.btcoex_enabled &&
+              (ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
+
+}
+void ath9k_btcoex_ath9k_hw_btcoex_enable(struct ath_hw *ah);
+static inline enum ath_btcoex_scheme
+ath9k_hw_get_btcoex_scheme(struct ath_hw *ah)
+{
+       return ah->btcoex_hw.scheme;
+}
+#else
+static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah)
+{
+       return false;
+}
+static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah)
+{
+       return false;
+}
+static inline void ath9k_btcoex_ath9k_hw_btcoex_enable(struct ath_hw *ah)
+{
+}
+static inline enum ath_btcoex_scheme
+ath9k_hw_get_btcoex_scheme(struct ath_hw *ah)
+{
+       return ATH_BTCOEX_CFG_NONE;
+}
+#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
+
+#define ATH9K_CLOCK_RATE_CCK           22
+#define ATH9K_CLOCK_RATE_5GHZ_OFDM     40
+#define ATH9K_CLOCK_RATE_2GHZ_OFDM     44
+#define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44
+
+#endif
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/init.c b/drivers/net/wireless/ath/ath9k_btcoex/init.c
new file mode 100644 (file)
index 0000000..f767585
--- /dev/null
@@ -0,0 +1,936 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/ath9k_platform.h>
+#include <linux/module.h>
+
+#include "ath9k.h"
+
+static char *dev_info = "ath9k";
+
+MODULE_AUTHOR("Atheros Communications");
+MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
+MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
+module_param_named(debug, ath9k_debug, uint, 0);
+MODULE_PARM_DESC(debug, "Debugging mask");
+
+int ath9k_modparam_nohwcrypt;
+module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
+
+int led_blink;
+module_param_named(blink, led_blink, int, 0444);
+MODULE_PARM_DESC(blink, "Enable LED blink on activity");
+
+static int ath9k_btcoex_enable;
+module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
+MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
+
+bool is_ath9k_unloaded;
+/* We use the hw_value as an index into our private channel structure */
+
+#define CHAN2G(_freq, _idx)  { \
+       .band = IEEE80211_BAND_2GHZ, \
+       .center_freq = (_freq), \
+       .hw_value = (_idx), \
+       .max_power = 20, \
+}
+
+#define CHAN5G(_freq, _idx) { \
+       .band = IEEE80211_BAND_5GHZ, \
+       .center_freq = (_freq), \
+       .hw_value = (_idx), \
+       .max_power = 20, \
+}
+
+/* Some 2 GHz radios are actually tunable on 2312-2732
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
+       CHAN2G(2412, 0), /* Channel 1 */
+       CHAN2G(2417, 1), /* Channel 2 */
+       CHAN2G(2422, 2), /* Channel 3 */
+       CHAN2G(2427, 3), /* Channel 4 */
+       CHAN2G(2432, 4), /* Channel 5 */
+       CHAN2G(2437, 5), /* Channel 6 */
+       CHAN2G(2442, 6), /* Channel 7 */
+       CHAN2G(2447, 7), /* Channel 8 */
+       CHAN2G(2452, 8), /* Channel 9 */
+       CHAN2G(2457, 9), /* Channel 10 */
+       CHAN2G(2462, 10), /* Channel 11 */
+       CHAN2G(2467, 11), /* Channel 12 */
+       CHAN2G(2472, 12), /* Channel 13 */
+       CHAN2G(2484, 13), /* Channel 14 */
+};
+
+/* Some 5 GHz radios are actually tunable on XXXX-YYYY
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
+       /* _We_ call this UNII 1 */
+       CHAN5G(5180, 14), /* Channel 36 */
+       CHAN5G(5200, 15), /* Channel 40 */
+       CHAN5G(5220, 16), /* Channel 44 */
+       CHAN5G(5240, 17), /* Channel 48 */
+       /* _We_ call this UNII 2 */
+       CHAN5G(5260, 18), /* Channel 52 */
+       CHAN5G(5280, 19), /* Channel 56 */
+       CHAN5G(5300, 20), /* Channel 60 */
+       CHAN5G(5320, 21), /* Channel 64 */
+       /* _We_ call this "Middle band" */
+       CHAN5G(5500, 22), /* Channel 100 */
+       CHAN5G(5520, 23), /* Channel 104 */
+       CHAN5G(5540, 24), /* Channel 108 */
+       CHAN5G(5560, 25), /* Channel 112 */
+       CHAN5G(5580, 26), /* Channel 116 */
+       CHAN5G(5600, 27), /* Channel 120 */
+       CHAN5G(5620, 28), /* Channel 124 */
+       CHAN5G(5640, 29), /* Channel 128 */
+       CHAN5G(5660, 30), /* Channel 132 */
+       CHAN5G(5680, 31), /* Channel 136 */
+       CHAN5G(5700, 32), /* Channel 140 */
+       /* _We_ call this UNII 3 */
+       CHAN5G(5745, 33), /* Channel 149 */
+       CHAN5G(5765, 34), /* Channel 153 */
+       CHAN5G(5785, 35), /* Channel 157 */
+       CHAN5G(5805, 36), /* Channel 161 */
+       CHAN5G(5825, 37), /* Channel 165 */
+};
+
+/* Atheros hardware rate code addition for short premble */
+#define SHPCHECK(__hw_rate, __flags) \
+       ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
+
+#define RATE(_bitrate, _hw_rate, _flags) {              \
+       .bitrate        = (_bitrate),                   \
+       .flags          = (_flags),                     \
+       .hw_value       = (_hw_rate),                   \
+       .hw_value_short = (SHPCHECK(_hw_rate, _flags))  \
+}
+
+static struct ieee80211_rate ath9k_legacy_rates[] = {
+       RATE(10, 0x1b, 0),
+       RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE),
+       RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE),
+       RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE),
+       RATE(60, 0x0b, 0),
+       RATE(90, 0x0f, 0),
+       RATE(120, 0x0a, 0),
+       RATE(180, 0x0e, 0),
+       RATE(240, 0x09, 0),
+       RATE(360, 0x0d, 0),
+       RATE(480, 0x08, 0),
+       RATE(540, 0x0c, 0),
+};
+
+#ifdef CONFIG_MAC80211_LEDS
+static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = {
+       { .throughput = 0 * 1024, .blink_time = 334 },
+       { .throughput = 1 * 1024, .blink_time = 260 },
+       { .throughput = 5 * 1024, .blink_time = 220 },
+       { .throughput = 10 * 1024, .blink_time = 190 },
+       { .throughput = 20 * 1024, .blink_time = 170 },
+       { .throughput = 50 * 1024, .blink_time = 150 },
+       { .throughput = 70 * 1024, .blink_time = 130 },
+       { .throughput = 100 * 1024, .blink_time = 110 },
+       { .throughput = 200 * 1024, .blink_time = 80 },
+       { .throughput = 300 * 1024, .blink_time = 50 },
+};
+#endif
+
+static void ath9k_deinit_softc(struct ath_softc *sc);
+
+/*
+ * Read and write, they both share the same lock. We do this to serialize
+ * reads and writes on Atheros 802.11n PCI devices only. This is required
+ * as the FIFO on these devices can only accept sanely 2 requests.
+ */
+
+static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
+{
+       struct ath_hw *ah = (struct ath_hw *) hw_priv;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+       if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
+               unsigned long flags;
+               spin_lock_irqsave(&sc->sc_serial_rw, flags);
+               iowrite32(val, sc->mem + reg_offset);
+               spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
+       } else
+               iowrite32(val, sc->mem + reg_offset);
+}
+
+static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
+{
+       struct ath_hw *ah = (struct ath_hw *) hw_priv;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+       u32 val;
+
+       if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
+               unsigned long flags;
+               spin_lock_irqsave(&sc->sc_serial_rw, flags);
+               val = ioread32(sc->mem + reg_offset);
+               spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
+       } else
+               val = ioread32(sc->mem + reg_offset);
+       return val;
+}
+
+static unsigned int __ath9k_reg_rmw(struct ath_softc *sc, u32 reg_offset,
+                                   u32 set, u32 clr)
+{
+       u32 val;
+
+       val = ioread32(sc->mem + reg_offset);
+       val &= ~clr;
+       val |= set;
+       iowrite32(val, sc->mem + reg_offset);
+
+       return val;
+}
+
+static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
+{
+       struct ath_hw *ah = (struct ath_hw *) hw_priv;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+       unsigned long uninitialized_var(flags);
+       u32 val;
+
+       if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
+               spin_lock_irqsave(&sc->sc_serial_rw, flags);
+               val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
+               spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
+       } else
+               val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
+
+       return val;
+}
+
+/**************************/
+/*     Initialization     */
+/**************************/
+
+static void setup_ht_cap(struct ath_softc *sc,
+                        struct ieee80211_sta_ht_cap *ht_info)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u8 tx_streams, rx_streams;
+       int i, max_streams;
+
+       ht_info->ht_supported = true;
+       ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+                      IEEE80211_HT_CAP_SM_PS |
+                      IEEE80211_HT_CAP_SGI_40 |
+                      IEEE80211_HT_CAP_DSSSCCK40;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC)
+               ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
+               ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
+
+       ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+       ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
+
+       if (AR_SREV_9330(ah) || AR_SREV_9485(ah))
+               max_streams = 1;
+       else if (AR_SREV_9462(ah))
+               max_streams = 2;
+       else if (AR_SREV_9300_20_OR_LATER(ah))
+               max_streams = 3;
+       else
+               max_streams = 2;
+
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               if (max_streams >= 2)
+                       ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
+               ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+       }
+
+       /* set up supported mcs set */
+       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+       tx_streams = ath9k_btcoex_ath9k_cmn_count_streams(ah->txchainmask, max_streams);
+       rx_streams = ath9k_btcoex_ath9k_cmn_count_streams(ah->rxchainmask, max_streams);
+
+       ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n",
+               tx_streams, rx_streams);
+
+       if (tx_streams != rx_streams) {
+               ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
+               ht_info->mcs.tx_params |= ((tx_streams - 1) <<
+                               IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
+       }
+
+       for (i = 0; i < rx_streams; i++)
+               ht_info->mcs.rx_mask[i] = 0xff;
+
+       ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
+}
+
+static int ath9k_reg_notifier(struct wiphy *wiphy,
+                             struct regulatory_request *request)
+{
+       struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+       int ret;
+
+       ret = ath_reg_notifier_apply(wiphy, request, reg);
+
+       /* Set tx power */
+       if (ah->curchan) {
+               sc->config.txpowlimit = 2 * ah->curchan->chan->max_power;
+               ath9k_ps_wakeup(sc);
+               ath9k_btcoex_ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
+               sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
+               ath9k_ps_restore(sc);
+       }
+
+       return ret;
+}
+
+/*
+ *  This function will allocate both the DMA descriptor structure, and the
+ *  buffers it contains.  These are used to contain the descriptors used
+ *  by the system.
+*/
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+                     struct list_head *head, const char *name,
+                     int nbuf, int ndesc, bool is_tx)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       u8 *ds;
+       struct ath_buf *bf;
+       int i, bsize, error, desc_len;
+
+       ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n",
+               name, nbuf, ndesc);
+
+       INIT_LIST_HEAD(head);
+
+       if (is_tx)
+               desc_len = sc->sc_ah->caps.tx_desc_len;
+       else
+               desc_len = sizeof(struct ath_desc);
+
+       /* ath_desc must be a multiple of DWORDs */
+       if ((desc_len % 4) != 0) {
+               ath_err(common, "ath_desc not DWORD aligned\n");
+               BUG_ON((desc_len % 4) != 0);
+               error = -ENOMEM;
+               goto fail;
+       }
+
+       dd->dd_desc_len = desc_len * nbuf * ndesc;
+
+       /*
+        * Need additional DMA memory because we can't use
+        * descriptors that cross the 4K page boundary. Assume
+        * one skipped descriptor per 4K page.
+        */
+       if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+               u32 ndesc_skipped =
+                       ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
+               u32 dma_len;
+
+               while (ndesc_skipped) {
+                       dma_len = ndesc_skipped * desc_len;
+                       dd->dd_desc_len += dma_len;
+
+                       ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
+               }
+       }
+
+       /* allocate descriptors */
+       dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
+                                        &dd->dd_desc_paddr, GFP_KERNEL);
+       if (dd->dd_desc == NULL) {
+               error = -ENOMEM;
+               goto fail;
+       }
+       ds = (u8 *) dd->dd_desc;
+       ath_dbg(common, CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
+               name, ds, (u32) dd->dd_desc_len,
+               ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
+
+       /* allocate buffers */
+       bsize = sizeof(struct ath_buf) * nbuf;
+       bf = kzalloc(bsize, GFP_KERNEL);
+       if (bf == NULL) {
+               error = -ENOMEM;
+               goto fail2;
+       }
+       dd->dd_bufptr = bf;
+
+       for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
+               bf->bf_desc = ds;
+               bf->bf_daddr = DS2PHYS(dd, ds);
+
+               if (!(sc->sc_ah->caps.hw_caps &
+                     ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+                       /*
+                        * Skip descriptor addresses which can cause 4KB
+                        * boundary crossing (addr + length) with a 32 dword
+                        * descriptor fetch.
+                        */
+                       while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
+                               BUG_ON((caddr_t) bf->bf_desc >=
+                                      ((caddr_t) dd->dd_desc +
+                                       dd->dd_desc_len));
+
+                               ds += (desc_len * ndesc);
+                               bf->bf_desc = ds;
+                               bf->bf_daddr = DS2PHYS(dd, ds);
+                       }
+               }
+               list_add_tail(&bf->list, head);
+       }
+       return 0;
+fail2:
+       dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
+                         dd->dd_desc_paddr);
+fail:
+       memset(dd, 0, sizeof(*dd));
+       return error;
+}
+
+static int ath9k_init_queues(struct ath_softc *sc)
+{
+       int i = 0;
+
+       sc->beacon.beaconq = ath9k_btcoex_ath9k_hw_beaconq_setup(sc->sc_ah);
+       sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
+
+       sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
+       ath_cabq_update(sc);
+
+       for (i = 0; i < WME_NUM_AC; i++) {
+               sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
+               sc->tx.txq_map[i]->mac80211_qnum = i;
+       }
+       return 0;
+}
+
+static int ath9k_init_channels_rates(struct ath_softc *sc)
+{
+       void *channels;
+
+       BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) +
+                    ARRAY_SIZE(ath9k_5ghz_chantable) !=
+                    ATH9K_NUM_CHANNELS);
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
+               channels = kmemdup(ath9k_2ghz_chantable,
+                       sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
+               if (!channels)
+                   return -ENOMEM;
+
+               sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
+               sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+               sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
+                       ARRAY_SIZE(ath9k_2ghz_chantable);
+               sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
+               sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
+                       ARRAY_SIZE(ath9k_legacy_rates);
+       }
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
+               channels = kmemdup(ath9k_5ghz_chantable,
+                       sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
+               if (!channels) {
+                       if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
+                               kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
+                       return -ENOMEM;
+               }
+
+               sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
+               sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
+               sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
+                       ARRAY_SIZE(ath9k_5ghz_chantable);
+               sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
+                       ath9k_legacy_rates + 4;
+               sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
+                       ARRAY_SIZE(ath9k_legacy_rates) - 4;
+       }
+       return 0;
+}
+
+static void ath9k_init_misc(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       int i = 0;
+
+       setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
+
+       sc->config.txpowlimit = ATH_TXPOWER_MAX;
+       memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+       sc->beacon.slottime = ATH9K_SLOT_TIME_9;
+
+       for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
+               sc->beacon.bslot[i] = NULL;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+               sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
+}
+
+static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
+                           const struct ath_bus_ops *bus_ops)
+{
+       struct ath9k_platform_data *pdata = sc->dev->platform_data;
+       struct ath_hw *ah = NULL;
+       struct ath_common *common;
+       int ret = 0, i;
+       int csz = 0;
+
+       ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
+       if (!ah)
+               return -ENOMEM;
+
+       ah->hw = sc->hw;
+       ah->hw_version.devid = devid;
+       ah->reg_ops.read = ath9k_ioread32;
+       ah->reg_ops.write = ath9k_iowrite32;
+       ah->reg_ops.rmw = ath9k_reg_rmw;
+       atomic_set(&ah->intr_ref_cnt, -1);
+       sc->sc_ah = ah;
+
+       if (!pdata) {
+               ah->ah_flags |= AH_USE_EEPROM;
+               sc->sc_ah->led_pin = -1;
+       } else {
+               sc->sc_ah->gpio_mask = pdata->gpio_mask;
+               sc->sc_ah->gpio_val = pdata->gpio_val;
+               sc->sc_ah->led_pin = pdata->led_pin;
+               ah->is_clk_25mhz = pdata->is_clk_25mhz;
+               ah->get_mac_revision = pdata->get_mac_revision;
+               ah->external_reset = pdata->external_reset;
+       }
+
+       common = ath9k_hw_common(ah);
+       common->ops = &ah->reg_ops;
+       common->bus_ops = bus_ops;
+       common->ah = ah;
+       common->hw = sc->hw;
+       common->priv = sc;
+       common->debug_mask = ath9k_debug;
+       common->btcoex_enabled = ath9k_btcoex_enable == 1;
+       common->disable_ani = false;
+       spin_lock_init(&common->cc_lock);
+
+       spin_lock_init(&sc->sc_serial_rw);
+       spin_lock_init(&sc->sc_pm_lock);
+       spin_lock_init(&sc->sc_bb_lock);
+       mutex_init(&sc->mutex);
+#ifdef CONFIG_ATH9K_DEBUGFS
+       spin_lock_init(&sc->nodes_lock);
+       INIT_LIST_HEAD(&sc->nodes);
+#endif
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+       spin_lock_init(&sc->debug.samp_lock);
+#endif
+       tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
+       tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
+                    (unsigned long)sc);
+
+       /*
+        * Cache line size is used to size and align various
+        * structures used to communicate with the hardware.
+        */
+       ath_read_cachesize(common, &csz);
+       common->cachelsz = csz << 2; /* convert to bytes */
+
+       /* Initializes the hardware for all supported chipsets */
+       ret = ath9k_btcoex_ath9k_hw_init(ah);
+       if (ret)
+               goto err_hw;
+
+       if (pdata && pdata->macaddr)
+               memcpy(common->macaddr, pdata->macaddr, ETH_ALEN);
+
+       ret = ath9k_init_queues(sc);
+       if (ret)
+               goto err_queues;
+
+       ret =  ath9k_init_btcoex(sc);
+       if (ret)
+               goto err_btcoex;
+
+       ret = ath9k_init_channels_rates(sc);
+       if (ret)
+               goto err_btcoex;
+
+       ath9k_btcoex_ath9k_cmn_init_crypto(sc->sc_ah);
+       ath9k_init_misc(sc);
+
+       if (common->bus_ops->aspm_init)
+               common->bus_ops->aspm_init(common);
+
+       return 0;
+
+err_btcoex:
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+               if (ATH_TXQ_SETUP(sc, i))
+                       ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+err_queues:
+       ath9k_btcoex_ath9k_hw_deinit(ah);
+err_hw:
+
+       kfree(ah);
+       sc->sc_ah = NULL;
+
+       return ret;
+}
+
+static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
+{
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *chan;
+       struct ath_hw *ah = sc->sc_ah;
+       int i;
+
+       sband = &sc->sbands[band];
+       for (i = 0; i < sband->n_channels; i++) {
+               chan = &sband->channels[i];
+               ah->curchan = &ah->channels[chan->hw_value];
+               ath9k_btcoex_ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
+               ath9k_btcoex_ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
+       }
+}
+
+static void ath9k_init_txpower_limits(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath9k_channel *curchan = ah->curchan;
+
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+               ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+               ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
+
+       ah->curchan = curchan;
+}
+
+void ath9k_reload_chainmask_settings(struct ath_softc *sc)
+{
+       if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT))
+               return;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+               setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+               setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+}
+
+static const struct ieee80211_iface_limit if_limits[] = {
+       { .max = 2048,  .types = BIT(NL80211_IFTYPE_STATION) |
+                                BIT(NL80211_IFTYPE_P2P_CLIENT) |
+                                BIT(NL80211_IFTYPE_WDS) },
+       { .max = 8,     .types =
+#ifdef CONFIG_MAC80211_MESH
+                                BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
+                                BIT(NL80211_IFTYPE_AP) |
+                                BIT(NL80211_IFTYPE_P2P_GO) },
+};
+
+static const struct ieee80211_iface_combination if_comb = {
+       .limits = if_limits,
+       .n_limits = ARRAY_SIZE(if_limits),
+       .max_interfaces = 2048,
+       .num_different_channels = 1,
+};
+
+void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+               IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+               IEEE80211_HW_SIGNAL_DBM |
+               IEEE80211_HW_SUPPORTS_PS |
+               IEEE80211_HW_PS_NULLFUNC_STACK |
+               IEEE80211_HW_SPECTRUM_MGMT |
+               IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
+                hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
+
+       if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt)
+               hw->flags |= IEEE80211_HW_MFP_CAPABLE;
+
+       hw->wiphy->interface_modes =
+               BIT(NL80211_IFTYPE_P2P_GO) |
+               BIT(NL80211_IFTYPE_P2P_CLIENT) |
+               BIT(NL80211_IFTYPE_AP) |
+               BIT(NL80211_IFTYPE_WDS) |
+               BIT(NL80211_IFTYPE_STATION) |
+               BIT(NL80211_IFTYPE_ADHOC) |
+               BIT(NL80211_IFTYPE_MESH_POINT);
+
+       hw->wiphy->iface_combinations = &if_comb;
+       hw->wiphy->n_iface_combinations = 1;
+
+       if (AR_SREV_5416(sc->sc_ah))
+               hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+       hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
+
+       hw->queues = 4;
+       hw->max_rates = 4;
+       hw->channel_change_time = 5000;
+       hw->max_listen_interval = 1;
+       hw->max_rate_tries = 10;
+       hw->sta_data_size = sizeof(struct ath_node);
+       hw->vif_data_size = sizeof(struct ath_vif);
+
+       hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
+       hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
+
+       /* single chain devices with rx diversity */
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+               hw->wiphy->available_antennas_rx = BIT(0) | BIT(1);
+
+       sc->ant_rx = hw->wiphy->available_antennas_rx;
+       sc->ant_tx = hw->wiphy->available_antennas_tx;
+
+#ifdef CONFIG_ATH9K_RATE_CONTROL
+       hw->rate_control_algorithm = "ath9k_btcoex_rate_cotnrol";
+#endif
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+               hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+                       &sc->sbands[IEEE80211_BAND_2GHZ];
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+               hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+                       &sc->sbands[IEEE80211_BAND_5GHZ];
+
+       ath9k_reload_chainmask_settings(sc);
+
+       SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
+}
+
+int ath9k_init_device(u16 devid, struct ath_softc *sc,
+                   const struct ath_bus_ops *bus_ops)
+{
+       struct ieee80211_hw *hw = sc->hw;
+       struct ath_common *common;
+       struct ath_hw *ah;
+       int error = 0;
+       struct ath_regulatory *reg;
+
+       /* Bring up device */
+       error = ath9k_init_softc(devid, sc, bus_ops);
+       if (error != 0)
+               goto error_init;
+
+       ah = sc->sc_ah;
+       common = ath9k_hw_common(ah);
+       ath9k_set_hw_capab(sc, hw);
+
+       /* Initialize regulatory */
+       error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
+                             ath9k_reg_notifier);
+       if (error)
+               goto error_regd;
+
+       reg = &common->regulatory;
+
+       /* Setup TX DMA */
+       error = ath_tx_init(sc, ATH_TXBUF);
+       if (error != 0)
+               goto error_tx;
+
+       /* Setup RX DMA */
+       error = ath_rx_init(sc, ATH_RXBUF);
+       if (error != 0)
+               goto error_rx;
+
+       ath9k_init_txpower_limits(sc);
+
+#ifdef CONFIG_MAC80211_LEDS
+       /* must be initialized before ieee80211_register_hw */
+       sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
+               IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
+               ARRAY_SIZE(ath9k_tpt_blink));
+#endif
+
+       INIT_WORK(&sc->hw_reset_work, ath_reset_work);
+       INIT_WORK(&sc->hw_check_work, ath_hw_check);
+       INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
+       INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
+       setup_timer(&sc->rx_poll_timer, ath_rx_poll_work, (unsigned long)sc);
+
+       /* Register with mac80211 */
+       error = ieee80211_register_hw(hw);
+       if (error)
+               goto error_register;
+
+       error = ath9k_init_debug(ah);
+       if (error) {
+               ath_err(common, "Unable to create debugfs files\n");
+               goto error_world;
+       }
+
+       /* Handle world regulatory */
+       if (!ath_is_world_regd(reg)) {
+               error = regulatory_hint(hw->wiphy, reg->alpha2);
+               if (error)
+                       goto error_world;
+       }
+
+       sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+
+       ath_init_leds(sc);
+       ath_start_rfkill_poll(sc);
+
+       return 0;
+
+error_world:
+       ieee80211_unregister_hw(hw);
+error_register:
+       ath_rx_cleanup(sc);
+error_rx:
+       ath_tx_cleanup(sc);
+error_tx:
+       /* Nothing */
+error_regd:
+       ath9k_deinit_softc(sc);
+error_init:
+       return error;
+}
+
+/*****************************/
+/*     De-Initialization     */
+/*****************************/
+
+static void ath9k_deinit_softc(struct ath_softc *sc)
+{
+       int i = 0;
+
+       if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
+               kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
+
+       if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
+               kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
+
+       ath9k_deinit_btcoex(sc);
+
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+               if (ATH_TXQ_SETUP(sc, i))
+                       ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+
+       ath9k_btcoex_ath9k_hw_deinit(sc->sc_ah);
+
+       kfree(sc->sc_ah);
+       sc->sc_ah = NULL;
+}
+
+void ath9k_deinit_device(struct ath_softc *sc)
+{
+       struct ieee80211_hw *hw = sc->hw;
+
+       ath9k_ps_wakeup(sc);
+
+       wiphy_rfkill_stop_polling(sc->hw->wiphy);
+       ath_deinit_leds(sc);
+
+       ath9k_ps_restore(sc);
+
+       ieee80211_unregister_hw(hw);
+       ath_rx_cleanup(sc);
+       ath_tx_cleanup(sc);
+       ath9k_deinit_softc(sc);
+}
+
+void ath_descdma_cleanup(struct ath_softc *sc,
+                        struct ath_descdma *dd,
+                        struct list_head *head)
+{
+       dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
+                         dd->dd_desc_paddr);
+
+       INIT_LIST_HEAD(head);
+       kfree(dd->dd_bufptr);
+       memset(dd, 0, sizeof(*dd));
+}
+
+/************************/
+/*     Module Hooks     */
+/************************/
+
+static int __init ath9k_init(void)
+{
+       int error;
+
+       /* Register rate control algorithm */
+       error = ath_rate_control_register();
+       if (error != 0) {
+               printk(KERN_ERR
+                       "ath9k: Unable to register rate control "
+                       "algorithm: %d\n",
+                       error);
+               goto err_out;
+       }
+
+       error = ath_pci_init();
+       if (error < 0) {
+               printk(KERN_ERR
+                       "ath9k: No PCI devices found, driver not installed.\n");
+               error = -ENODEV;
+               goto err_rate_unregister;
+       }
+
+       error = ath_ahb_init();
+       if (error < 0) {
+               error = -ENODEV;
+               goto err_pci_exit;
+       }
+
+       return 0;
+
+ err_pci_exit:
+       ath_pci_exit();
+
+ err_rate_unregister:
+       ath_rate_control_unregister();
+ err_out:
+       return error;
+}
+module_init(ath9k_init);
+
+static void __exit ath9k_exit(void)
+{
+       is_ath9k_unloaded = true;
+       ath_ahb_exit();
+       ath_pci_exit();
+       ath_rate_control_unregister();
+       printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
+}
+module_exit(ath9k_exit);
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/mac.c b/drivers/net/wireless/ath/ath9k_btcoex/mac.c
new file mode 100644 (file)
index 0000000..e56ed34
--- /dev/null
@@ -0,0 +1,917 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+#include <linux/export.h>
+
+static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
+                                       struct ath9k_tx_queue_info *qi)
+{
+       ath_dbg(ath9k_hw_common(ah), INTERRUPT,
+               "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
+               ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
+               ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
+               ah->txurn_interrupt_mask);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_IMR_S0,
+                 SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
+                 | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
+       REG_WRITE(ah, AR_IMR_S1,
+                 SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
+                 | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
+
+       ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
+       ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
+       REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+}
+
+u32 ath9k_btcoex_ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
+{
+       return REG_READ(ah, AR_QTXDP(q));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_gettxbuf);
+
+void ath9k_btcoex_ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
+{
+       REG_WRITE(ah, AR_QTXDP(q), txdp);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_puttxbuf);
+
+void ath9k_btcoex_ath9k_hw_txstart(struct ath_hw *ah, u32 q)
+{
+       ath_dbg(ath9k_hw_common(ah), QUEUE, "Enable TXE on queue: %u\n", q);
+       REG_WRITE(ah, AR_Q_TXE, 1 << q);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_txstart);
+
+u32 ath9k_btcoex_ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
+{
+       u32 npend;
+
+       npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
+       if (npend == 0) {
+
+               if (REG_READ(ah, AR_Q_TXE) & (1 << q))
+                       npend = 1;
+       }
+
+       return npend;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_numtxpending);
+
+/**
+ * ath9k_btcoex_ath9k_hw_updatetxtriglevel - adjusts the frame trigger level
+ *
+ * @ah: atheros hardware struct
+ * @bIncTrigLevel: whether or not the frame trigger level should be updated
+ *
+ * The frame trigger level specifies the minimum number of bytes,
+ * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO
+ * before the PCU will initiate sending the frame on the air. This can
+ * mean we initiate transmit before a full frame is on the PCU TX FIFO.
+ * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs
+ * first)
+ *
+ * Caution must be taken to ensure to set the frame trigger level based
+ * on the DMA request size. For example if the DMA request size is set to
+ * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because
+ * there need to be enough space in the tx FIFO for the requested transfer
+ * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set
+ * the threshold to a value beyond 6, then the transmit will hang.
+ *
+ * Current dual   stream devices have a PCU TX FIFO size of 8 KB.
+ * Current single stream devices have a PCU TX FIFO size of 4 KB, however,
+ * there is a hardware issue which forces us to use 2 KB instead so the
+ * frame trigger level must not exceed 2 KB for these chipsets.
+ */
+bool ath9k_btcoex_ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
+{
+       u32 txcfg, curLevel, newLevel;
+
+       if (ah->tx_trig_level >= ah->config.max_txtrig_level)
+               return false;
+
+       ath9k_btcoex_ath9k_hw_disable_interrupts(ah);
+
+       txcfg = REG_READ(ah, AR_TXCFG);
+       curLevel = MS(txcfg, AR_FTRIG);
+       newLevel = curLevel;
+       if (bIncTrigLevel) {
+               if (curLevel < ah->config.max_txtrig_level)
+                       newLevel++;
+       } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
+               newLevel--;
+       if (newLevel != curLevel)
+               REG_WRITE(ah, AR_TXCFG,
+                         (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
+
+       ath9k_btcoex_ath9k_hw_enable_interrupts(ah);
+
+       ah->tx_trig_level = newLevel;
+
+       return newLevel != curLevel;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_updatetxtriglevel);
+
+void ath9k_btcoex_ath9k_hw_abort_tx_dma(struct ath_hw *ah)
+{
+       int i, q;
+
+       REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
+
+       REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
+       REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+       REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
+
+       for (q = 0; q < AR_NUM_QCU; q++) {
+               for (i = 0; i < 1000; i++) {
+                       if (i)
+                               udelay(5);
+
+                       if (!ath9k_btcoex_ath9k_hw_numtxpending(ah, q))
+                               break;
+               }
+       }
+
+       REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
+       REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+       REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
+
+       REG_WRITE(ah, AR_Q_TXD, 0);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_abort_tx_dma);
+
+bool ath9k_btcoex_ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
+{
+#define ATH9K_TX_STOP_DMA_TIMEOUT      1000    /* usec */
+#define ATH9K_TIME_QUANTUM             100     /* usec */
+       int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
+       int wait;
+
+       REG_WRITE(ah, AR_Q_TXD, 1 << q);
+
+       for (wait = wait_time; wait != 0; wait--) {
+               if (wait != wait_time)
+                       udelay(ATH9K_TIME_QUANTUM);
+
+               if (ath9k_btcoex_ath9k_hw_numtxpending(ah, q) == 0)
+                       break;
+       }
+
+       REG_WRITE(ah, AR_Q_TXD, 0);
+
+       return wait != 0;
+
+#undef ATH9K_TX_STOP_DMA_TIMEOUT
+#undef ATH9K_TIME_QUANTUM
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_stop_dma_queue);
+
+bool ath9k_btcoex_ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
+                           const struct ath9k_tx_queue_info *qinfo)
+{
+       u32 cw;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_tx_queue_info *qi;
+
+       qi = &ah->txq[q];
+       if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+               ath_dbg(common, QUEUE,
+                       "Set TXQ properties, inactive queue: %u\n", q);
+               return false;
+       }
+
+       ath_dbg(common, QUEUE, "Set queue properties for: %u\n", q);
+
+       qi->tqi_ver = qinfo->tqi_ver;
+       qi->tqi_subtype = qinfo->tqi_subtype;
+       qi->tqi_qflags = qinfo->tqi_qflags;
+       qi->tqi_priority = qinfo->tqi_priority;
+       if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
+               qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
+       else
+               qi->tqi_aifs = INIT_AIFS;
+       if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
+               cw = min(qinfo->tqi_cwmin, 1024U);
+               qi->tqi_cwmin = 1;
+               while (qi->tqi_cwmin < cw)
+                       qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
+       } else
+               qi->tqi_cwmin = qinfo->tqi_cwmin;
+       if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
+               cw = min(qinfo->tqi_cwmax, 1024U);
+               qi->tqi_cwmax = 1;
+               while (qi->tqi_cwmax < cw)
+                       qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
+       } else
+               qi->tqi_cwmax = INIT_CWMAX;
+
+       if (qinfo->tqi_shretry != 0)
+               qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
+       else
+               qi->tqi_shretry = INIT_SH_RETRY;
+       if (qinfo->tqi_lgretry != 0)
+               qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
+       else
+               qi->tqi_lgretry = INIT_LG_RETRY;
+       qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
+       qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
+       qi->tqi_burstTime = qinfo->tqi_burstTime;
+       qi->tqi_readyTime = qinfo->tqi_readyTime;
+
+       switch (qinfo->tqi_subtype) {
+       case ATH9K_WME_UPSD:
+               if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
+                       qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
+               break;
+       default:
+               break;
+       }
+
+       return true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_set_txq_props);
+
+bool ath9k_btcoex_ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
+                           struct ath9k_tx_queue_info *qinfo)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_tx_queue_info *qi;
+
+       qi = &ah->txq[q];
+       if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+               ath_dbg(common, QUEUE,
+                       "Get TXQ properties, inactive queue: %u\n", q);
+               return false;
+       }
+
+       qinfo->tqi_qflags = qi->tqi_qflags;
+       qinfo->tqi_ver = qi->tqi_ver;
+       qinfo->tqi_subtype = qi->tqi_subtype;
+       qinfo->tqi_qflags = qi->tqi_qflags;
+       qinfo->tqi_priority = qi->tqi_priority;
+       qinfo->tqi_aifs = qi->tqi_aifs;
+       qinfo->tqi_cwmin = qi->tqi_cwmin;
+       qinfo->tqi_cwmax = qi->tqi_cwmax;
+       qinfo->tqi_shretry = qi->tqi_shretry;
+       qinfo->tqi_lgretry = qi->tqi_lgretry;
+       qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
+       qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
+       qinfo->tqi_burstTime = qi->tqi_burstTime;
+       qinfo->tqi_readyTime = qi->tqi_readyTime;
+
+       return true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_get_txq_props);
+
+int ath9k_btcoex_ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
+                         const struct ath9k_tx_queue_info *qinfo)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_tx_queue_info *qi;
+       int q;
+
+       switch (type) {
+       case ATH9K_TX_QUEUE_BEACON:
+               q = ATH9K_NUM_TX_QUEUES - 1;
+               break;
+       case ATH9K_TX_QUEUE_CAB:
+               q = ATH9K_NUM_TX_QUEUES - 2;
+               break;
+       case ATH9K_TX_QUEUE_PSPOLL:
+               q = 1;
+               break;
+       case ATH9K_TX_QUEUE_UAPSD:
+               q = ATH9K_NUM_TX_QUEUES - 3;
+               break;
+       case ATH9K_TX_QUEUE_DATA:
+               for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
+                       if (ah->txq[q].tqi_type ==
+                           ATH9K_TX_QUEUE_INACTIVE)
+                               break;
+               if (q == ATH9K_NUM_TX_QUEUES) {
+                       ath_err(common, "No available TX queue\n");
+                       return -1;
+               }
+               break;
+       default:
+               ath_err(common, "Invalid TX queue type: %u\n", type);
+               return -1;
+       }
+
+       ath_dbg(common, QUEUE, "Setup TX queue: %u\n", q);
+
+       qi = &ah->txq[q];
+       if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
+               ath_err(common, "TX queue: %u already active\n", q);
+               return -1;
+       }
+       memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
+       qi->tqi_type = type;
+       qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
+       (void) ath9k_btcoex_ath9k_hw_set_txq_props(ah, q, qinfo);
+
+       return q;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_setuptxqueue);
+
+static void ath9k_hw_clear_queue_interrupts(struct ath_hw *ah, u32 q)
+{
+       ah->txok_interrupt_mask &= ~(1 << q);
+       ah->txerr_interrupt_mask &= ~(1 << q);
+       ah->txdesc_interrupt_mask &= ~(1 << q);
+       ah->txeol_interrupt_mask &= ~(1 << q);
+       ah->txurn_interrupt_mask &= ~(1 << q);
+}
+
+bool ath9k_btcoex_ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_tx_queue_info *qi;
+
+       qi = &ah->txq[q];
+       if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+               ath_dbg(common, QUEUE, "Release TXQ, inactive queue: %u\n", q);
+               return false;
+       }
+
+       ath_dbg(common, QUEUE, "Release TX queue: %u\n", q);
+
+       qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
+       ath9k_hw_clear_queue_interrupts(ah, q);
+       ath9k_hw_set_txq_interrupts(ah, qi);
+
+       return true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_releasetxqueue);
+
+bool ath9k_btcoex_ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_channel *chan = ah->curchan;
+       struct ath9k_tx_queue_info *qi;
+       u32 cwMin, chanCwMin, value;
+
+       qi = &ah->txq[q];
+       if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+               ath_dbg(common, QUEUE, "Reset TXQ, inactive queue: %u\n", q);
+               return true;
+       }
+
+       ath_dbg(common, QUEUE, "Reset TX queue: %u\n", q);
+
+       if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
+               if (chan && IS_CHAN_B(chan))
+                       chanCwMin = INIT_CWMIN_11B;
+               else
+                       chanCwMin = INIT_CWMIN;
+
+               for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
+       } else
+               cwMin = qi->tqi_cwmin;
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_DLCL_IFS(q),
+                 SM(cwMin, AR_D_LCL_IFS_CWMIN) |
+                 SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
+                 SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
+
+       REG_WRITE(ah, AR_DRETRY_LIMIT(q),
+                 SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
+                 SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
+                 SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
+
+       REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
+
+       if (AR_SREV_9340(ah))
+               REG_WRITE(ah, AR_DMISC(q),
+                         AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
+       else
+               REG_WRITE(ah, AR_DMISC(q),
+                         AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
+
+       if (qi->tqi_cbrPeriod) {
+               REG_WRITE(ah, AR_QCBRCFG(q),
+                         SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
+                         SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
+               REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR |
+                           (qi->tqi_cbrOverflowLimit ?
+                            AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
+       }
+       if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
+               REG_WRITE(ah, AR_QRDYTIMECFG(q),
+                         SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
+                         AR_Q_RDYTIMECFG_EN);
+       }
+
+       REG_WRITE(ah, AR_DCHNTIME(q),
+                 SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
+                 (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
+
+       if (qi->tqi_burstTime
+           && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE))
+               REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY);
+
+       if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE)
+               REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+
+       if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
+               REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN);
+
+       switch (qi->tqi_type) {
+       case ATH9K_TX_QUEUE_BEACON:
+               ENABLE_REGWRITE_BUFFER(ah);
+
+               REG_SET_BIT(ah, AR_QMISC(q),
+                           AR_Q_MISC_FSP_DBA_GATED
+                           | AR_Q_MISC_BEACON_USE
+                           | AR_Q_MISC_CBR_INCR_DIS1);
+
+               REG_SET_BIT(ah, AR_DMISC(q),
+                           (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+                            AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
+                           | AR_D_MISC_BEACON_USE
+                           | AR_D_MISC_POST_FR_BKOFF_DIS);
+
+               REGWRITE_BUFFER_FLUSH(ah);
+
+               /*
+                * cwmin and cwmax should be 0 for beacon queue
+                * but not for IBSS as we would create an imbalance
+                * on beaconing fairness for participating nodes.
+                */
+               if (AR_SREV_9300_20_OR_LATER(ah) &&
+                   ah->opmode != NL80211_IFTYPE_ADHOC) {
+                       REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN)
+                                 | SM(0, AR_D_LCL_IFS_CWMAX)
+                                 | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
+               }
+               break;
+       case ATH9K_TX_QUEUE_CAB:
+               ENABLE_REGWRITE_BUFFER(ah);
+
+               REG_SET_BIT(ah, AR_QMISC(q),
+                           AR_Q_MISC_FSP_DBA_GATED
+                           | AR_Q_MISC_CBR_INCR_DIS1
+                           | AR_Q_MISC_CBR_INCR_DIS0);
+               value = (qi->tqi_readyTime -
+                        (ah->config.sw_beacon_response_time -
+                         ah->config.dma_beacon_response_time) -
+                        ah->config.additional_swba_backoff) * 1024;
+               REG_WRITE(ah, AR_QRDYTIMECFG(q),
+                         value | AR_Q_RDYTIMECFG_EN);
+               REG_SET_BIT(ah, AR_DMISC(q),
+                           (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+                            AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
+
+               REGWRITE_BUFFER_FLUSH(ah);
+
+               break;
+       case ATH9K_TX_QUEUE_PSPOLL:
+               REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_CBR_INCR_DIS1);
+               break;
+       case ATH9K_TX_QUEUE_UAPSD:
+               REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);
+               break;
+       default:
+               break;
+       }
+
+       if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
+               REG_SET_BIT(ah, AR_DMISC(q),
+                           SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
+                              AR_D_MISC_ARB_LOCKOUT_CNTRL) |
+                           AR_D_MISC_POST_FR_BKOFF_DIS);
+       }
+
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);
+
+       ath9k_hw_clear_queue_interrupts(ah, q);
+       if (qi->tqi_qflags & TXQ_FLAG_TXINT_ENABLE) {
+               ah->txok_interrupt_mask |= 1 << q;
+               ah->txerr_interrupt_mask |= 1 << q;
+       }
+       if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
+               ah->txdesc_interrupt_mask |= 1 << q;
+       if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
+               ah->txeol_interrupt_mask |= 1 << q;
+       if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
+               ah->txurn_interrupt_mask |= 1 << q;
+       ath9k_hw_set_txq_interrupts(ah, qi);
+
+       return true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_resettxqueue);
+
+int ath9k_btcoex_ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
+                       struct ath_rx_status *rs)
+{
+       struct ar5416_desc ads;
+       struct ar5416_desc *adsp = AR5416DESC(ds);
+       u32 phyerr;
+
+       if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
+               return -EINPROGRESS;
+
+       ads.u.rx = adsp->u.rx;
+
+       rs->rs_status = 0;
+       rs->rs_flags = 0;
+
+       rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
+       rs->rs_tstamp = ads.AR_RcvTimestamp;
+
+       if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
+               rs->rs_rssi = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
+       } else {
+               rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+               rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
+                                               AR_RxRSSIAnt00);
+               rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
+                                               AR_RxRSSIAnt01);
+               rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
+                                               AR_RxRSSIAnt02);
+               rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
+                                               AR_RxRSSIAnt10);
+               rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
+                                               AR_RxRSSIAnt11);
+               rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
+                                               AR_RxRSSIAnt12);
+       }
+       if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
+               rs->rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
+       else
+               rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
+
+       rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate);
+       rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
+
+       rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
+       rs->rs_moreaggr =
+               (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
+       rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
+       rs->rs_flags =
+               (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
+       rs->rs_flags |=
+               (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
+
+       if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
+               rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
+       if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
+               rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
+       if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
+               rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
+
+       if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
+               /*
+                * Treat these errors as mutually exclusive to avoid spurious
+                * extra error reports from the hardware. If a CRC error is
+                * reported, then decryption and MIC errors are irrelevant,
+                * the frame is going to be dropped either way
+                */
+               if (ads.ds_rxstatus8 & AR_CRCErr)
+                       rs->rs_status |= ATH9K_RXERR_CRC;
+               else if (ads.ds_rxstatus8 & AR_PHYErr) {
+                       rs->rs_status |= ATH9K_RXERR_PHY;
+                       phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
+                       rs->rs_phyerr = phyerr;
+               } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+                       rs->rs_status |= ATH9K_RXERR_DECRYPT;
+               else if (ads.ds_rxstatus8 & AR_MichaelErr)
+                       rs->rs_status |= ATH9K_RXERR_MIC;
+       }
+
+       if (ads.ds_rxstatus8 & AR_KeyMiss)
+               rs->rs_status |= ATH9K_RXERR_KEYMISS;
+
+       return 0;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_rxprocdesc);
+
+/*
+ * This can stop or re-enables RX.
+ *
+ * If bool is set this will kill any frame which is currently being
+ * transferred between the MAC and baseband and also prevent any new
+ * frames from getting started.
+ */
+bool ath9k_btcoex_ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
+{
+       u32 reg;
+
+       if (set) {
+               REG_SET_BIT(ah, AR_DIAG_SW,
+                           (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+               if (!ath9k_btcoex_ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
+                                  0, AH_WAIT_TIMEOUT)) {
+                       REG_CLR_BIT(ah, AR_DIAG_SW,
+                                   (AR_DIAG_RX_DIS |
+                                    AR_DIAG_RX_ABORT));
+
+                       reg = REG_READ(ah, AR_OBS_BUS_1);
+                       ath_err(ath9k_hw_common(ah),
+                               "RX failed to go idle in 10 ms RXSM=0x%x\n",
+                               reg);
+
+                       return false;
+               }
+       } else {
+               REG_CLR_BIT(ah, AR_DIAG_SW,
+                           (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+       }
+
+       return true;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_setrxabort);
+
+void ath9k_btcoex_ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
+{
+       REG_WRITE(ah, AR_RXDP, rxdp);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_putrxbuf);
+
+void ath9k_btcoex_ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning)
+{
+       ath9k_enable_mib_counters(ah);
+
+       ath9k_ani_reset(ah, is_scanning);
+
+       REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_startpcureceive);
+
+void ath9k_btcoex_ath9k_hw_abortpcurecv(struct ath_hw *ah)
+{
+       REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
+
+       ath9k_btcoex_ath9k_hw_disable_mib_counters(ah);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_abortpcurecv);
+
+bool ath9k_btcoex_ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset)
+{
+#define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 mac_status, last_mac_status = 0;
+       int i;
+
+       /* Enable access to the DMA observation bus */
+       REG_WRITE(ah, AR_MACMISC,
+                 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+                  (AR_MACMISC_MISC_OBS_BUS_1 <<
+                   AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
+       REG_WRITE(ah, AR_CR, AR_CR_RXD);
+
+       /* Wait for rx enable bit to go low */
+       for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
+               if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
+                       break;
+
+               if (!AR_SREV_9300_20_OR_LATER(ah)) {
+                       mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
+                       if (mac_status == 0x1c0 && mac_status == last_mac_status) {
+                               *reset = true;
+                               break;
+                       }
+
+                       last_mac_status = mac_status;
+               }
+
+               udelay(AH_TIME_QUANTUM);
+       }
+
+       if (i == 0) {
+               ath_err(common,
+                       "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
+                       AH_RX_STOP_DMA_TIMEOUT / 1000,
+                       REG_READ(ah, AR_CR),
+                       REG_READ(ah, AR_DIAG_SW),
+                       REG_READ(ah, AR_DMADBG_7));
+               return false;
+       } else {
+               return true;
+       }
+
+#undef AH_RX_STOP_DMA_TIMEOUT
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_stopdmarecv);
+
+int ath9k_btcoex_ath9k_hw_beaconq_setup(struct ath_hw *ah)
+{
+       struct ath9k_tx_queue_info qi;
+
+       memset(&qi, 0, sizeof(qi));
+       qi.tqi_aifs = 1;
+       qi.tqi_cwmin = 0;
+       qi.tqi_cwmax = 0;
+
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+               qi.tqi_qflags = TXQ_FLAG_TXINT_ENABLE;
+
+       return ath9k_btcoex_ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_beaconq_setup);
+
+bool ath9k_btcoex_ath9k_hw_intrpend(struct ath_hw *ah)
+{
+       u32 host_isr;
+
+       if (AR_SREV_9100(ah))
+               return true;
+
+       host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
+
+       if (((host_isr & AR_INTR_MAC_IRQ) ||
+            (host_isr & AR_INTR_ASYNC_MASK_MCI)) &&
+           (host_isr != AR_INTR_SPURIOUS))
+               return true;
+
+       host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
+       if ((host_isr & AR_INTR_SYNC_DEFAULT)
+           && (host_isr != AR_INTR_SPURIOUS))
+               return true;
+
+       return false;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_intrpend);
+
+void ath9k_btcoex_ath9k_hw_disable_interrupts(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (!(ah->imask & ATH9K_INT_GLOBAL))
+               atomic_set(&ah->intr_ref_cnt, -1);
+       else
+               atomic_dec(&ah->intr_ref_cnt);
+
+       ath_dbg(common, INTERRUPT, "disable IER\n");
+       REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+       (void) REG_READ(ah, AR_IER);
+       if (!AR_SREV_9100(ah)) {
+               REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
+               (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+
+               REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+               (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
+       }
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_disable_interrupts);
+
+void ath9k_btcoex_ath9k_hw_enable_interrupts(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 sync_default = AR_INTR_SYNC_DEFAULT;
+       u32 async_mask;
+
+       if (!(ah->imask & ATH9K_INT_GLOBAL))
+               return;
+
+       if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
+               ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
+                       atomic_read(&ah->intr_ref_cnt));
+               return;
+       }
+
+       if (AR_SREV_9340(ah))
+               sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
+
+       async_mask = AR_INTR_MAC_IRQ;
+
+       if (ah->imask & ATH9K_INT_MCI)
+               async_mask |= AR_INTR_ASYNC_MASK_MCI;
+
+       ath_dbg(common, INTERRUPT, "enable IER\n");
+       REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+       if (!AR_SREV_9100(ah)) {
+               REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, async_mask);
+               REG_WRITE(ah, AR_INTR_ASYNC_MASK, async_mask);
+
+               REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default);
+               REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default);
+       }
+       ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
+               REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_enable_interrupts);
+
+void ath9k_btcoex_ath9k_hw_set_interrupts(struct ath_hw *ah)
+{
+       enum ath9k_int ints = ah->imask;
+       u32 mask, mask2;
+       struct ath9k_hw_capabilities *pCap = &ah->caps;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (!(ints & ATH9K_INT_GLOBAL))
+               ath9k_btcoex_ath9k_hw_disable_interrupts(ah);
+
+       ath_dbg(common, INTERRUPT, "New interrupt mask 0x%x\n", ints);
+
+       mask = ints & ATH9K_INT_COMMON;
+       mask2 = 0;
+
+       if (ints & ATH9K_INT_TX) {
+               if (ah->config.tx_intr_mitigation)
+                       mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
+               else {
+                       if (ah->txok_interrupt_mask)
+                               mask |= AR_IMR_TXOK;
+                       if (ah->txdesc_interrupt_mask)
+                               mask |= AR_IMR_TXDESC;
+               }
+               if (ah->txerr_interrupt_mask)
+                       mask |= AR_IMR_TXERR;
+               if (ah->txeol_interrupt_mask)
+                       mask |= AR_IMR_TXEOL;
+       }
+       if (ints & ATH9K_INT_RX) {
+               if (AR_SREV_9300_20_OR_LATER(ah)) {
+                       mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
+                       if (ah->config.rx_intr_mitigation) {
+                               mask &= ~AR_IMR_RXOK_LP;
+                               mask |=  AR_IMR_RXMINTR | AR_IMR_RXINTM;
+                       } else {
+                               mask |= AR_IMR_RXOK_LP;
+                       }
+               } else {
+                       if (ah->config.rx_intr_mitigation)
+                               mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
+                       else
+                               mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
+               }
+               if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+                       mask |= AR_IMR_GENTMR;
+       }
+
+       if (ints & ATH9K_INT_GENTIMER)
+               mask |= AR_IMR_GENTMR;
+
+       if (ints & (ATH9K_INT_BMISC)) {
+               mask |= AR_IMR_BCNMISC;
+               if (ints & ATH9K_INT_TIM)
+                       mask2 |= AR_IMR_S2_TIM;
+               if (ints & ATH9K_INT_DTIM)
+                       mask2 |= AR_IMR_S2_DTIM;
+               if (ints & ATH9K_INT_DTIMSYNC)
+                       mask2 |= AR_IMR_S2_DTIMSYNC;
+               if (ints & ATH9K_INT_CABEND)
+                       mask2 |= AR_IMR_S2_CABEND;
+               if (ints & ATH9K_INT_TSFOOR)
+                       mask2 |= AR_IMR_S2_TSFOOR;
+       }
+
+       if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
+               mask |= AR_IMR_BCNMISC;
+               if (ints & ATH9K_INT_GTT)
+                       mask2 |= AR_IMR_S2_GTT;
+               if (ints & ATH9K_INT_CST)
+                       mask2 |= AR_IMR_S2_CST;
+       }
+
+       ath_dbg(common, INTERRUPT, "new IMR 0x%x\n", mask);
+       REG_WRITE(ah, AR_IMR, mask);
+       ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
+                          AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
+                          AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
+       ah->imrs2_reg |= mask2;
+       REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
+
+       if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+               if (ints & ATH9K_INT_TIM_TIMER)
+                       REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+               else
+                       REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+       }
+
+       return;
+}
+EXPORT_SYMBOL(ath9k_btcoex_ath9k_hw_set_interrupts);
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/mac.h b/drivers/net/wireless/ath/ath9k_btcoex/mac.h
new file mode 100644 (file)
index 0000000..0286178
--- /dev/null
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MAC_H
+#define MAC_H
+
+#define set11nTries(_series, _index) \
+       (SM((_series)[_index].Tries, AR_XmitDataTries##_index))
+
+#define set11nRate(_series, _index) \
+       (SM((_series)[_index].Rate, AR_XmitRate##_index))
+
+#define set11nPktDurRTSCTS(_series, _index)                            \
+       (SM((_series)[_index].PktDuration, AR_PacketDur##_index) |      \
+        ((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS   ?    \
+         AR_RTSCTSQual##_index : 0))
+
+#define set11nRateFlags(_series, _index)                               \
+       (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ?         \
+         AR_2040_##_index : 0)                                         \
+        |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ?      \
+          AR_GI##_index : 0)                                           \
+        |((_series)[_index].RateFlags & ATH9K_RATESERIES_STBC ?        \
+          AR_STBC##_index : 0)                                         \
+        |SM((_series)[_index].ChSel, AR_ChainSel##_index))
+
+#define CCK_SIFS_TIME        10
+#define CCK_PREAMBLE_BITS   144
+#define CCK_PLCP_BITS        48
+
+#define OFDM_SIFS_TIME        16
+#define OFDM_PREAMBLE_TIME    20
+#define OFDM_PLCP_BITS        22
+#define OFDM_SYMBOL_TIME      4
+
+#define OFDM_SIFS_TIME_HALF     32
+#define OFDM_PREAMBLE_TIME_HALF 40
+#define OFDM_PLCP_BITS_HALF     22
+#define OFDM_SYMBOL_TIME_HALF   8
+
+#define OFDM_SIFS_TIME_QUARTER      64
+#define OFDM_PREAMBLE_TIME_QUARTER  80
+#define OFDM_PLCP_BITS_QUARTER      22
+#define OFDM_SYMBOL_TIME_QUARTER    16
+
+#define INIT_AIFS       2
+#define INIT_CWMIN      15
+#define INIT_CWMIN_11B  31
+#define INIT_CWMAX      1023
+#define INIT_SH_RETRY   10
+#define INIT_LG_RETRY   10
+#define INIT_SSH_RETRY  32
+#define INIT_SLG_RETRY  32
+
+#define ATH9K_SLOT_TIME_6 6
+#define ATH9K_SLOT_TIME_9 9
+#define ATH9K_SLOT_TIME_20 20
+
+#define ATH9K_TXERR_XRETRY         0x01
+#define ATH9K_TXERR_FILT           0x02
+#define ATH9K_TXERR_FIFO           0x04
+#define ATH9K_TXERR_XTXOP          0x08
+#define ATH9K_TXERR_TIMER_EXPIRED  0x10
+#define ATH9K_TX_ACKED            0x20
+#define ATH9K_TX_FLUSH            0x40
+#define ATH9K_TXERR_MASK                                               \
+       (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO |     \
+        ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED | ATH9K_TX_FLUSH)
+
+#define ATH9K_TX_BA                0x01
+#define ATH9K_TX_PWRMGMT           0x02
+#define ATH9K_TX_DESC_CFG_ERR      0x04
+#define ATH9K_TX_DATA_UNDERRUN     0x08
+#define ATH9K_TX_DELIM_UNDERRUN    0x10
+#define ATH9K_TX_SW_FILTERED       0x80
+
+/* 64 bytes */
+#define MIN_TX_FIFO_THRESHOLD   0x1
+
+/*
+ * Single stream device AR9285 and AR9271 require 2 KB
+ * to work around a hardware issue, all other devices
+ * have can use the max 4 KB limit.
+ */
+#define MAX_TX_FIFO_THRESHOLD   ((4096 / 64) - 1)
+
+struct ath_tx_status {
+       u32 ts_tstamp;
+       u16 ts_seqnum;
+       u8 ts_status;
+       u8 ts_rateindex;
+       int8_t ts_rssi;
+       u8 ts_shortretry;
+       u8 ts_longretry;
+       u8 ts_virtcol;
+       u8 ts_flags;
+       int8_t ts_rssi_ctl0;
+       int8_t ts_rssi_ctl1;
+       int8_t ts_rssi_ctl2;
+       int8_t ts_rssi_ext0;
+       int8_t ts_rssi_ext1;
+       int8_t ts_rssi_ext2;
+       u8 qid;
+       u16 desc_id;
+       u8 tid;
+       u32 ba_low;
+       u32 ba_high;
+       u32 evm0;
+       u32 evm1;
+       u32 evm2;
+};
+
+struct ath_rx_status {
+       u32 rs_tstamp;
+       u16 rs_datalen;
+       u8 rs_status;
+       u8 rs_phyerr;
+       int8_t rs_rssi;
+       u8 rs_keyix;
+       u8 rs_rate;
+       u8 rs_antenna;
+       u8 rs_more;
+       int8_t rs_rssi_ctl0;
+       int8_t rs_rssi_ctl1;
+       int8_t rs_rssi_ctl2;
+       int8_t rs_rssi_ext0;
+       int8_t rs_rssi_ext1;
+       int8_t rs_rssi_ext2;
+       u8 rs_isaggr;
+       u8 rs_moreaggr;
+       u8 rs_num_delims;
+       u8 rs_flags;
+       bool is_mybeacon;
+       u32 evm0;
+       u32 evm1;
+       u32 evm2;
+       u32 evm3;
+       u32 evm4;
+};
+
+struct ath_htc_rx_status {
+       __be64 rs_tstamp;
+       __be16 rs_datalen;
+       u8 rs_status;
+       u8 rs_phyerr;
+       int8_t rs_rssi;
+       int8_t rs_rssi_ctl0;
+       int8_t rs_rssi_ctl1;
+       int8_t rs_rssi_ctl2;
+       int8_t rs_rssi_ext0;
+       int8_t rs_rssi_ext1;
+       int8_t rs_rssi_ext2;
+       u8 rs_keyix;
+       u8 rs_rate;
+       u8 rs_antenna;
+       u8 rs_more;
+       u8 rs_isaggr;
+       u8 rs_moreaggr;
+       u8 rs_num_delims;
+       u8 rs_flags;
+       u8 rs_dummy;
+       __be32 evm0;
+       __be32 evm1;
+       __be32 evm2;
+};
+
+#define ATH9K_RXERR_CRC           0x01
+#define ATH9K_RXERR_PHY           0x02
+#define ATH9K_RXERR_FIFO          0x04
+#define ATH9K_RXERR_DECRYPT       0x08
+#define ATH9K_RXERR_MIC           0x10
+#define ATH9K_RXERR_KEYMISS       0x20
+
+#define ATH9K_RX_MORE             0x01
+#define ATH9K_RX_MORE_AGGR        0x02
+#define ATH9K_RX_GI               0x04
+#define ATH9K_RX_2040             0x08
+#define ATH9K_RX_DELIM_CRC_PRE    0x10
+#define ATH9K_RX_DELIM_CRC_POST   0x20
+#define ATH9K_RX_DECRYPT_BUSY     0x40
+
+#define ATH9K_RXKEYIX_INVALID  ((u8)-1)
+#define ATH9K_TXKEYIX_INVALID  ((u8)-1)
+
+enum ath9k_phyerr {
+       ATH9K_PHYERR_UNDERRUN             = 0,  /* Transmit underrun */
+       ATH9K_PHYERR_TIMING               = 1,  /* Timing error */
+       ATH9K_PHYERR_PARITY               = 2,  /* Illegal parity */
+       ATH9K_PHYERR_RATE                 = 3,  /* Illegal rate */
+       ATH9K_PHYERR_LENGTH               = 4,  /* Illegal length */
+       ATH9K_PHYERR_RADAR                = 5,  /* Radar detect */
+       ATH9K_PHYERR_SERVICE              = 6,  /* Illegal service */
+       ATH9K_PHYERR_TOR                  = 7,  /* Transmit override receive */
+
+       ATH9K_PHYERR_OFDM_TIMING          = 17,
+       ATH9K_PHYERR_OFDM_SIGNAL_PARITY   = 18,
+       ATH9K_PHYERR_OFDM_RATE_ILLEGAL    = 19,
+       ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL  = 20,
+       ATH9K_PHYERR_OFDM_POWER_DROP      = 21,
+       ATH9K_PHYERR_OFDM_SERVICE         = 22,
+       ATH9K_PHYERR_OFDM_RESTART         = 23,
+       ATH9K_PHYERR_FALSE_RADAR_EXT      = 24,
+
+       ATH9K_PHYERR_CCK_TIMING           = 25,
+       ATH9K_PHYERR_CCK_HEADER_CRC       = 26,
+       ATH9K_PHYERR_CCK_RATE_ILLEGAL     = 27,
+       ATH9K_PHYERR_CCK_SERVICE          = 30,
+       ATH9K_PHYERR_CCK_RESTART          = 31,
+       ATH9K_PHYERR_CCK_LENGTH_ILLEGAL   = 32,
+       ATH9K_PHYERR_CCK_POWER_DROP       = 33,
+
+       ATH9K_PHYERR_HT_CRC_ERROR         = 34,
+       ATH9K_PHYERR_HT_LENGTH_ILLEGAL    = 35,
+       ATH9K_PHYERR_HT_RATE_ILLEGAL      = 36,
+
+       ATH9K_PHYERR_MAX                  = 37,
+};
+
+struct ath_desc {
+       u32 ds_link;
+       u32 ds_data;
+       u32 ds_ctl0;
+       u32 ds_ctl1;
+       u32 ds_hw[20];
+       void *ds_vdata;
+} __packed __aligned(4);
+
+#define ATH9K_TXDESC_NOACK             0x0002
+#define ATH9K_TXDESC_RTSENA            0x0004
+#define ATH9K_TXDESC_CTSENA            0x0008
+/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for
+ * the descriptor its marked on.  We take a tx interrupt to reap
+ * descriptors when the h/w hits an EOL condition or
+ * when the descriptor is specifically marked to generate
+ * an interrupt with this flag. Descriptors should be
+ * marked periodically to insure timely replenishing of the
+ * supply needed for sending frames. Defering interrupts
+ * reduces system load and potentially allows more concurrent
+ * work to be done but if done to aggressively can cause
+ * senders to backup. When the hardware queue is left too
+ * large rate control information may also be too out of
+ * date. An Alternative for this is TX interrupt mitigation
+ * but this needs more testing. */
+#define ATH9K_TXDESC_INTREQ            0x0010
+#define ATH9K_TXDESC_VEOL              0x0020
+#define ATH9K_TXDESC_EXT_ONLY          0x0040
+#define ATH9K_TXDESC_EXT_AND_CTL       0x0080
+#define ATH9K_TXDESC_VMF               0x0100
+#define ATH9K_TXDESC_FRAG_IS_ON        0x0200
+#define ATH9K_TXDESC_LOWRXCHAIN                0x0400
+#define ATH9K_TXDESC_LDPC              0x0800
+#define ATH9K_TXDESC_CLRDMASK          0x1000
+
+#define ATH9K_TXDESC_PAPRD             0x70000
+#define ATH9K_TXDESC_PAPRD_S           16
+
+#define ATH9K_RXDESC_INTREQ            0x0020
+
+struct ar5416_desc {
+       u32 ds_link;
+       u32 ds_data;
+       u32 ds_ctl0;
+       u32 ds_ctl1;
+       union {
+               struct {
+                       u32 ctl2;
+                       u32 ctl3;
+                       u32 ctl4;
+                       u32 ctl5;
+                       u32 ctl6;
+                       u32 ctl7;
+                       u32 ctl8;
+                       u32 ctl9;
+                       u32 ctl10;
+                       u32 ctl11;
+                       u32 status0;
+                       u32 status1;
+                       u32 status2;
+                       u32 status3;
+                       u32 status4;
+                       u32 status5;
+                       u32 status6;
+                       u32 status7;
+                       u32 status8;
+                       u32 status9;
+               } tx;
+               struct {
+                       u32 status0;
+                       u32 status1;
+                       u32 status2;
+                       u32 status3;
+                       u32 status4;
+                       u32 status5;
+                       u32 status6;
+                       u32 status7;
+                       u32 status8;
+               } rx;
+       } u;
+} __packed __aligned(4);
+
+#define AR5416DESC(_ds)         ((struct ar5416_desc *)(_ds))
+#define AR5416DESC_CONST(_ds)   ((const struct ar5416_desc *)(_ds))
+
+#define ds_ctl2     u.tx.ctl2
+#define ds_ctl3     u.tx.ctl3
+#define ds_ctl4     u.tx.ctl4
+#define ds_ctl5     u.tx.ctl5
+#define ds_ctl6     u.tx.ctl6
+#define ds_ctl7     u.tx.ctl7
+#define ds_ctl8     u.tx.ctl8
+#define ds_ctl9     u.tx.ctl9
+#define ds_ctl10    u.tx.ctl10
+#define ds_ctl11    u.tx.ctl11
+
+#define ds_txstatus0    u.tx.status0
+#define ds_txstatus1    u.tx.status1
+#define ds_txstatus2    u.tx.status2
+#define ds_txstatus3    u.tx.status3
+#define ds_txstatus4    u.tx.status4
+#define ds_txstatus5    u.tx.status5
+#define ds_txstatus6    u.tx.status6
+#define ds_txstatus7    u.tx.status7
+#define ds_txstatus8    u.tx.status8
+#define ds_txstatus9    u.tx.status9
+
+#define ds_rxstatus0    u.rx.status0
+#define ds_rxstatus1    u.rx.status1
+#define ds_rxstatus2    u.rx.status2
+#define ds_rxstatus3    u.rx.status3
+#define ds_rxstatus4    u.rx.status4
+#define ds_rxstatus5    u.rx.status5
+#define ds_rxstatus6    u.rx.status6
+#define ds_rxstatus7    u.rx.status7
+#define ds_rxstatus8    u.rx.status8
+
+#define AR_FrameLen         0x00000fff
+#define AR_VirtMoreFrag     0x00001000
+#define AR_TxCtlRsvd00      0x0000e000
+#define AR_XmitPower        0x003f0000
+#define AR_XmitPower_S      16
+#define AR_RTSEnable        0x00400000
+#define AR_VEOL             0x00800000
+#define AR_ClrDestMask      0x01000000
+#define AR_TxCtlRsvd01      0x1e000000
+#define AR_TxIntrReq        0x20000000
+#define AR_DestIdxValid     0x40000000
+#define AR_CTSEnable        0x80000000
+
+#define AR_TxMore           0x00001000
+#define AR_DestIdx          0x000fe000
+#define AR_DestIdx_S        13
+#define AR_FrameType        0x00f00000
+#define AR_FrameType_S      20
+#define AR_NoAck            0x01000000
+#define AR_InsertTS         0x02000000
+#define AR_CorruptFCS       0x04000000
+#define AR_ExtOnly          0x08000000
+#define AR_ExtAndCtl        0x10000000
+#define AR_MoreAggr         0x20000000
+#define AR_IsAggr           0x40000000
+
+#define AR_BurstDur         0x00007fff
+#define AR_BurstDur_S       0
+#define AR_DurUpdateEna     0x00008000
+#define AR_XmitDataTries0   0x000f0000
+#define AR_XmitDataTries0_S 16
+#define AR_XmitDataTries1   0x00f00000
+#define AR_XmitDataTries1_S 20
+#define AR_XmitDataTries2   0x0f000000
+#define AR_XmitDataTries2_S 24
+#define AR_XmitDataTries3   0xf0000000
+#define AR_XmitDataTries3_S 28
+
+#define AR_XmitRate0        0x000000ff
+#define AR_XmitRate0_S      0
+#define AR_XmitRate1        0x0000ff00
+#define AR_XmitRate1_S      8
+#define AR_XmitRate2        0x00ff0000
+#define AR_XmitRate2_S      16
+#define AR_XmitRate3        0xff000000
+#define AR_XmitRate3_S      24
+
+#define AR_PacketDur0       0x00007fff
+#define AR_PacketDur0_S     0
+#define AR_RTSCTSQual0      0x00008000
+#define AR_PacketDur1       0x7fff0000
+#define AR_PacketDur1_S     16
+#define AR_RTSCTSQual1      0x80000000
+
+#define AR_PacketDur2       0x00007fff
+#define AR_PacketDur2_S     0
+#define AR_RTSCTSQual2      0x00008000
+#define AR_PacketDur3       0x7fff0000
+#define AR_PacketDur3_S     16
+#define AR_RTSCTSQual3      0x80000000
+
+#define AR_AggrLen          0x0000ffff
+#define AR_AggrLen_S        0
+#define AR_TxCtlRsvd60      0x00030000
+#define AR_PadDelim         0x03fc0000
+#define AR_PadDelim_S       18
+#define AR_EncrType         0x0c000000
+#define AR_EncrType_S       26
+#define AR_TxCtlRsvd61      0xf0000000
+#define AR_LDPC             0x80000000
+
+#define AR_2040_0           0x00000001
+#define AR_GI0              0x00000002
+#define AR_ChainSel0        0x0000001c
+#define AR_ChainSel0_S      2
+#define AR_2040_1           0x00000020
+#define AR_GI1              0x00000040
+#define AR_ChainSel1        0x00000380
+#define AR_ChainSel1_S      7
+#define AR_2040_2           0x00000400
+#define AR_GI2              0x00000800
+#define AR_ChainSel2        0x00007000
+#define AR_ChainSel2_S      12
+#define AR_2040_3           0x00008000
+#define AR_GI3              0x00010000
+#define AR_ChainSel3        0x000e0000
+#define AR_ChainSel3_S      17
+#define AR_RTSCTSRate       0x0ff00000
+#define AR_RTSCTSRate_S     20
+#define AR_STBC0            0x10000000
+#define AR_STBC1            0x20000000
+#define AR_STBC2            0x40000000
+#define AR_STBC3            0x80000000
+
+#define AR_TxRSSIAnt00      0x000000ff
+#define AR_TxRSSIAnt00_S    0
+#define AR_TxRSSIAnt01      0x0000ff00
+#define AR_TxRSSIAnt01_S    8
+#define AR_TxRSSIAnt02      0x00ff0000
+#define AR_TxRSSIAnt02_S    16
+#define AR_TxStatusRsvd00   0x3f000000
+#define AR_TxBaStatus       0x40000000
+#define AR_TxStatusRsvd01   0x80000000
+
+/*
+ * AR_FrmXmitOK - Frame transmission success flag. If set, the frame was
+ * transmitted successfully. If clear, no ACK or BA was received to indicate
+ * successful transmission when we were expecting an ACK or BA.
+ */
+#define AR_FrmXmitOK            0x00000001
+#define AR_ExcessiveRetries     0x00000002
+#define AR_FIFOUnderrun         0x00000004
+#define AR_Filtered             0x00000008
+#define AR_RTSFailCnt           0x000000f0
+#define AR_RTSFailCnt_S         4
+#define AR_DataFailCnt          0x00000f00
+#define AR_DataFailCnt_S        8
+#define AR_VirtRetryCnt         0x0000f000
+#define AR_VirtRetryCnt_S       12
+#define AR_TxDelimUnderrun      0x00010000
+#define AR_TxDataUnderrun       0x00020000
+#define AR_DescCfgErr           0x00040000
+#define AR_TxTimerExpired       0x00080000
+#define AR_TxStatusRsvd10       0xfff00000
+
+#define AR_SendTimestamp    ds_txstatus2
+#define AR_BaBitmapLow      ds_txstatus3
+#define AR_BaBitmapHigh     ds_txstatus4
+
+#define AR_TxRSSIAnt10      0x000000ff
+#define AR_TxRSSIAnt10_S    0
+#define AR_TxRSSIAnt11      0x0000ff00
+#define AR_TxRSSIAnt11_S    8
+#define AR_TxRSSIAnt12      0x00ff0000
+#define AR_TxRSSIAnt12_S    16
+#define AR_TxRSSICombined   0xff000000
+#define AR_TxRSSICombined_S 24
+
+#define AR_TxTid       0xf0000000
+#define AR_TxTid_S     28
+
+#define AR_TxEVM0           ds_txstatus5
+#define AR_TxEVM1           ds_txstatus6
+#define AR_TxEVM2           ds_txstatus7
+
+#define AR_TxDone           0x00000001
+#define AR_SeqNum           0x00001ffe
+#define AR_SeqNum_S         1
+#define AR_TxStatusRsvd80   0x0001e000
+#define AR_TxOpExceeded     0x00020000
+#define AR_TxStatusRsvd81   0x001c0000
+#define AR_FinalTxIdx       0x00600000
+#define AR_FinalTxIdx_S     21
+#define AR_TxStatusRsvd82   0x01800000
+#define AR_PowerMgmt        0x02000000
+#define AR_TxStatusRsvd83   0xfc000000
+
+#define AR_RxCTLRsvd00  0xffffffff
+
+#define AR_RxCtlRsvd00  0x00001000
+#define AR_RxIntrReq    0x00002000
+#define AR_RxCtlRsvd01  0xffffc000
+
+#define AR_RxRSSIAnt00      0x000000ff
+#define AR_RxRSSIAnt00_S    0
+#define AR_RxRSSIAnt01      0x0000ff00
+#define AR_RxRSSIAnt01_S    8
+#define AR_RxRSSIAnt02      0x00ff0000
+#define AR_RxRSSIAnt02_S    16
+#define AR_RxRate           0xff000000
+#define AR_RxRate_S         24
+#define AR_RxStatusRsvd00   0xff000000
+
+#define AR_DataLen          0x00000fff
+#define AR_RxMore           0x00001000
+#define AR_NumDelim         0x003fc000
+#define AR_NumDelim_S       14
+#define AR_RxStatusRsvd10   0xff800000
+
+#define AR_RcvTimestamp     ds_rxstatus2
+
+#define AR_GI               0x00000001
+#define AR_2040             0x00000002
+#define AR_Parallel40       0x00000004
+#define AR_Parallel40_S     2
+#define AR_RxStatusRsvd30   0x000000f8
+#define AR_RxAntenna       0xffffff00
+#define AR_RxAntenna_S     8
+
+#define AR_RxRSSIAnt10            0x000000ff
+#define AR_RxRSSIAnt10_S          0
+#define AR_RxRSSIAnt11            0x0000ff00
+#define AR_RxRSSIAnt11_S          8
+#define AR_RxRSSIAnt12            0x00ff0000
+#define AR_RxRSSIAnt12_S          16
+#define AR_RxRSSICombined         0xff000000
+#define AR_RxRSSICombined_S       24
+
+#define AR_RxEVM0           ds_rxstatus4
+#define AR_RxEVM1           ds_rxstatus5
+#define AR_RxEVM2           ds_rxstatus6
+
+#define AR_RxDone           0x00000001
+#define AR_RxFrameOK        0x00000002
+#define AR_CRCErr           0x00000004
+#define AR_DecryptCRCErr    0x00000008
+#define AR_PHYErr           0x00000010
+#define AR_MichaelErr       0x00000020
+#define AR_PreDelimCRCErr   0x00000040
+#define AR_RxStatusRsvd70   0x00000080
+#define AR_RxKeyIdxValid    0x00000100
+#define AR_KeyIdx           0x0000fe00
+#define AR_KeyIdx_S         9
+#define AR_PHYErrCode       0x0000ff00
+#define AR_PHYErrCode_S     8
+#define AR_RxMoreAggr       0x00010000
+#define AR_RxAggr           0x00020000
+#define AR_PostDelimCRCErr  0x00040000
+#define AR_RxStatusRsvd71   0x3ff80000
+#define AR_DecryptBusyErr   0x40000000
+#define AR_KeyMiss          0x80000000
+
+enum ath9k_tx_queue {
+       ATH9K_TX_QUEUE_INACTIVE = 0,
+       ATH9K_TX_QUEUE_DATA,
+       ATH9K_TX_QUEUE_BEACON,
+       ATH9K_TX_QUEUE_CAB,
+       ATH9K_TX_QUEUE_UAPSD,
+       ATH9K_TX_QUEUE_PSPOLL
+};
+
+#define        ATH9K_NUM_TX_QUEUES 10
+
+/* Used as a queue subtype instead of a WMM AC */
+#define ATH9K_WME_UPSD 4
+
+enum ath9k_tx_queue_flags {
+       TXQ_FLAG_TXINT_ENABLE = 0x0001,
+       TXQ_FLAG_TXDESCINT_ENABLE = 0x0002,
+       TXQ_FLAG_TXEOLINT_ENABLE = 0x0004,
+       TXQ_FLAG_TXURNINT_ENABLE = 0x0008,
+       TXQ_FLAG_BACKOFF_DISABLE = 0x0010,
+       TXQ_FLAG_COMPRESSION_ENABLE = 0x0020,
+       TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040,
+       TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080,
+};
+
+#define ATH9K_TXQ_USEDEFAULT ((u32) -1)
+#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001
+
+#define ATH9K_DECOMP_MASK_SIZE     128
+#define ATH9K_READY_TIME_LO_BOUND  50
+#define ATH9K_READY_TIME_HI_BOUND  96
+
+enum ath9k_pkt_type {
+       ATH9K_PKT_TYPE_NORMAL = 0,
+       ATH9K_PKT_TYPE_ATIM,
+       ATH9K_PKT_TYPE_PSPOLL,
+       ATH9K_PKT_TYPE_BEACON,
+       ATH9K_PKT_TYPE_PROBE_RESP,
+       ATH9K_PKT_TYPE_CHIRP,
+       ATH9K_PKT_TYPE_GRP_POLL,
+};
+
+struct ath9k_tx_queue_info {
+       u32 tqi_ver;
+       enum ath9k_tx_queue tqi_type;
+       int tqi_subtype;
+       enum ath9k_tx_queue_flags tqi_qflags;
+       u32 tqi_priority;
+       u32 tqi_aifs;
+       u32 tqi_cwmin;
+       u32 tqi_cwmax;
+       u16 tqi_shretry;
+       u16 tqi_lgretry;
+       u32 tqi_cbrPeriod;
+       u32 tqi_cbrOverflowLimit;
+       u32 tqi_burstTime;
+       u32 tqi_readyTime;
+       u32 tqi_physCompBuf;
+       u32 tqi_intFlags;
+};
+
+enum ath9k_rx_filter {
+       ATH9K_RX_FILTER_UCAST = 0x00000001,
+       ATH9K_RX_FILTER_MCAST = 0x00000002,
+       ATH9K_RX_FILTER_BCAST = 0x00000004,
+       ATH9K_RX_FILTER_CONTROL = 0x00000008,
+       ATH9K_RX_FILTER_BEACON = 0x00000010,
+       ATH9K_RX_FILTER_PROM = 0x00000020,
+       ATH9K_RX_FILTER_PROBEREQ = 0x00000080,
+       ATH9K_RX_FILTER_PHYERR = 0x00000100,
+       ATH9K_RX_FILTER_MYBEACON = 0x00000200,
+       ATH9K_RX_FILTER_COMP_BAR = 0x00000400,
+       ATH9K_RX_FILTER_COMP_BA = 0x00000800,
+       ATH9K_RX_FILTER_UNCOMP_BA_BAR = 0x00001000,
+       ATH9K_RX_FILTER_PSPOLL = 0x00004000,
+       ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
+       ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
+       ATH9K_RX_FILTER_CONTROL_WRAPPER = 0x00080000,
+};
+
+#define ATH9K_RATESERIES_RTS_CTS  0x0001
+#define ATH9K_RATESERIES_2040     0x0002
+#define ATH9K_RATESERIES_HALFGI   0x0004
+#define ATH9K_RATESERIES_STBC     0x0008
+
+struct ath9k_11n_rate_series {
+       u32 Tries;
+       u32 Rate;
+       u32 PktDuration;
+       u32 ChSel;
+       u32 RateFlags;
+};
+
+enum aggr_type {
+       AGGR_BUF_NONE,
+       AGGR_BUF_FIRST,
+       AGGR_BUF_MIDDLE,
+       AGGR_BUF_LAST,
+};
+
+enum ath9k_key_type {
+       ATH9K_KEY_TYPE_CLEAR,
+       ATH9K_KEY_TYPE_WEP,
+       ATH9K_KEY_TYPE_AES,
+       ATH9K_KEY_TYPE_TKIP,
+};
+
+struct ath_tx_info {
+       u8 qcu;
+
+       bool is_first;
+       bool is_last;
+
+       enum aggr_type aggr;
+       u8 ndelim;
+       u16 aggr_len;
+
+       dma_addr_t link;
+       int pkt_len;
+       u32 flags;
+
+       dma_addr_t buf_addr[4];
+       int buf_len[4];
+
+       struct ath9k_11n_rate_series rates[4];
+       u8 rtscts_rate;
+       bool dur_update;
+
+       enum ath9k_pkt_type type;
+       enum ath9k_key_type keytype;
+       u8 keyix;
+       u8 txpower;
+};
+
+struct ath_hw;
+struct ath9k_channel;
+enum ath9k_int;
+
+u32 ath9k_btcoex_ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
+void ath9k_btcoex_ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
+void ath9k_btcoex_ath9k_hw_txstart(struct ath_hw *ah, u32 q);
+u32 ath9k_btcoex_ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
+bool ath9k_btcoex_ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
+bool ath9k_btcoex_ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
+void ath9k_btcoex_ath9k_hw_abort_tx_dma(struct ath_hw *ah);
+bool ath9k_btcoex_ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
+                           const struct ath9k_tx_queue_info *qinfo);
+bool ath9k_btcoex_ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
+                           struct ath9k_tx_queue_info *qinfo);
+int ath9k_btcoex_ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
+                         const struct ath9k_tx_queue_info *qinfo);
+bool ath9k_btcoex_ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
+bool ath9k_btcoex_ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
+int ath9k_btcoex_ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
+                       struct ath_rx_status *rs);
+void ath9k_btcoex_ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
+                         u32 size, u32 flags);
+bool ath9k_btcoex_ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
+void ath9k_btcoex_ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
+void ath9k_btcoex_ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning);
+void ath9k_btcoex_ath9k_hw_abortpcurecv(struct ath_hw *ah);
+bool ath9k_btcoex_ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset);
+int ath9k_btcoex_ath9k_hw_beaconq_setup(struct ath_hw *ah);
+
+/* Interrupt Handling */
+bool ath9k_btcoex_ath9k_hw_intrpend(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_set_interrupts(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_enable_interrupts(struct ath_hw *ah);
+void ath9k_btcoex_ath9k_hw_disable_interrupts(struct ath_hw *ah);
+
+void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
+
+#endif /* MAC_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/main.c b/drivers/net/wireless/ath/ath9k_btcoex/main.c
new file mode 100644 (file)
index 0000000..8ce743b
--- /dev/null
@@ -0,0 +1,2647 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/delay.h>
+#include "ath9k.h"
+#include "btcoex.h"
+
+static void ath9k_set_assoc_state(struct ath_softc *sc,
+                                 struct ieee80211_vif *vif);
+
+u8 ath9k_parse_mpdudensity(u8 mpdudensity)
+{
+       /*
+        * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
+        *   0 for no restriction
+        *   1 for 1/4 us
+        *   2 for 1/2 us
+        *   3 for 1 us
+        *   4 for 2 us
+        *   5 for 4 us
+        *   6 for 8 us
+        *   7 for 16 us
+        */
+       switch (mpdudensity) {
+       case 0:
+               return 0;
+       case 1:
+       case 2:
+       case 3:
+               /* Our lower layer calculations limit our precision to
+                  1 microsecond */
+               return 1;
+       case 4:
+               return 2;
+       case 5:
+               return 4;
+       case 6:
+               return 8;
+       case 7:
+               return 16;
+       default:
+               return 0;
+       }
+}
+
+static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
+{
+       bool pending = false;
+
+       spin_lock_bh(&txq->axq_lock);
+
+       if (txq->axq_depth || !list_empty(&txq->axq_acq))
+               pending = true;
+
+       spin_unlock_bh(&txq->axq_lock);
+       return pending;
+}
+
+static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
+{
+       unsigned long flags;
+       bool ret;
+
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+       ret = ath9k_btcoex_ath9k_hw_setpower(sc->sc_ah, mode);
+       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+
+       return ret;
+}
+
+void ath9k_ps_wakeup(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       unsigned long flags;
+       enum ath9k_power_mode power_mode;
+
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+       if (++sc->ps_usecount != 1)
+               goto unlock;
+
+       power_mode = sc->sc_ah->power_mode;
+       ath9k_btcoex_ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
+
+       /*
+        * While the hardware is asleep, the cycle counters contain no
+        * useful data. Better clear them now so that they don't mess up
+        * survey data results.
+        */
+       if (power_mode != ATH9K_PM_AWAKE) {
+               spin_lock(&common->cc_lock);
+               ath_hw_cycle_counters_update(common);
+               memset(&common->cc_survey, 0, sizeof(common->cc_survey));
+               memset(&common->cc_ani, 0, sizeof(common->cc_ani));
+               spin_unlock(&common->cc_lock);
+       }
+
+ unlock:
+       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+}
+
+void ath9k_ps_restore(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       enum ath9k_power_mode mode;
+       unsigned long flags;
+       bool reset;
+
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+       if (--sc->ps_usecount != 0)
+               goto unlock;
+
+       if (sc->ps_idle) {
+               ath9k_btcoex_ath9k_hw_setrxabort(sc->sc_ah, 1);
+               ath9k_btcoex_ath9k_hw_stopdmarecv(sc->sc_ah, &reset);
+               mode = ATH9K_PM_FULL_SLEEP;
+       } else if (sc->ps_enabled &&
+                  !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
+                                    PS_WAIT_FOR_CAB |
+                                    PS_WAIT_FOR_PSPOLL_DATA |
+                                    PS_WAIT_FOR_TX_ACK))) {
+               mode = ATH9K_PM_NETWORK_SLEEP;
+               if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
+                       ath9k_btcoex_stop_gen_timer(sc);
+       } else {
+               goto unlock;
+       }
+
+       spin_lock(&common->cc_lock);
+       ath_hw_cycle_counters_update(common);
+       spin_unlock(&common->cc_lock);
+
+       ath9k_btcoex_ath9k_hw_setpower(sc->sc_ah, mode);
+
+ unlock:
+       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+}
+
+void ath_start_ani(struct ath_common *common)
+{
+       struct ath_hw *ah = common->ah;
+       unsigned long timestamp = jiffies_to_msecs(jiffies);
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+       if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags))
+               return;
+
+       if (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
+               return;
+
+       common->ani.longcal_timer = timestamp;
+       common->ani.shortcal_timer = timestamp;
+       common->ani.checkani_timer = timestamp;
+
+       mod_timer(&common->ani.timer,
+                 jiffies +
+                       msecs_to_jiffies((u32)ah->config.ani_poll_interval));
+}
+
+static void ath_update_survey_nf(struct ath_softc *sc, int channel)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath9k_channel *chan = &ah->channels[channel];
+       struct survey_info *survey = &sc->survey[channel];
+
+       if (chan->noisefloor) {
+               survey->filled |= SURVEY_INFO_NOISE_DBM;
+               survey->noise = ath9k_btcoex_ath9k_hw_getchan_noise(ah, chan);
+       }
+}
+
+/*
+ * Updates the survey statistics and returns the busy time since last
+ * update in %, if the measurement duration was long enough for the
+ * result to be useful, -1 otherwise.
+ */
+static int ath_update_survey_stats(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       int pos = ah->curchan - &ah->channels[0];
+       struct survey_info *survey = &sc->survey[pos];
+       struct ath_cycle_counters *cc = &common->cc_survey;
+       unsigned int div = common->clockrate * 1000;
+       int ret = 0;
+
+       if (!ah->curchan)
+               return -1;
+
+       if (ah->power_mode == ATH9K_PM_AWAKE)
+               ath_hw_cycle_counters_update(common);
+
+       if (cc->cycles > 0) {
+               survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+                       SURVEY_INFO_CHANNEL_TIME_BUSY |
+                       SURVEY_INFO_CHANNEL_TIME_RX |
+                       SURVEY_INFO_CHANNEL_TIME_TX;
+               survey->channel_time += cc->cycles / div;
+               survey->channel_time_busy += cc->rx_busy / div;
+               survey->channel_time_rx += cc->rx_frame / div;
+               survey->channel_time_tx += cc->tx_frame / div;
+       }
+
+       if (cc->cycles < div)
+               return -1;
+
+       if (cc->cycles > 0)
+               ret = cc->rx_busy * 100 / cc->cycles;
+
+       memset(cc, 0, sizeof(*cc));
+
+       ath_update_survey_nf(sc, pos);
+
+       return ret;
+}
+
+static void __ath_cancel_work(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (test_bit(SC_OP_INVALID, &sc->sc_flags))
+               return;
+
+       sc->hw_busy_count = 0;
+
+       del_timer_sync(&common->ani.timer);
+       del_timer_sync(&sc->rx_poll_timer);
+       cancel_work_sync(&sc->paprd_work);
+       cancel_work_sync(&sc->hw_check_work);
+       cancel_work_sync(&sc->hw_reset_work);
+       cancel_delayed_work_sync(&sc->tx_complete_work);
+       cancel_delayed_work_sync(&sc->hw_pll_work);
+
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+       if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+               cancel_work_sync(&sc->mci_work);
+#endif
+}
+
+static void ath_cancel_work(struct ath_softc *sc)
+{
+       __ath_cancel_work(sc);
+}
+
+static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       bool ret = true;
+
+       ieee80211_stop_queues(sc->hw);
+
+       sc->hw_busy_count = 0;
+       del_timer_sync(&common->ani.timer);
+
+       ath9k_debug_samp_bb_mac(sc);
+       ath9k_btcoex_ath9k_hw_disable_interrupts(ah);
+
+       if (!ath_stoprecv(sc))
+               ret = false;
+
+       if (!ath_drain_all_txq(sc, retry_tx))
+               ret = false;
+
+       if (!flush) {
+               if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+                       ath_rx_tasklet(sc, 1, true);
+               ath_rx_tasklet(sc, 1, false);
+       } else {
+               ath_flushrecv(sc);
+       }
+
+       return ret;
+}
+
+static bool ath_complete_reset(struct ath_softc *sc, bool start)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       unsigned long flags;
+
+       if (ath_startrecv(sc) != 0) {
+               ath_err(common, "Unable to restart recv logic\n");
+               return false;
+       }
+
+       ath9k_btcoex_ath9k_cmn_update_txpow(ah, sc->curtxpow,
+                              sc->config.txpowlimit, &sc->curtxpow);
+       ath9k_btcoex_ath9k_hw_set_interrupts(ah);
+       ath9k_btcoex_ath9k_hw_enable_interrupts(ah);
+
+       if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && start) {
+               if (test_bit(SC_OP_BEACONS, &sc->sc_flags)) {
+                       if (ah->opmode == NL80211_IFTYPE_AP) {
+                               ath9k_set_beacon(sc);
+                       } else if (ah->opmode == NL80211_IFTYPE_ADHOC) {
+                               sc->ps_flags |= PS_BEACON_SYNC |
+                                               PS_WAIT_FOR_BEACON;
+                               ath9k_set_beacon(sc);
+                       } else {
+                               sc->ps_flags |= PS_BEACON_SYNC |
+                                               PS_WAIT_FOR_BEACON;
+                       }
+               }
+
+               ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+               ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
+               if (!common->disable_ani)
+                       ath_start_ani(common);
+               ath_start_rx_poll(sc, 100);
+       }
+
+       if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3)
+               ath_ant_comb_update(sc);
+
+       ieee80211_wake_queues(sc->hw);
+
+       spin_lock_irqsave(&sc->sc_bb_lock, flags);
+       clear_bit(SC_OP_BB_WATCHDOG, &sc->sc_flags);
+       spin_unlock_irqrestore(&sc->sc_bb_lock, flags);
+
+       return true;
+}
+
+static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
+                             bool retry_tx)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_cal_data *caldata = NULL;
+       bool fastcc = true;
+       bool flush = false;
+       int r;
+
+       __ath_cancel_work(sc);
+
+       spin_lock_bh(&sc->sc_pcu_lock);
+
+       if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
+               fastcc = false;
+               caldata = &sc->caldata;
+       }
+
+       if (!hchan) {
+               fastcc = false;
+               flush = true;
+               hchan = ah->curchan;
+       }
+
+       if (!ath_prepare_reset(sc, retry_tx, flush))
+               fastcc = false;
+
+       ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
+               hchan->channel, IS_CHAN_HT40(hchan), fastcc);
+
+       r = ath9k_btcoex_ath9k_hw_reset(ah, hchan, caldata, fastcc);
+       if (r) {
+               ath_err(common,
+                       "Unable to reset channel, reset status %d\n", r);
+               goto out;
+       }
+
+       if (!ath_complete_reset(sc, true))
+               r = -EIO;
+
+out:
+       spin_unlock_bh(&sc->sc_pcu_lock);
+       return r;
+}
+
+
+/*
+ * Set/change channels.  If the channel is really being changed, it's done
+ * by reseting the chip.  To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+*/
+static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+                   struct ath9k_channel *hchan)
+{
+       int r;
+
+       if (test_bit(SC_OP_INVALID, &sc->sc_flags))
+               return -EIO;
+
+       r = ath_reset_internal(sc, hchan, false);
+
+       return r;
+}
+
+static void ath_paprd_activate(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+       int chain;
+
+       if (!caldata || !caldata->paprd_done)
+               return;
+
+       ath9k_ps_wakeup(sc);
+       ath9k_btcoex_ar9003_paprd_enable(ah, false);
+       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+               if (!(ah->txchainmask & BIT(chain)))
+                       continue;
+
+               ath9k_btcoex_ar9003_paprd_populate_single_table(ah, caldata, chain);
+       }
+
+       ath9k_btcoex_ar9003_paprd_enable(ah, true);
+       ath9k_ps_restore(sc);
+}
+
+static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain)
+{
+       struct ieee80211_hw *hw = sc->hw;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_tx_control txctl;
+       int time_left;
+
+       memset(&txctl, 0, sizeof(txctl));
+       txctl.txq = sc->tx.txq_map[WME_AC_BE];
+
+       memset(tx_info, 0, sizeof(*tx_info));
+       tx_info->band = hw->conf.channel->band;
+       tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
+       tx_info->control.rates[0].idx = 0;
+       tx_info->control.rates[0].count = 1;
+       tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
+       tx_info->control.rates[1].idx = -1;
+
+       init_completion(&sc->paprd_complete);
+       txctl.paprd = BIT(chain);
+
+       if (ath_tx_start(hw, skb, &txctl) != 0) {
+               ath_dbg(common, CALIBRATE, "PAPRD TX failed\n");
+               dev_kfree_skb_any(skb);
+               return false;
+       }
+
+       time_left = wait_for_completion_timeout(&sc->paprd_complete,
+                       msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
+
+       if (!time_left)
+               ath_dbg(common, CALIBRATE,
+                       "Timeout waiting for paprd training on TX chain %d\n",
+                       chain);
+
+       return !!time_left;
+}
+
+void ath_paprd_calibrate(struct work_struct *work)
+{
+       struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work);
+       struct ieee80211_hw *hw = sc->hw;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ieee80211_hdr *hdr;
+       struct sk_buff *skb = NULL;
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+       struct ath_common *common = ath9k_hw_common(ah);
+       int ftype;
+       int chain_ok = 0;
+       int chain;
+       int len = 1800;
+
+       if (!caldata)
+               return;
+
+       ath9k_ps_wakeup(sc);
+
+       if (ath9k_btcoex_ar9003_paprd_init_table(ah) < 0)
+               goto fail_paprd;
+
+       skb = alloc_skb(len, GFP_KERNEL);
+       if (!skb)
+               goto fail_paprd;
+
+       skb_put(skb, len);
+       memset(skb->data, 0, len);
+       hdr = (struct ieee80211_hdr *)skb->data;
+       ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC;
+       hdr->frame_control = cpu_to_le16(ftype);
+       hdr->duration_id = cpu_to_le16(10);
+       memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN);
+       memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
+       memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
+
+       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+               if (!(ah->txchainmask & BIT(chain)))
+                       continue;
+
+               chain_ok = 0;
+
+               ath_dbg(common, CALIBRATE,
+                       "Sending PAPRD frame for thermal measurement on chain %d\n",
+                       chain);
+               if (!ath_paprd_send_frame(sc, skb, chain))
+                       goto fail_paprd;
+
+               ath9k_btcoex_ar9003_paprd_setup_gain_table(ah, chain);
+
+               ath_dbg(common, CALIBRATE,
+                       "Sending PAPRD training frame on chain %d\n", chain);
+               if (!ath_paprd_send_frame(sc, skb, chain))
+                       goto fail_paprd;
+
+               if (!ath9k_btcoex_ar9003_paprd_is_done(ah)) {
+                       ath_dbg(common, CALIBRATE,
+                               "PAPRD not yet done on chain %d\n", chain);
+                       break;
+               }
+
+               if (ath9k_btcoex_ar9003_paprd_create_curve(ah, caldata, chain)) {
+                       ath_dbg(common, CALIBRATE,
+                               "PAPRD create curve failed on chain %d\n",
+                                                                  chain);
+                       break;
+               }
+
+               chain_ok = 1;
+       }
+       kfree_skb(skb);
+
+       if (chain_ok) {
+               caldata->paprd_done = true;
+               ath_paprd_activate(sc);
+       }
+
+fail_paprd:
+       ath9k_ps_restore(sc);
+}
+
+/*
+ *  This routine performs the periodic noise floor calibration function
+ *  that is used to adjust and optimize the chip performance.  This
+ *  takes environmental changes (location, temperature) into account.
+ *  When the task is complete, it reschedules itself depending on the
+ *  appropriate interval that was calculated.
+ */
+void ath_ani_calibrate(unsigned long data)
+{
+       struct ath_softc *sc = (struct ath_softc *)data;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       bool longcal = false;
+       bool shortcal = false;
+       bool aniflag = false;
+       unsigned int timestamp = jiffies_to_msecs(jiffies);
+       u32 cal_interval, short_cal_interval, long_cal_interval;
+       unsigned long flags;
+
+       if (ah->caldata && ah->caldata->nfcal_interference)
+               long_cal_interval = ATH_LONG_CALINTERVAL_INT;
+       else
+               long_cal_interval = ATH_LONG_CALINTERVAL;
+
+       short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
+               ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
+
+       /* Only calibrate if awake */
+       if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
+               goto set_timer;
+
+       ath9k_ps_wakeup(sc);
+
+       /* Long calibration runs independently of short calibration. */
+       if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
+               longcal = true;
+               common->ani.longcal_timer = timestamp;
+       }
+
+       /* Short calibration applies only while caldone is false */
+       if (!common->ani.caldone) {
+               if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
+                       shortcal = true;
+                       common->ani.shortcal_timer = timestamp;
+                       common->ani.resetcal_timer = timestamp;
+               }
+       } else {
+               if ((timestamp - common->ani.resetcal_timer) >=
+                   ATH_RESTART_CALINTERVAL) {
+                       common->ani.caldone = ath9k_btcoex_ath9k_hw_reset_calvalid(ah);
+                       if (common->ani.caldone)
+                               common->ani.resetcal_timer = timestamp;
+               }
+       }
+
+       /* Verify whether we must check ANI */
+       if (sc->sc_ah->config.enable_ani
+           && (timestamp - common->ani.checkani_timer) >=
+           ah->config.ani_poll_interval) {
+               aniflag = true;
+               common->ani.checkani_timer = timestamp;
+       }
+
+       /* Call ANI routine if necessary */
+       if (aniflag) {
+               spin_lock_irqsave(&common->cc_lock, flags);
+               ath9k_btcoex_ath9k_hw_ani_monitor(ah, ah->curchan);
+               ath_update_survey_stats(sc);
+               spin_unlock_irqrestore(&common->cc_lock, flags);
+       }
+
+       /* Perform calibration if necessary */
+       if (longcal || shortcal) {
+               common->ani.caldone =
+                       ath9k_hw_calibrate(ah, ah->curchan,
+                                               ah->rxchainmask, longcal);
+       }
+
+       ath_dbg(common, ANI,
+               "Calibration @%lu finished: %s %s %s, caldone: %s\n",
+               jiffies,
+               longcal ? "long" : "", shortcal ? "short" : "",
+               aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
+
+       ath9k_debug_samp_bb_mac(sc);
+       ath9k_ps_restore(sc);
+
+set_timer:
+       /*
+       * Set timer interval based on previous results.
+       * The interval must be the shortest necessary to satisfy ANI,
+       * short calibration and long calibration.
+       */
+       cal_interval = ATH_LONG_CALINTERVAL;
+       if (sc->sc_ah->config.enable_ani)
+               cal_interval = min(cal_interval,
+                                  (u32)ah->config.ani_poll_interval);
+       if (!common->ani.caldone)
+               cal_interval = min(cal_interval, (u32)short_cal_interval);
+
+       mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
+       if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) {
+               if (!ah->caldata->paprd_done)
+                       ieee80211_queue_work(sc->hw, &sc->paprd_work);
+               else if (!ah->paprd_table_write_done)
+                       ath_paprd_activate(sc);
+       }
+}
+
+static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
+                           struct ieee80211_vif *vif)
+{
+       struct ath_node *an;
+       u8 density;
+       an = (struct ath_node *)sta->drv_priv;
+
+#ifdef CONFIG_ATH9K_DEBUGFS
+       spin_lock(&sc->nodes_lock);
+       list_add(&an->list, &sc->nodes);
+       spin_unlock(&sc->nodes_lock);
+#endif
+       an->sta = sta;
+       an->vif = vif;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+               ath_tx_node_init(sc, an);
+               an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
+                                    sta->ht_cap.ampdu_factor);
+               density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
+               an->mpdudensity = density;
+       }
+}
+
+static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
+{
+       struct ath_node *an = (struct ath_node *)sta->drv_priv;
+
+#ifdef CONFIG_ATH9K_DEBUGFS
+       spin_lock(&sc->nodes_lock);
+       list_del(&an->list);
+       spin_unlock(&sc->nodes_lock);
+       an->sta = NULL;
+#endif
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
+               ath_tx_node_cleanup(sc, an);
+}
+
+void ath_start_rx_poll(struct ath_softc *sc, u32 nmsec)
+{
+       if (!AR_SREV_9300(sc->sc_ah))
+               return;
+
+       if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
+               return;
+
+       mod_timer(&sc->rx_poll_timer, jiffies + msecs_to_jiffies(nmsec));
+}
+
+void ath_rx_poll_work(unsigned long data)
+{
+       struct ath_softc *sc = (struct ath_softc *)data;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_conf *conf = &common->hw->conf;
+       struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist;
+       static u32 iter, match_count;
+       static u64 last_run;
+       unsigned long flags;
+       u32 rx_clear, rx, tx, reg;
+       int i, j, len;
+       u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+       u8 nread, nmsec = 10, buf[200];
+
+       if (jiffies_to_msecs(jiffies - last_run) > 30)
+               iter = match_count = 0;
+       else
+               iter += 1;
+
+       ath9k_ps_wakeup(sc);
+
+       spin_lock_irqsave(&common->cc_lock, flags);
+       ath_hw_cycle_counters_update(common);
+
+       if (common->cc_rxpoll.cycles == 0) {
+               spin_unlock_irqrestore(&common->cc_lock, flags);
+               ath_info(common, "rxpoll cycles is zero.  Skipping.");
+               ath9k_ps_restore(sc);
+               ath_start_rx_poll(sc, nmsec);
+               return;
+       }
+
+       rx_clear = common->cc_rxpoll.rx_busy * 100 / common->cc_rxpoll.cycles;
+       rx = common->cc_rxpoll.rx_frame * 100 / common->cc_rxpoll.cycles;
+       tx = common->cc_rxpoll.tx_frame * 100 / common->cc_rxpoll.cycles;
+       memset(&common->cc_rxpoll, 0, sizeof(common->cc_rxpoll));
+       spin_unlock_irqrestore(&common->cc_lock, flags);
+
+       ath_dbg(common, RX_STUCK,
+               "--------------------------------------------------\n");
+       ath_dbg(common, RX_STUCK, "Iteration: %d\n", iter);
+       ath_dbg(common, RX_STUCK, "Cycle Counters:\n");
+       ath_dbg(common, RX_STUCK,
+               "rx_clear = %d%% rx_frame %d%% tx_frame %d%%\n",
+               rx_clear, rx, tx);
+
+       ath_dbg(common, RX_STUCK, "IMR %08x IER %08x intr_cnt %d\n",
+               REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER),
+               atomic_read(&ah->intr_ref_cnt));
+
+       ath_dbg(common, RX_STUCK, "ts tail %d\n", ah->ts_tail);
+
+       REG_SET_BIT(ah, AR_DIAG_SW, 0x8080000);
+       for (i = 0; i < 5; i++) {
+               ath_dbg(common, RX_STUCK,
+                       "OBS_BUS_1(0x806c) = %08x "
+                       "OBS_BUS_CTRL(0x8068) = %08x\n",
+                       REG_READ(ah, AR_OBS_BUS_1),
+                       REG_READ(ah, AR_OBS_BUS_CTRL));
+       }
+       ath_dbg(common, RX_STUCK,
+               "DIAG_SW(0x8048) = %08x MAC_PCU_LOGIC_ANALYZER(0x8264) = %08x"
+               " PCU_MISC_MODE2(0x8344) = %08x\n",
+               REG_READ(ah, AR_DIAG_SW),
+               REG_READ(ah, AR_MAC_PCU_LOGIC_ANALYZER),
+               REG_READ(ah, AR_PCU_MISC_MODE2));
+
+       ath_dbg(common, RX_STUCK, "0x100 = %08x 0x104 = %08x\n",
+               REG_READ(ah, 0x100), REG_READ(ah, 0x104));
+       for (i = 0; i < 10; i++)
+               ath_dbg(common, RX_STUCK, "QSTS(%d) = %08x\n",
+                       i, REG_READ(ah, AR_QSTS(i)));
+
+       ath_dbg(common, RX_STUCK, "Rxdp: hp %08x lp %08x\n",
+               REG_READ(ah, AR_HP_RXDP), REG_READ(ah, AR_LP_RXDP));
+       ath_dbg(common, RX_STUCK,
+               "rx filter: %08x\n", REG_READ(ah, AR_RX_FILTER));
+
+       ath_dbg(common, RX_STUCK, "DMADBG dump:\n");
+       for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+               ath_dbg(common, RX_STUCK, "%d: %08x ",
+                       i, REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32))));
+       ath_dbg(common, RX_STUCK, "\n");
+
+       ath_dbg(common, RX_STUCK, "BB Debug dump:\n");
+       /* Step 1a: Set bit 23 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x00800000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2a: Set register 0xa364 to 0x1000 */
+       reg = 0x1000;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3a: Read bits 17:0 of register 0x9c20 */
+       reg = REG_READ(ah, 0x9c20);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x1000] 0x9c20[17:0] = 0x%x\n", reg);
+
+       /* Step 1b: Set bit 23 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x00800000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2b: Set register 0xa364 to 0x1400 */
+       reg = 0x1400;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3b: Read bits 17:0 of register 0x9c20 */
+       reg = REG_READ(ah, 0x9c20);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x1400] 0x9c20[17:0] = 0x%x\n", reg);
+
+       /* Step 1c: Set bit 23 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x00800000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2c: Set register 0xa364 to 0x3C00 */
+       reg = 0x3c00;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3c: Read bits 17:0 of register 0x9c20 */
+       reg = REG_READ(ah, 0x9c20);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x3C00] 0x9c20[17:0] = 0x%x\n", reg);
+
+       /* Step 1d: Set bit 24 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x001040000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2d: Set register 0xa364 to 0x5005D */
+       reg = 0x5005D;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3d: Read bits 17:0 of register 0xa368 */
+       reg = REG_READ(ah, 0xa368);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x5005D] 0xa368[17:0] = 0x%x\n", reg);
+
+       /* Step 1e: Set bit 24 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x001040000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2e: Set register 0xa364 to 0x7005D */
+       reg = 0x7005D;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3e: Read bits 17:0 of register 0xa368 */
+       reg = REG_READ(ah, 0xa368);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x7005D] 0xa368[17:0] = 0x%x\n", reg);
+
+       /* Step 1f: Set bit 24 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x001000000;
+       reg |= 0x40000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2f: Set register 0xa364 to 0x3005D */
+       reg = 0x3005D;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3f: Read bits 17:0 of register 0xa368 */
+       reg = REG_READ(ah, 0xa368);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x3005D] 0xa368[17:0] = 0x%x\n", reg);
+
+       /* Step 1g: Set bit 24 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x001000000;
+       reg |= 0x40000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2g: Set register 0xa364 to 0x6005D */
+       reg = 0x6005D;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3g: Read bits 17:0 of register 0xa368 */
+       reg = REG_READ(ah, 0xa368);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x6005D] 0xa368[17:0] = 0x%x\n", reg);
+
+       ath9k_btcoex_ar9003_hw_dump_ani_reg(ah);
+
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "WATCHDOG",
+               sc->debug.stats.istats.bb_watchdog);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "TX", sc->debug.stats.istats.txok);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "MIB", sc->debug.stats.istats.mib);
+       ath_dbg(common, RX_STUCK, "%8s: %10u\n", "RXPHY",
+               sc->debug.stats.istats.rxphyerr);
+       ath_dbg(common, RX_STUCK, "%8s: %10u\n", "RXKCM",
+               sc->debug.stats.istats.rx_keycache_miss);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "CST", sc->debug.stats.istats.cst);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt);
+
+       ath_dbg(common, RX_STUCK, "Noise floor dump:\n");
+       ath_dbg(common, RX_STUCK,
+               "Channel Noise Floor : %d\n", ah->noise);
+       ath_dbg(common, RX_STUCK,
+               "Chain | privNF | # Readings | NF Readings\n");
+       for (i = 0; i < 6; i++) {
+               if (!(chainmask & (1 << i)) ||
+                   ((i >= 3) && !conf_is_ht40(conf)))
+                       continue;
+
+               memset(buf, 0, sizeof(buf));
+               len = 0;
+               nread = 5 - h[i].invalidNFcount;
+               for (j = 0; j < nread; j++)
+                       len += snprintf(buf + len, sizeof(buf) - len,
+                                       "%d ", h[i].nfCalBuffer[j]);
+               ath_dbg(common, RX_STUCK, " %d\t %d\t %d\t\t %s",
+                       i, h[i].privNF, nread, buf);
+       }
+
+       last_run = jiffies;
+       if (rx_clear > 98) {
+               ath_dbg(common, RESET,
+                       "rx clear %d match count %d iteration %d\n",
+                       rx_clear, match_count, iter);
+               if (match_count++ > 9)
+                       goto queue_reset_work;
+       } else if (ath9k_btcoex_ath9k_hw_detect_mac_hang(ah))
+               goto queue_reset_work;
+       else if (iter >= 15) {
+               iter = match_count = 0;
+               nmsec = 200;
+       }
+       ath9k_ps_restore(sc);
+       ath_start_rx_poll(sc, nmsec);
+       return;
+
+queue_reset_work:
+       ath9k_ps_restore(sc);
+       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+       iter = match_count = 0;
+}
+
+void ath9k_tasklet(unsigned long data)
+{
+       struct ath_softc *sc = (struct ath_softc *)data;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       u32 status = sc->intrstatus;
+       u32 rxmask;
+
+       ath9k_ps_wakeup(sc);
+       spin_lock(&sc->sc_pcu_lock);
+
+       if ((status & ATH9K_INT_FATAL) ||
+           (status & ATH9K_INT_BB_WATCHDOG)) {
+#ifdef CONFIG_ATH9K_DEBUGFS
+               enum ath_reset_type type;
+
+               if (status & ATH9K_INT_FATAL)
+                       type = RESET_TYPE_FATAL_INT;
+               else
+                       type = RESET_TYPE_BB_WATCHDOG;
+
+               RESET_STAT_INC(sc, type);
+#endif
+               spin_lock(&sc->sc_bb_lock);
+               set_bit(SC_OP_BB_WATCHDOG, &sc->sc_flags);
+               spin_unlock(&sc->sc_bb_lock);
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+               goto out;
+       }
+
+       /*
+        * Only run the baseband hang check if beacons stop working in AP or
+        * IBSS mode, because it has a high false positive rate. For station
+        * mode it should not be necessary, since the upper layers will detect
+        * this through a beacon miss automatically and the following channel
+        * change will trigger a hardware reset anyway
+        */
+       if (ath9k_btcoex_ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0 &&
+           !ath9k_btcoex_ath9k_hw_check_alive(ah))
+               ieee80211_queue_work(sc->hw, &sc->hw_check_work);
+
+       if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) {
+               /*
+                * TSF sync does not look correct; remain awake to sync with
+                * the next Beacon.
+                */
+               ath_dbg(common, PS, "TSFOOR - Sync with next Beacon\n");
+               sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
+       }
+
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+               rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL |
+                         ATH9K_INT_RXORN);
+       else
+               rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+
+       if (status & rxmask) {
+               /* Check for high priority Rx first */
+               if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
+                   (status & ATH9K_INT_RXHP))
+                       ath_rx_tasklet(sc, 0, true);
+
+               ath_rx_tasklet(sc, 0, false);
+       }
+
+       if (status & ATH9K_INT_TX) {
+               if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+                       ath_tx_edma_tasklet(sc);
+               else
+                       ath_tx_tasklet(sc);
+       }
+
+       ath9k_btcoex_handle_interrupt(sc, status);
+
+out:
+       /* re-enable hardware interrupt */
+       ath9k_btcoex_ath9k_hw_enable_interrupts(ah);
+
+       spin_unlock(&sc->sc_pcu_lock);
+       ath9k_ps_restore(sc);
+}
+
+irqreturn_t ath_isr(int irq, void *dev)
+{
+#define SCHED_INTR (                           \
+               ATH9K_INT_FATAL |               \
+               ATH9K_INT_BB_WATCHDOG |         \
+               ATH9K_INT_RXORN |               \
+               ATH9K_INT_RXEOL |               \
+               ATH9K_INT_RX |                  \
+               ATH9K_INT_RXLP |                \
+               ATH9K_INT_RXHP |                \
+               ATH9K_INT_TX |                  \
+               ATH9K_INT_BMISS |               \
+               ATH9K_INT_CST |                 \
+               ATH9K_INT_TSFOOR |              \
+               ATH9K_INT_GENTIMER |            \
+               ATH9K_INT_MCI)
+
+       struct ath_softc *sc = dev;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       enum ath9k_int status;
+       bool sched = false;
+
+       /*
+        * The hardware is not ready/present, don't
+        * touch anything. Note this can happen early
+        * on if the IRQ is shared.
+        */
+       if (test_bit(SC_OP_INVALID, &sc->sc_flags))
+               return IRQ_NONE;
+
+       /* shared irq, not for us */
+
+       if (!ath9k_btcoex_ath9k_hw_intrpend(ah))
+               return IRQ_NONE;
+
+       spin_lock(&sc->sc_bb_lock);
+       if (test_bit(SC_OP_BB_WATCHDOG, &sc->sc_flags)) {
+               spin_unlock(&sc->sc_bb_lock);
+               return IRQ_HANDLED;
+       }
+       spin_unlock(&sc->sc_bb_lock);
+
+       /*
+        * Figure out the reason(s) for the interrupt.  Note
+        * that the hal returns a pseudo-ISR that may include
+        * bits we haven't explicitly enabled so we mask the
+        * value to insure we only process bits we requested.
+        */
+       ath9k_hw_getisr(ah, &status);   /* NB: clears ISR too */
+       status &= ah->imask;    /* discard unasked-for bits */
+
+       /*
+        * If there are no status bits set, then this interrupt was not
+        * for me (should have been caught above).
+        */
+       if (!status)
+               return IRQ_NONE;
+
+       /* Cache the status */
+       sc->intrstatus = status;
+
+       if (status & SCHED_INTR)
+               sched = true;
+
+       /*
+        * If a FATAL or RXORN interrupt is received, we have to reset the
+        * chip immediately.
+        */
+       if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) &&
+           !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
+               goto chip_reset;
+
+       if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
+           (status & ATH9K_INT_BB_WATCHDOG)) {
+
+               spin_lock(&common->cc_lock);
+               ath_hw_cycle_counters_update(common);
+               ath9k_btcoex_ar9003_hw_bb_watchdog_dbg_info(ah);
+               spin_unlock(&common->cc_lock);
+
+               goto chip_reset;
+       }
+
+       if (status & ATH9K_INT_SWBA)
+               tasklet_schedule(&sc->bcon_tasklet);
+
+       if (status & ATH9K_INT_TXURN)
+               ath9k_btcoex_ath9k_hw_updatetxtriglevel(ah, true);
+
+       if (status & ATH9K_INT_RXEOL) {
+               ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+               ath9k_btcoex_ath9k_hw_set_interrupts(ah);
+       }
+
+       if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+               if (status & ATH9K_INT_TIM_TIMER) {
+                       if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle))
+                               goto chip_reset;
+                       /* Clear RxAbort bit so that we can
+                        * receive frames */
+                       ath9k_setpower(sc, ATH9K_PM_AWAKE);
+                       ath9k_btcoex_ath9k_hw_setrxabort(sc->sc_ah, 0);
+                       sc->ps_flags |= PS_WAIT_FOR_BEACON;
+               }
+
+chip_reset:
+
+       ath_debug_stat_interrupt(sc, status);
+
+       if (sched) {
+               /* turn off every interrupt */
+               ath9k_btcoex_ath9k_hw_disable_interrupts(ah);
+               tasklet_schedule(&sc->intr_tq);
+       }
+
+       return IRQ_HANDLED;
+
+#undef SCHED_INTR
+}
+
+static int ath_reset(struct ath_softc *sc, bool retry_tx)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       int r;
+
+       sc->hw_busy_count = 0;
+
+       ath9k_debug_samp_bb_mac(sc);
+       /* Stop ANI */
+       del_timer_sync(&common->ani.timer);
+       del_timer_sync(&sc->rx_poll_timer);
+
+       ath9k_ps_wakeup(sc);
+
+       ieee80211_stop_queues(sc->hw);
+
+       ath9k_btcoex_ath9k_hw_disable_interrupts(ah);
+       ath_drain_all_txq(sc, retry_tx);
+
+       ath_stoprecv(sc);
+       ath_flushrecv(sc);
+
+       r = ath9k_btcoex_ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
+       if (r)
+               ath_err(common,
+                       "Unable to reset hardware; reset status %d\n", r);
+
+       if (!ath_complete_reset(sc, true))
+               r = -EIO;
+
+       if (retry_tx) {
+               int i;
+               for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+                       if (ATH_TXQ_SETUP(sc, i)) {
+                               spin_lock_bh(&sc->tx.txq[i].axq_lock);
+                               ath_txq_schedule(sc, &sc->tx.txq[i]);
+                               spin_unlock_bh(&sc->tx.txq[i].axq_lock);
+                       }
+               }
+       }
+
+       ath9k_ps_restore(sc);
+
+       return r;
+}
+
+void ath_reset_work(struct work_struct *work)
+{
+       struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
+
+       ath_reset(sc, true);
+}
+
+void ath_hw_check(struct work_struct *work)
+{
+       struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       unsigned long flags;
+       int busy;
+
+       ath9k_ps_wakeup(sc);
+       if (ath9k_btcoex_ath9k_hw_check_alive(sc->sc_ah))
+               goto out;
+
+       spin_lock_irqsave(&common->cc_lock, flags);
+       busy = ath_update_survey_stats(sc);
+       spin_unlock_irqrestore(&common->cc_lock, flags);
+
+       ath_dbg(common, RESET, "Possible baseband hang, busy=%d (try %d)\n",
+               busy, sc->hw_busy_count + 1);
+       if (busy >= 99) {
+               if (++sc->hw_busy_count >= 3) {
+                       RESET_STAT_INC(sc, RESET_TYPE_BB_HANG);
+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+               }
+
+       } else if (busy >= 0)
+               sc->hw_busy_count = 0;
+
+out:
+       ath9k_ps_restore(sc);
+}
+
+static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
+{
+       static int count;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+       if (pll_sqsum >= 0x40000) {
+               count++;
+               if (count == 3) {
+                       /* Rx is hung for more than 500ms. Reset it */
+                       ath_dbg(common, RESET, "Possible RX hang, resetting\n");
+                       RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);
+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+                       count = 0;
+               }
+       } else
+               count = 0;
+}
+
+void ath_hw_pll_work(struct work_struct *work)
+{
+       struct ath_softc *sc = container_of(work, struct ath_softc,
+                                           hw_pll_work.work);
+       u32 pll_sqsum;
+
+       if (AR_SREV_9485(sc->sc_ah)) {
+
+               ath9k_ps_wakeup(sc);
+               pll_sqsum = ath9k_btcoex_ar9003_get_pll_sqsum_dvc(sc->sc_ah);
+               ath9k_ps_restore(sc);
+
+               ath_hw_pll_rx_hang_check(sc, pll_sqsum);
+
+               ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
+       }
+}
+
+/**********************/
+/* mac80211 callbacks */
+/**********************/
+
+static int ath9k_start(struct ieee80211_hw *hw)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_channel *curchan = hw->conf.channel;
+       struct ath9k_channel *init_channel;
+       int r;
+
+       ath_dbg(common, CONFIG,
+               "Starting driver with initial channel: %d MHz\n",
+               curchan->center_freq);
+
+       ath9k_ps_wakeup(sc);
+       mutex_lock(&sc->mutex);
+
+       init_channel = ath9k_btcoex_ath9k_cmn_get_curchannel(hw, ah);
+
+       /* Reset SERDES registers */
+       ath9k_hw_configpcipowersave(ah, false);
+
+       /*
+        * The basic interface to setting the hardware in a good
+        * state is ``reset''.  On return the hardware is known to
+        * be powered up and with interrupts disabled.  This must
+        * be followed by initialization of the appropriate bits
+        * and then setup of the interrupt mask.
+        */
+       spin_lock_bh(&sc->sc_pcu_lock);
+
+       atomic_set(&ah->intr_ref_cnt, -1);
+
+       r = ath9k_btcoex_ath9k_hw_reset(ah, init_channel, ah->caldata, false);
+       if (r) {
+               ath_err(common,
+                       "Unable to reset hardware; reset status %d (freq %u MHz)\n",
+                       r, curchan->center_freq);
+               spin_unlock_bh(&sc->sc_pcu_lock);
+               goto mutex_unlock;
+       }
+
+       /* Setup our intr mask. */
+       ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
+                   ATH9K_INT_RXORN | ATH9K_INT_FATAL |
+                   ATH9K_INT_GLOBAL;
+
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+               ah->imask |= ATH9K_INT_RXHP |
+                            ATH9K_INT_RXLP |
+                            ATH9K_INT_BB_WATCHDOG;
+       else
+               ah->imask |= ATH9K_INT_RX;
+
+       ah->imask |= ATH9K_INT_GTT;
+
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_HT)
+               ah->imask |= ATH9K_INT_CST;
+
+       ath_mci_enable(sc);
+
+       clear_bit(SC_OP_INVALID, &sc->sc_flags);
+       sc->sc_ah->is_monitoring = false;
+
+       if (!ath_complete_reset(sc, false)) {
+               r = -EIO;
+               spin_unlock_bh(&sc->sc_pcu_lock);
+               goto mutex_unlock;
+       }
+
+       if (ah->led_pin >= 0) {
+               ath9k_btcoex_ath9k_hw_cfg_output(ah, ah->led_pin,
+                                   AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+               ath9k_btcoex_ath9k_hw_set_gpio(ah, ah->led_pin, 0);
+       }
+
+       /*
+        * Reset key cache to sane defaults (all entries cleared) instead of
+        * semi-random values after suspend/resume.
+        */
+       ath9k_btcoex_ath9k_cmn_init_crypto(sc->sc_ah);
+
+       spin_unlock_bh(&sc->sc_pcu_lock);
+
+       if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
+               common->bus_ops->extn_synch_en(common);
+
+mutex_unlock:
+       mutex_unlock(&sc->mutex);
+
+       ath9k_ps_restore(sc);
+
+       return r;
+}
+
+static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_tx_control txctl;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
+       if (sc->ps_enabled) {
+               /*
+                * mac80211 does not set PM field for normal data frames, so we
+                * need to update that based on the current PS mode.
+                */
+               if (ieee80211_is_data(hdr->frame_control) &&
+                   !ieee80211_is_nullfunc(hdr->frame_control) &&
+                   !ieee80211_has_pm(hdr->frame_control)) {
+                       ath_dbg(common, PS,
+                               "Add PM=1 for a TX frame while in PS mode\n");
+                       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
+               }
+       }
+
+       if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP)) {
+               /*
+                * We are using PS-Poll and mac80211 can request TX while in
+                * power save mode. Need to wake up hardware for the TX to be
+                * completed and if needed, also for RX of buffered frames.
+                */
+               ath9k_ps_wakeup(sc);
+               if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+                       ath9k_btcoex_ath9k_hw_setrxabort(sc->sc_ah, 0);
+               if (ieee80211_is_pspoll(hdr->frame_control)) {
+                       ath_dbg(common, PS,
+                               "Sending PS-Poll to pick a buffered frame\n");
+                       sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA;
+               } else {
+                       ath_dbg(common, PS, "Wake up to complete TX\n");
+                       sc->ps_flags |= PS_WAIT_FOR_TX_ACK;
+               }
+               /*
+                * The actual restore operation will happen only after
+                * the ps_flags bit is cleared. We are just dropping
+                * the ps_usecount here.
+                */
+               ath9k_ps_restore(sc);
+       }
+
+       /*
+        * Cannot tx while the hardware is in full sleep, it first needs a full
+        * chip reset to recover from that
+        */
+       if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP)) {
+               ath_err(common, "TX while HW is in FULL_SLEEP mode\n");
+               goto exit;
+       }
+
+       memset(&txctl, 0, sizeof(struct ath_tx_control));
+       txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
+
+       ath_dbg(common, XMIT, "transmitting packet, skb: %p\n", skb);
+
+       if (ath_tx_start(hw, skb, &txctl) != 0) {
+               ath_dbg(common, XMIT, "TX failed\n");
+               goto exit;
+       }
+
+       return;
+exit:
+       dev_kfree_skb_any(skb);
+}
+
+static void ath9k_stop(struct ieee80211_hw *hw)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       bool prev_idle;
+
+       mutex_lock(&sc->mutex);
+
+       ath_cancel_work(sc);
+
+       if (test_bit(SC_OP_INVALID, &sc->sc_flags)) {
+               ath_dbg(common, ANY, "Device not present\n");
+               mutex_unlock(&sc->mutex);
+               return;
+       }
+
+       /* Ensure HW is awake when we try to shut it down. */
+       ath9k_ps_wakeup(sc);
+
+       spin_lock_bh(&sc->sc_pcu_lock);
+
+       /* prevent tasklets to enable interrupts once we disable them */
+       ah->imask &= ~ATH9K_INT_GLOBAL;
+
+       /* make sure h/w will not generate any interrupt
+        * before setting the invalid flag. */
+       ath9k_btcoex_ath9k_hw_disable_interrupts(ah);
+
+       spin_unlock_bh(&sc->sc_pcu_lock);
+
+       /* we can now sync irq and kill any running tasklets, since we already
+        * disabled interrupts and not holding a spin lock */
+       synchronize_irq(sc->irq);
+       tasklet_kill(&sc->intr_tq);
+       tasklet_kill(&sc->bcon_tasklet);
+
+       prev_idle = sc->ps_idle;
+       sc->ps_idle = true;
+
+       spin_lock_bh(&sc->sc_pcu_lock);
+
+       if (ah->led_pin >= 0) {
+               ath9k_btcoex_ath9k_hw_set_gpio(ah, ah->led_pin, 1);
+               ath9k_btcoex_ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
+       }
+
+       ath_prepare_reset(sc, false, true);
+
+       if (sc->rx.frag) {
+               dev_kfree_skb_any(sc->rx.frag);
+               sc->rx.frag = NULL;
+       }
+
+       if (!ah->curchan)
+               ah->curchan = ath9k_btcoex_ath9k_cmn_get_curchannel(hw, ah);
+
+       ath9k_btcoex_ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+       ath9k_btcoex_ath9k_hw_phy_disable(ah);
+
+       ath9k_hw_configpcipowersave(ah, true);
+
+       spin_unlock_bh(&sc->sc_pcu_lock);
+
+       ath9k_ps_restore(sc);
+
+       set_bit(SC_OP_INVALID, &sc->sc_flags);
+       sc->ps_idle = prev_idle;
+
+       mutex_unlock(&sc->mutex);
+
+       ath_dbg(common, CONFIG, "Driver halt\n");
+}
+
+bool ath9k_uses_beacons(int type)
+{
+       switch (type) {
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_MESH_POINT:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+       struct ath9k_vif_iter_data *iter_data = data;
+       int i;
+
+       if (iter_data->hw_macaddr)
+               for (i = 0; i < ETH_ALEN; i++)
+                       iter_data->mask[i] &=
+                               ~(iter_data->hw_macaddr[i] ^ mac[i]);
+
+       switch (vif->type) {
+       case NL80211_IFTYPE_AP:
+               iter_data->naps++;
+               break;
+       case NL80211_IFTYPE_STATION:
+               iter_data->nstations++;
+               break;
+       case NL80211_IFTYPE_ADHOC:
+               iter_data->nadhocs++;
+               break;
+       case NL80211_IFTYPE_MESH_POINT:
+               iter_data->nmeshes++;
+               break;
+       case NL80211_IFTYPE_WDS:
+               iter_data->nwds++;
+               break;
+       default:
+               break;
+       }
+}
+
+static void ath9k_sta_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+       struct ath_softc *sc = data;
+       struct ath_vif *avp = (void *)vif->drv_priv;
+
+       if (vif->type != NL80211_IFTYPE_STATION)
+               return;
+
+       if (avp->primary_sta_vif)
+               ath9k_set_assoc_state(sc, vif);
+}
+
+/* Called with sc->mutex held. */
+void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+                              struct ieee80211_vif *vif,
+                              struct ath9k_vif_iter_data *iter_data)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       /*
+        * Use the hardware MAC address as reference, the hardware uses it
+        * together with the BSSID mask when matching addresses.
+        */
+       memset(iter_data, 0, sizeof(*iter_data));
+       iter_data->hw_macaddr = common->macaddr;
+       memset(&iter_data->mask, 0xff, ETH_ALEN);
+
+       if (vif)
+               ath9k_vif_iter(iter_data, vif->addr, vif);
+
+       /* Get list of all active MAC addresses */
+       ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
+                                                  iter_data);
+}
+
+/* Called with sc->mutex held. */
+static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
+                                         struct ieee80211_vif *vif)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_vif_iter_data iter_data;
+       enum nl80211_iftype old_opmode = ah->opmode;
+
+       ath9k_calculate_iter_data(hw, vif, &iter_data);
+
+       memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+       ath_hw_setbssidmask(common);
+
+       if (iter_data.naps > 0) {
+               ath9k_btcoex_ath9k_hw_set_tsfadjust(ah, true);
+               ah->opmode = NL80211_IFTYPE_AP;
+       } else {
+               ath9k_btcoex_ath9k_hw_set_tsfadjust(ah, false);
+
+               if (iter_data.nmeshes)
+                       ah->opmode = NL80211_IFTYPE_MESH_POINT;
+               else if (iter_data.nwds)
+                       ah->opmode = NL80211_IFTYPE_AP;
+               else if (iter_data.nadhocs)
+                       ah->opmode = NL80211_IFTYPE_ADHOC;
+               else
+                       ah->opmode = NL80211_IFTYPE_STATION;
+       }
+
+       ath9k_btcoex_ath9k_hw_setopmode(ah);
+
+       if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
+               ah->imask |= ATH9K_INT_TSFOOR;
+       else
+               ah->imask &= ~ATH9K_INT_TSFOOR;
+
+       ath9k_btcoex_ath9k_hw_set_interrupts(ah);
+
+       /*
+        * If we are changing the opmode to STATION,
+        * a beacon sync needs to be done.
+        */
+       if (ah->opmode == NL80211_IFTYPE_STATION &&
+           old_opmode == NL80211_IFTYPE_AP &&
+           test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
+               ieee80211_iterate_active_interfaces_atomic(sc->hw,
+                                                  ath9k_sta_vif_iter, sc);
+       }
+}
+
+static int ath9k_add_interface(struct ieee80211_hw *hw,
+                              struct ieee80211_vif *vif)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       int ret = 0;
+
+       ath9k_ps_wakeup(sc);
+       mutex_lock(&sc->mutex);
+
+       switch (vif->type) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_WDS:
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_MESH_POINT:
+               break;
+       default:
+               ath_err(common, "Interface type %d not yet supported\n",
+                       vif->type);
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+
+       if (ath9k_uses_beacons(vif->type)) {
+               if (sc->nbcnvifs >= ATH_BCBUF) {
+                       ath_err(common, "Not enough beacon buffers when adding"
+                               " new interface of type: %i\n",
+                               vif->type);
+                       ret = -ENOBUFS;
+                       goto out;
+               }
+       }
+
+       if ((ah->opmode == NL80211_IFTYPE_ADHOC) ||
+           ((vif->type == NL80211_IFTYPE_ADHOC) &&
+            sc->nvifs > 0)) {
+               ath_err(common, "Cannot create ADHOC interface when other"
+                       " interfaces already exist.\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
+
+       sc->nvifs++;
+
+       ath9k_calculate_summary_state(hw, vif);
+       if (ath9k_uses_beacons(vif->type))
+               ath9k_beacon_assign_slot(sc, vif);
+
+out:
+       mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
+       return ret;
+}
+
+static int ath9k_change_interface(struct ieee80211_hw *hw,
+                                 struct ieee80211_vif *vif,
+                                 enum nl80211_iftype new_type,
+                                 bool p2p)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       int ret = 0;
+
+       ath_dbg(common, CONFIG, "Change Interface\n");
+
+       mutex_lock(&sc->mutex);
+       ath9k_ps_wakeup(sc);
+
+       /* See if new interface type is valid. */
+       if ((new_type == NL80211_IFTYPE_ADHOC) &&
+           (sc->nvifs > 1)) {
+               ath_err(common, "When using ADHOC, it must be the only"
+                       " interface.\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (ath9k_uses_beacons(new_type) &&
+           !ath9k_uses_beacons(vif->type)) {
+               if (sc->nbcnvifs >= ATH_BCBUF) {
+                       ath_err(common, "No beacon slot available\n");
+                       ret = -ENOBUFS;
+                       goto out;
+               }
+       }
+
+       if (ath9k_uses_beacons(vif->type))
+               ath9k_beacon_remove_slot(sc, vif);
+
+       vif->type = new_type;
+       vif->p2p = p2p;
+
+       ath9k_calculate_summary_state(hw, vif);
+       if (ath9k_uses_beacons(vif->type))
+               ath9k_beacon_assign_slot(sc, vif);
+
+out:
+       ath9k_ps_restore(sc);
+       mutex_unlock(&sc->mutex);
+       return ret;
+}
+
+static void ath9k_remove_interface(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+       ath_dbg(common, CONFIG, "Detach Interface\n");
+
+       ath9k_ps_wakeup(sc);
+       mutex_lock(&sc->mutex);
+
+       sc->nvifs--;
+
+       if (ath9k_uses_beacons(vif->type))
+               ath9k_beacon_remove_slot(sc, vif);
+
+       ath9k_calculate_summary_state(hw, NULL);
+
+       mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
+}
+
+static void ath9k_enable_ps(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       sc->ps_enabled = true;
+       if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+               if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) {
+                       ah->imask |= ATH9K_INT_TIM_TIMER;
+                       ath9k_btcoex_ath9k_hw_set_interrupts(ah);
+               }
+               ath9k_btcoex_ath9k_hw_setrxabort(ah, 1);
+       }
+       ath_dbg(common, PS, "PowerSave enabled\n");
+}
+
+static void ath9k_disable_ps(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       sc->ps_enabled = false;
+       ath9k_btcoex_ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
+       if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+               ath9k_btcoex_ath9k_hw_setrxabort(ah, 0);
+               sc->ps_flags &= ~(PS_WAIT_FOR_BEACON |
+                                 PS_WAIT_FOR_CAB |
+                                 PS_WAIT_FOR_PSPOLL_DATA |
+                                 PS_WAIT_FOR_TX_ACK);
+               if (ah->imask & ATH9K_INT_TIM_TIMER) {
+                       ah->imask &= ~ATH9K_INT_TIM_TIMER;
+                       ath9k_btcoex_ath9k_hw_set_interrupts(ah);
+               }
+       }
+       ath_dbg(common, PS, "PowerSave disabled\n");
+}
+
+static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_conf *conf = &hw->conf;
+       bool reset_channel = false;
+
+       ath9k_ps_wakeup(sc);
+       mutex_lock(&sc->mutex);
+
+       if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+               sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
+               if (sc->ps_idle) {
+                       ath_cancel_work(sc);
+                       ath9k_stop_btcoex(sc);
+               } else {
+                       ath9k_start_btcoex(sc);
+                       /*
+                        * The chip needs a reset to properly wake up from
+                        * full sleep
+                        */
+                       reset_channel = ah->chip_fullsleep;
+               }
+       }
+
+       /*
+        * We just prepare to enable PS. We have to wait until our AP has
+        * ACK'd our null data frame to disable RX otherwise we'll ignore
+        * those ACKs and end up retransmitting the same null data frames.
+        * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode.
+        */
+       if (changed & IEEE80211_CONF_CHANGE_PS) {
+               unsigned long flags;
+               spin_lock_irqsave(&sc->sc_pm_lock, flags);
+               if (conf->flags & IEEE80211_CONF_PS)
+                       ath9k_enable_ps(sc);
+               else
+                       ath9k_disable_ps(sc);
+               spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+       }
+
+       if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+               if (conf->flags & IEEE80211_CONF_MONITOR) {
+                       ath_dbg(common, CONFIG, "Monitor mode is enabled\n");
+                       sc->sc_ah->is_monitoring = true;
+               } else {
+                       ath_dbg(common, CONFIG, "Monitor mode is disabled\n");
+                       sc->sc_ah->is_monitoring = false;
+               }
+       }
+
+       if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
+               struct ieee80211_channel *curchan = hw->conf.channel;
+               int pos = curchan->hw_value;
+               int old_pos = -1;
+               unsigned long flags;
+
+               if (ah->curchan)
+                       old_pos = ah->curchan - &ah->channels[0];
+
+               ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n",
+                       curchan->center_freq, conf->channel_type);
+
+               /* update survey stats for the old channel before switching */
+               spin_lock_irqsave(&common->cc_lock, flags);
+               ath_update_survey_stats(sc);
+               spin_unlock_irqrestore(&common->cc_lock, flags);
+
+               /*
+                * Preserve the current channel values, before updating
+                * the same channel
+                */
+               if (ah->curchan && (old_pos == pos))
+                       ath9k_btcoex_ath9k_hw_getnf(ah, ah->curchan);
+
+               ath9k_btcoex_ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
+                                         curchan, conf->channel_type);
+
+               /*
+                * If the operating channel changes, change the survey in-use flags
+                * along with it.
+                * Reset the survey data for the new channel, unless we're switching
+                * back to the operating channel from an off-channel operation.
+                */
+               if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) &&
+                   sc->cur_survey != &sc->survey[pos]) {
+
+                       if (sc->cur_survey)
+                               sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
+
+                       sc->cur_survey = &sc->survey[pos];
+
+                       memset(sc->cur_survey, 0, sizeof(struct survey_info));
+                       sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
+               } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
+                       memset(&sc->survey[pos], 0, sizeof(struct survey_info));
+               }
+
+               if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
+                       ath_err(common, "Unable to set channel\n");
+                       mutex_unlock(&sc->mutex);
+                       ath9k_ps_restore(sc);
+                       return -EINVAL;
+               }
+
+               /*
+                * The most recent snapshot of channel->noisefloor for the old
+                * channel is only available after the hardware reset. Copy it to
+                * the survey stats now.
+                */
+               if (old_pos >= 0)
+                       ath_update_survey_nf(sc, old_pos);
+       }
+
+       if (changed & IEEE80211_CONF_CHANGE_POWER) {
+               ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
+               sc->config.txpowlimit = 2 * conf->power_level;
+               ath9k_btcoex_ath9k_cmn_update_txpow(ah, sc->curtxpow,
+                                      sc->config.txpowlimit, &sc->curtxpow);
+       }
+
+       mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
+
+       return 0;
+}
+
+#define SUPPORTED_FILTERS                      \
+       (FIF_PROMISC_IN_BSS |                   \
+       FIF_ALLMULTI |                          \
+       FIF_CONTROL |                           \
+       FIF_PSPOLL |                            \
+       FIF_OTHER_BSS |                         \
+       FIF_BCN_PRBRESP_PROMISC |               \
+       FIF_PROBE_REQ |                         \
+       FIF_FCSFAIL)
+
+/* FIXME: sc->sc_full_reset ? */
+static void ath9k_configure_filter(struct ieee80211_hw *hw,
+                                  unsigned int changed_flags,
+                                  unsigned int *total_flags,
+                                  u64 multicast)
+{
+       struct ath_softc *sc = hw->priv;
+       u32 rfilt;
+
+       changed_flags &= SUPPORTED_FILTERS;
+       *total_flags &= SUPPORTED_FILTERS;
+
+       sc->rx.rxfilter = *total_flags;
+       ath9k_ps_wakeup(sc);
+       rfilt = ath_calcrxfilter(sc);
+       ath9k_btcoex_ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
+       ath9k_ps_restore(sc);
+
+       ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG, "Set HW RX filter: 0x%x\n",
+               rfilt);
+}
+
+static int ath9k_sta_add(struct ieee80211_hw *hw,
+                        struct ieee80211_vif *vif,
+                        struct ieee80211_sta *sta)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_node *an = (struct ath_node *) sta->drv_priv;
+       struct ieee80211_key_conf ps_key = { };
+
+       ath_node_attach(sc, sta, vif);
+
+       if (vif->type != NL80211_IFTYPE_AP &&
+           vif->type != NL80211_IFTYPE_AP_VLAN)
+               return 0;
+
+       an->ps_key = ath_key_config(common, vif, sta, &ps_key);
+
+       return 0;
+}
+
+static void ath9k_del_ps_key(struct ath_softc *sc,
+                            struct ieee80211_vif *vif,
+                            struct ieee80211_sta *sta)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_node *an = (struct ath_node *) sta->drv_priv;
+       struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key };
+
+       if (!an->ps_key)
+           return;
+
+       ath_key_delete(common, &ps_key);
+}
+
+static int ath9k_sta_remove(struct ieee80211_hw *hw,
+                           struct ieee80211_vif *vif,
+                           struct ieee80211_sta *sta)
+{
+       struct ath_softc *sc = hw->priv;
+
+       ath9k_del_ps_key(sc, vif, sta);
+       ath_node_detach(sc, sta);
+
+       return 0;
+}
+
+static void ath9k_sta_notify(struct ieee80211_hw *hw,
+                        struct ieee80211_vif *vif,
+                        enum sta_notify_cmd cmd,
+                        struct ieee80211_sta *sta)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_node *an = (struct ath_node *) sta->drv_priv;
+
+       if (!sta->ht_cap.ht_supported)
+               return;
+
+       switch (cmd) {
+       case STA_NOTIFY_SLEEP:
+               an->sleeping = true;
+               ath_tx_aggr_sleep(sta, sc, an);
+               break;
+       case STA_NOTIFY_AWAKE:
+               an->sleeping = false;
+               ath_tx_aggr_wakeup(sc, an);
+               break;
+       }
+}
+
+static int ath9k_conf_tx(struct ieee80211_hw *hw,
+                        struct ieee80211_vif *vif, u16 queue,
+                        const struct ieee80211_tx_queue_params *params)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_txq *txq;
+       struct ath9k_tx_queue_info qi;
+       int ret = 0;
+
+       if (queue >= WME_NUM_AC)
+               return 0;
+
+       txq = sc->tx.txq_map[queue];
+
+       ath9k_ps_wakeup(sc);
+       mutex_lock(&sc->mutex);
+
+       memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
+
+       qi.tqi_aifs = params->aifs;
+       qi.tqi_cwmin = params->cw_min;
+       qi.tqi_cwmax = params->cw_max;
+       qi.tqi_burstTime = params->txop * 32;
+
+       ath_dbg(common, CONFIG,
+               "Configure tx [queue/halq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
+               queue, txq->axq_qnum, params->aifs, params->cw_min,
+               params->cw_max, params->txop);
+
+       ret = ath_txq_update(sc, txq->axq_qnum, &qi);
+       if (ret)
+               ath_err(common, "TXQ Update failed\n");
+
+       mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
+
+       return ret;
+}
+
+static int ath9k_set_key(struct ieee80211_hw *hw,
+                        enum set_key_cmd cmd,
+                        struct ieee80211_vif *vif,
+                        struct ieee80211_sta *sta,
+                        struct ieee80211_key_conf *key)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       int ret = 0;
+
+       if (ath9k_modparam_nohwcrypt)
+               return -ENOSPC;
+
+       if ((vif->type == NL80211_IFTYPE_ADHOC ||
+            vif->type == NL80211_IFTYPE_MESH_POINT) &&
+           (key->cipher == WLAN_CIPHER_SUITE_TKIP ||
+            key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
+           !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+               /*
+                * For now, disable hw crypto for the RSN IBSS group keys. This
+                * could be optimized in the future to use a modified key cache
+                * design to support per-STA RX GTK, but until that gets
+                * implemented, use of software crypto for group addressed
+                * frames is a acceptable to allow RSN IBSS to be used.
+                */
+               return -EOPNOTSUPP;
+       }
+
+       mutex_lock(&sc->mutex);
+       ath9k_ps_wakeup(sc);
+       ath_dbg(common, CONFIG, "Set HW Key\n");
+
+       switch (cmd) {
+       case SET_KEY:
+               if (sta)
+                       ath9k_del_ps_key(sc, vif, sta);
+
+               ret = ath_key_config(common, vif, sta, key);
+               if (ret >= 0) {
+                       key->hw_key_idx = ret;
+                       /* push IV and Michael MIC generation to stack */
+                       key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+                       if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
+                               key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+                       if (sc->sc_ah->sw_mgmt_crypto &&
+                           key->cipher == WLAN_CIPHER_SUITE_CCMP)
+                               key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
+                       ret = 0;
+               }
+               break;
+       case DISABLE_KEY:
+               ath_key_delete(common, key);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       ath9k_ps_restore(sc);
+       mutex_unlock(&sc->mutex);
+
+       return ret;
+}
+
+static void ath9k_set_assoc_state(struct ath_softc *sc,
+                                 struct ieee80211_vif *vif)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_vif *avp = (void *)vif->drv_priv;
+       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+       unsigned long flags;
+
+       set_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);
+       avp->primary_sta_vif = true;
+
+       /*
+        * Set the AID, BSSID and do beacon-sync only when
+        * the HW opmode is STATION.
+        *
+        * But the primary bit is set above in any case.
+        */
+       if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+               return;
+
+       memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+       common->curaid = bss_conf->aid;
+       ath9k_btcoex_ath9k_hw_write_associd(sc->sc_ah);
+
+       sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+       sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+       sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+
+       ath_dbg(common, CONFIG,
+               "Primary Station interface: %pM, BSSID: %pM\n",
+               vif->addr, common->curbssid);
+}
+
+static void ath9k_bss_assoc_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+       struct ath_softc *sc = data;
+       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+
+       if (test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
+               return;
+
+       if (bss_conf->assoc)
+               ath9k_set_assoc_state(sc, vif);
+}
+
+static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif,
+                                  struct ieee80211_bss_conf *bss_conf,
+                                  u32 changed)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_vif *avp = (void *)vif->drv_priv;
+       int slottime;
+
+       ath9k_ps_wakeup(sc);
+       mutex_lock(&sc->mutex);
+
+       if (changed & BSS_CHANGED_ASSOC) {
+               ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
+                       bss_conf->bssid, bss_conf->assoc);
+
+               if (avp->primary_sta_vif && !bss_conf->assoc) {
+                       clear_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);
+                       avp->primary_sta_vif = false;
+
+                       if (ah->opmode == NL80211_IFTYPE_STATION)
+                               clear_bit(SC_OP_BEACONS, &sc->sc_flags);
+               }
+
+               ieee80211_iterate_active_interfaces_atomic(sc->hw,
+                                                  ath9k_bss_assoc_iter, sc);
+
+               if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags) &&
+                   ah->opmode == NL80211_IFTYPE_STATION) {
+                       memset(common->curbssid, 0, ETH_ALEN);
+                       common->curaid = 0;
+                       ath9k_btcoex_ath9k_hw_write_associd(sc->sc_ah);
+               }
+       }
+
+       if (changed & BSS_CHANGED_IBSS) {
+               memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+               common->curaid = bss_conf->aid;
+               ath9k_btcoex_ath9k_hw_write_associd(sc->sc_ah);
+
+               if (bss_conf->ibss_joined) {
+                       if (!common->disable_ani) {
+                               set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+                               ath_start_ani(common);
+                       }
+               } else {
+                       clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+                       del_timer_sync(&common->ani.timer);
+               }
+       }
+
+       if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
+           (changed & BSS_CHANGED_BEACON_INT)) {
+               if (ah->opmode == NL80211_IFTYPE_AP &&
+                   bss_conf->enable_beacon)
+                       ath9k_set_tsfadjust(sc, vif);
+               if (ath9k_allow_beacon_config(sc, vif))
+                       ath9k_beacon_config(sc, vif, changed);
+       }
+
+       if (changed & BSS_CHANGED_ERP_SLOT) {
+               if (bss_conf->use_short_slot)
+                       slottime = 9;
+               else
+                       slottime = 20;
+               if (vif->type == NL80211_IFTYPE_AP) {
+                       /*
+                        * Defer update, so that connected stations can adjust
+                        * their settings at the same time.
+                        * See beacon.c for more details
+                        */
+                       sc->beacon.slottime = slottime;
+                       sc->beacon.updateslot = UPDATE;
+               } else {
+                       ah->slottime = slottime;
+                       ath9k_btcoex_ath9k_hw_init_global_settings(ah);
+               }
+       }
+
+       mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
+}
+
+static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct ath_softc *sc = hw->priv;
+       u64 tsf;
+
+       mutex_lock(&sc->mutex);
+       ath9k_ps_wakeup(sc);
+       tsf = ath9k_btcoex_ath9k_hw_gettsf64(sc->sc_ah);
+       ath9k_ps_restore(sc);
+       mutex_unlock(&sc->mutex);
+
+       return tsf;
+}
+
+static void ath9k_set_tsf(struct ieee80211_hw *hw,
+                         struct ieee80211_vif *vif,
+                         u64 tsf)
+{
+       struct ath_softc *sc = hw->priv;
+
+       mutex_lock(&sc->mutex);
+       ath9k_ps_wakeup(sc);
+       ath9k_btcoex_ath9k_hw_settsf64(sc->sc_ah, tsf);
+       ath9k_ps_restore(sc);
+       mutex_unlock(&sc->mutex);
+}
+
+static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct ath_softc *sc = hw->priv;
+
+       mutex_lock(&sc->mutex);
+
+       ath9k_ps_wakeup(sc);
+       ath9k_btcoex_ath9k_hw_reset_tsf(sc->sc_ah);
+       ath9k_ps_restore(sc);
+
+       mutex_unlock(&sc->mutex);
+}
+
+static int ath9k_ampdu_action(struct ieee80211_hw *hw,
+                             struct ieee80211_vif *vif,
+                             enum ieee80211_ampdu_mlme_action action,
+                             struct ieee80211_sta *sta,
+                             u16 tid, u16 *ssn, u8 buf_size)
+{
+       struct ath_softc *sc = hw->priv;
+       int ret = 0;
+
+       local_bh_disable();
+
+       switch (action) {
+       case IEEE80211_AMPDU_RX_START:
+               break;
+       case IEEE80211_AMPDU_RX_STOP:
+               break;
+       case IEEE80211_AMPDU_TX_START:
+               ath9k_ps_wakeup(sc);
+               ret = ath_tx_aggr_start(sc, sta, tid, ssn);
+               if (!ret)
+                       ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               ath9k_ps_restore(sc);
+               break;
+       case IEEE80211_AMPDU_TX_STOP:
+               ath9k_ps_wakeup(sc);
+               ath_tx_aggr_stop(sc, sta, tid);
+               ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               ath9k_ps_restore(sc);
+               break;
+       case IEEE80211_AMPDU_TX_OPERATIONAL:
+               ath9k_ps_wakeup(sc);
+               ath_tx_aggr_resume(sc, sta, tid);
+               ath9k_ps_restore(sc);
+               break;
+       default:
+               ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n");
+       }
+
+       local_bh_enable();
+
+       return ret;
+}
+
+static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
+                            struct survey_info *survey)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *chan;
+       unsigned long flags;
+       int pos;
+
+       spin_lock_irqsave(&common->cc_lock, flags);
+       if (idx == 0)
+               ath_update_survey_stats(sc);
+
+       sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
+       if (sband && idx >= sband->n_channels) {
+               idx -= sband->n_channels;
+               sband = NULL;
+       }
+
+       if (!sband)
+               sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
+
+       if (!sband || idx >= sband->n_channels) {
+               spin_unlock_irqrestore(&common->cc_lock, flags);
+               return -ENOENT;
+       }
+
+       chan = &sband->channels[idx];
+       pos = chan->hw_value;
+       memcpy(survey, &sc->survey[pos], sizeof(*survey));
+       survey->channel = chan;
+       spin_unlock_irqrestore(&common->cc_lock, flags);
+
+       return 0;
+}
+
+static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+
+       mutex_lock(&sc->mutex);
+       ah->coverage_class = coverage_class;
+
+       ath9k_ps_wakeup(sc);
+       ath9k_btcoex_ath9k_hw_init_global_settings(ah);
+       ath9k_ps_restore(sc);
+
+       mutex_unlock(&sc->mutex);
+}
+
+static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       int timeout = 200; /* ms */
+       int i, j;
+       bool drain_txq;
+
+       mutex_lock(&sc->mutex);
+       cancel_delayed_work_sync(&sc->tx_complete_work);
+
+       if (ah->ah_flags & AH_UNPLUGGED) {
+               ath_dbg(common, ANY, "Device has been unplugged!\n");
+               mutex_unlock(&sc->mutex);
+               return;
+       }
+
+       if (sc->sc_flags & SC_OP_INVALID) {
+               ath_dbg(common, ANY, "Device not present\n");
+               mutex_unlock(&sc->mutex);
+               return;
+       }
+
+       for (j = 0; j < timeout; j++) {
+               bool npend = false;
+
+               if (j)
+                       usleep_range(1000, 2000);
+
+               for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+                       if (!ATH_TXQ_SETUP(sc, i))
+                               continue;
+
+                       npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
+
+                       if (npend)
+                               break;
+               }
+
+               if (!npend)
+                   break;
+       }
+
+       if (drop) {
+               ath9k_ps_wakeup(sc);
+               spin_lock_bh(&sc->sc_pcu_lock);
+               drain_txq = ath_drain_all_txq(sc, false);
+               spin_unlock_bh(&sc->sc_pcu_lock);
+
+               if (!drain_txq)
+                       ath_reset(sc, false);
+
+               ath9k_ps_restore(sc);
+               ieee80211_wake_queues(hw);
+       }
+
+       ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
+       mutex_unlock(&sc->mutex);
+}
+
+static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
+{
+       struct ath_softc *sc = hw->priv;
+       int i;
+
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (!ATH_TXQ_SETUP(sc, i))
+                       continue;
+
+               if (ath9k_has_pending_frames(sc, &sc->tx.txq[i]))
+                       return true;
+       }
+       return false;
+}
+
+static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ieee80211_vif *vif;
+       struct ath_vif *avp;
+       struct ath_buf *bf;
+       struct ath_tx_status ts;
+       bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+       int status;
+
+       vif = sc->beacon.bslot[0];
+       if (!vif)
+               return 0;
+
+       if (!vif->bss_conf.enable_beacon)
+               return 0;
+
+       avp = (void *)vif->drv_priv;
+
+       if (!sc->beacon.tx_processed && !edma) {
+               tasklet_disable(&sc->bcon_tasklet);
+
+               bf = avp->av_bcbuf;
+               if (!bf || !bf->bf_mpdu)
+                       goto skip;
+
+               status = ath9k_hw_txprocdesc(ah, bf->bf_desc, &ts);
+               if (status == -EINPROGRESS)
+                       goto skip;
+
+               sc->beacon.tx_processed = true;
+               sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
+
+skip:
+               tasklet_enable(&sc->bcon_tasklet);
+       }
+
+       return sc->beacon.tx_last;
+}
+
+static int ath9k_get_stats(struct ieee80211_hw *hw,
+                          struct ieee80211_low_level_stats *stats)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats;
+
+       stats->dot11ACKFailureCount = mib_stats->ackrcv_bad;
+       stats->dot11RTSFailureCount = mib_stats->rts_bad;
+       stats->dot11FCSErrorCount = mib_stats->fcs_bad;
+       stats->dot11RTSSuccessCount = mib_stats->rts_good;
+       return 0;
+}
+
+static u32 fill_chainmask(u32 cap, u32 new)
+{
+       u32 filled = 0;
+       int i;
+
+       for (i = 0; cap && new; i++, cap >>= 1) {
+               if (!(cap & BIT(0)))
+                       continue;
+
+               if (new & BIT(0))
+                       filled |= BIT(i);
+
+               new >>= 1;
+       }
+
+       return filled;
+}
+
+static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+
+       if (!rx_ant || !tx_ant)
+               return -EINVAL;
+
+       sc->ant_rx = rx_ant;
+       sc->ant_tx = tx_ant;
+
+       if (ah->caps.rx_chainmask == 1)
+               return 0;
+
+       /* AR9100 runs into calibration issues if not all rx chains are enabled */
+       if (AR_SREV_9100(ah))
+               ah->rxchainmask = 0x7;
+       else
+               ah->rxchainmask = fill_chainmask(ah->caps.rx_chainmask, rx_ant);
+
+       ah->txchainmask = fill_chainmask(ah->caps.tx_chainmask, tx_ant);
+       ath9k_reload_chainmask_settings(sc);
+
+       return 0;
+}
+
+static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+       struct ath_softc *sc = hw->priv;
+
+       *tx_ant = sc->ant_tx;
+       *rx_ant = sc->ant_rx;
+       return 0;
+}
+
+struct ieee80211_ops ath9k_ops = {
+       .tx                 = ath9k_tx,
+       .start              = ath9k_start,
+       .stop               = ath9k_stop,
+       .add_interface      = ath9k_add_interface,
+       .change_interface   = ath9k_change_interface,
+       .remove_interface   = ath9k_remove_interface,
+       .config             = ath9k_config,
+       .configure_filter   = ath9k_configure_filter,
+       .sta_add            = ath9k_sta_add,
+       .sta_remove         = ath9k_sta_remove,
+       .sta_notify         = ath9k_sta_notify,
+       .conf_tx            = ath9k_conf_tx,
+       .bss_info_changed   = ath9k_bss_info_changed,
+       .set_key            = ath9k_set_key,
+       .get_tsf            = ath9k_get_tsf,
+       .set_tsf            = ath9k_set_tsf,
+       .reset_tsf          = ath9k_reset_tsf,
+       .ampdu_action       = ath9k_ampdu_action,
+       .get_survey         = ath9k_get_survey,
+       .rfkill_poll        = ath9k_rfkill_poll_state,
+       .set_coverage_class = ath9k_set_coverage_class,
+       .flush              = ath9k_flush,
+       .tx_frames_pending  = ath9k_tx_frames_pending,
+       .tx_last_beacon     = ath9k_tx_last_beacon,
+       .get_stats          = ath9k_get_stats,
+       .set_antenna        = ath9k_set_antenna,
+       .get_antenna        = ath9k_get_antenna,
+};
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/mci.c b/drivers/net/wireless/ath/ath9k_btcoex/mci.c
new file mode 100644 (file)
index 0000000..9278266
--- /dev/null
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#include "ath9k.h"
+#include "mci.h"
+
+static const u8 ath_mci_duty_cycle[] = { 55, 50, 60, 70, 80, 85, 90, 95, 98 };
+
+static struct ath_mci_profile_info*
+ath_mci_find_profile(struct ath_mci_profile *mci,
+                    struct ath_mci_profile_info *info)
+{
+       struct ath_mci_profile_info *entry;
+
+       if (list_empty(&mci->info))
+               return NULL;
+
+       list_for_each_entry(entry, &mci->info, list) {
+               if (entry->conn_handle == info->conn_handle)
+                       return entry;
+       }
+       return NULL;
+}
+
+static bool ath_mci_add_profile(struct ath_common *common,
+                               struct ath_mci_profile *mci,
+                               struct ath_mci_profile_info *info)
+{
+       struct ath_mci_profile_info *entry;
+
+       if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) &&
+           (info->type == MCI_GPM_COEX_PROFILE_VOICE))
+               return false;
+
+       if (((NUM_PROF(mci) - mci->num_sco) == ATH_MCI_MAX_ACL_PROFILE) &&
+           (info->type != MCI_GPM_COEX_PROFILE_VOICE))
+               return false;
+
+       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+       if (!entry)
+               return false;
+
+       memcpy(entry, info, 10);
+       INC_PROF(mci, info);
+       list_add_tail(&entry->list, &mci->info);
+
+       return true;
+}
+
+static void ath_mci_del_profile(struct ath_common *common,
+                               struct ath_mci_profile *mci,
+                               struct ath_mci_profile_info *entry)
+{
+       if (!entry)
+               return;
+
+       DEC_PROF(mci, entry);
+       list_del(&entry->list);
+       kfree(entry);
+}
+
+void ath_mci_flush_profile(struct ath_mci_profile *mci)
+{
+       struct ath_mci_profile_info *info, *tinfo;
+
+       mci->aggr_limit = 0;
+
+       if (list_empty(&mci->info))
+               return;
+
+       list_for_each_entry_safe(info, tinfo, &mci->info, list) {
+               list_del(&info->list);
+               DEC_PROF(mci, info);
+               kfree(info);
+       }
+}
+
+static void ath_mci_adjust_aggr_limit(struct ath_btcoex *btcoex)
+{
+       struct ath_mci_profile *mci = &btcoex->mci;
+       u32 wlan_airtime = btcoex->btcoex_period *
+                               (100 - btcoex->duty_cycle) / 100;
+
+       /*
+        * Scale: wlan_airtime is in ms, aggr_limit is in 0.25 ms.
+        * When wlan_airtime is less than 4ms, aggregation limit has to be
+        * adjusted half of wlan_airtime to ensure that the aggregation can fit
+        * without collision with BT traffic.
+        */
+       if ((wlan_airtime <= 4) &&
+           (!mci->aggr_limit || (mci->aggr_limit > (2 * wlan_airtime))))
+               mci->aggr_limit = 2 * wlan_airtime;
+}
+
+static void ath_mci_update_scheme(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_mci_profile *mci = &btcoex->mci;
+       struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci;
+       struct ath_mci_profile_info *info;
+       u32 num_profile = NUM_PROF(mci);
+
+       if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_TUNING)
+               goto skip_tuning;
+
+       btcoex->duty_cycle = ath_mci_duty_cycle[num_profile];
+
+       if (num_profile == 1) {
+               info = list_first_entry(&mci->info,
+                                       struct ath_mci_profile_info,
+                                       list);
+               if (mci->num_sco) {
+                       if (info->T == 12)
+                               mci->aggr_limit = 8;
+                       else if (info->T == 6) {
+                               mci->aggr_limit = 6;
+                               btcoex->duty_cycle = 30;
+                       }
+                       ath_dbg(common, MCI,
+                               "Single SCO, aggregation limit %d 1/4 ms\n",
+                               mci->aggr_limit);
+               } else if (mci->num_pan || mci->num_other_acl) {
+                       /*
+                        * For single PAN/FTP profile, allocate 35% for BT
+                        * to improve WLAN throughput.
+                        */
+                       btcoex->duty_cycle = 35;
+                       btcoex->btcoex_period = 53;
+                       ath_dbg(common, MCI,
+                               "Single PAN/FTP bt period %d ms dutycycle %d\n",
+                               btcoex->duty_cycle, btcoex->btcoex_period);
+               } else if (mci->num_hid) {
+                       btcoex->duty_cycle = 30;
+                       mci->aggr_limit = 6;
+                       ath_dbg(common, MCI,
+                               "Multiple attempt/timeout single HID "
+                               "aggregation limit 1.5 ms dutycycle 30%%\n");
+               }
+       } else if (num_profile == 2) {
+               if (mci->num_hid == 2)
+                       btcoex->duty_cycle = 30;
+               mci->aggr_limit = 6;
+               ath_dbg(common, MCI,
+                       "Two BT profiles aggr limit 1.5 ms dutycycle %d%%\n",
+                       btcoex->duty_cycle);
+       } else if (num_profile >= 3) {
+               mci->aggr_limit = 4;
+               ath_dbg(common, MCI,
+                       "Three or more profiles aggregation limit 1 ms\n");
+       }
+
+skip_tuning:
+       if (IS_CHAN_2GHZ(sc->sc_ah->curchan)) {
+               if (IS_CHAN_HT(sc->sc_ah->curchan))
+                       ath_mci_adjust_aggr_limit(btcoex);
+               else
+                       btcoex->btcoex_period >>= 1;
+       }
+
+       ath9k_btcoex_timer_pause(sc);
+       ath9k_btcoex_ath9k_hw_btcoex_disable(sc->sc_ah);
+
+       if (IS_CHAN_5GHZ(sc->sc_ah->curchan))
+               return;
+
+       btcoex->duty_cycle += (mci->num_bdr ? ATH_MCI_BDR_DUTY_CYCLE : 0);
+       if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE)
+               btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE;
+
+       btcoex->btcoex_no_stomp =  btcoex->btcoex_period * 1000 *
+               (100 - btcoex->duty_cycle) / 100;
+
+       ath9k_btcoex_ath9k_hw_btcoex_enable(sc->sc_ah);
+       ath9k_btcoex_timer_resume(sc);
+}
+
+static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
+       u32 payload[4] = {0, 0, 0, 0};
+
+       switch (opcode) {
+       case MCI_GPM_BT_CAL_REQ:
+               if (mci_hw->bt_state == MCI_BT_AWAKE) {
+                       ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START);
+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+               }
+               ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);
+               break;
+       case MCI_GPM_BT_CAL_GRANT:
+               MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE);
+               ath9k_btcoex_ar9003_mci_send_message(sc->sc_ah, MCI_GPM, 0, payload,
+                                       16, false, true);
+               break;
+       default:
+               ath_dbg(common, MCI, "Unknown GPM CAL message\n");
+               break;
+       }
+}
+
+static void ath9k_mci_work(struct work_struct *work)
+{
+       struct ath_softc *sc = container_of(work, struct ath_softc, mci_work);
+
+       ath_mci_update_scheme(sc);
+}
+
+static void ath_mci_process_profile(struct ath_softc *sc,
+                                   struct ath_mci_profile_info *info)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_mci_profile *mci = &btcoex->mci;
+       struct ath_mci_profile_info *entry = NULL;
+
+       entry = ath_mci_find_profile(mci, info);
+       if (entry) {
+               /*
+                * Two MCI interrupts are generated while connecting to
+                * headset and A2DP profile, but only one MCI interrupt
+                * is generated with last added profile type while disconnecting
+                * both profiles.
+                * So while adding second profile type decrement
+                * the first one.
+                */
+               if (entry->type != info->type) {
+                       DEC_PROF(mci, entry);
+                       INC_PROF(mci, info);
+               }
+               memcpy(entry, info, 10);
+       }
+
+       if (info->start) {
+               if (!entry && !ath_mci_add_profile(common, mci, info))
+                       return;
+       } else
+               ath_mci_del_profile(common, mci, entry);
+
+       btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD;
+       mci->aggr_limit = mci->num_sco ? 6 : 0;
+
+       btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)];
+       if (NUM_PROF(mci))
+               btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
+       else
+               btcoex->bt_stomp_type = mci->num_mgmt ? ATH_BTCOEX_STOMP_ALL :
+                                                       ATH_BTCOEX_STOMP_LOW;
+
+       ieee80211_queue_work(sc->hw, &sc->mci_work);
+}
+
+static void ath_mci_process_status(struct ath_softc *sc,
+                                  struct ath_mci_profile_status *status)
+{
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_mci_profile *mci = &btcoex->mci;
+       struct ath_mci_profile_info info;
+       int i = 0, old_num_mgmt = mci->num_mgmt;
+
+       /* Link status type are not handled */
+       if (status->is_link)
+               return;
+
+       info.conn_handle = status->conn_handle;
+       if (ath_mci_find_profile(mci, &info))
+               return;
+
+       if (status->conn_handle >= ATH_MCI_MAX_PROFILE)
+               return;
+
+       if (status->is_critical)
+               __set_bit(status->conn_handle, mci->status);
+       else
+               __clear_bit(status->conn_handle, mci->status);
+
+       mci->num_mgmt = 0;
+       do {
+               if (test_bit(i, mci->status))
+                       mci->num_mgmt++;
+       } while (++i < ATH_MCI_MAX_PROFILE);
+
+       if (old_num_mgmt != mci->num_mgmt)
+               ieee80211_queue_work(sc->hw, &sc->mci_work);
+}
+
+static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_mci_profile_info profile_info;
+       struct ath_mci_profile_status profile_status;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       u8 major, minor;
+       u32 seq_num;
+
+       switch (opcode) {
+       case MCI_GPM_COEX_VERSION_QUERY:
+               ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_COEX_VERSION);
+               break;
+       case MCI_GPM_COEX_VERSION_RESPONSE:
+               major = *(rx_payload + MCI_GPM_COEX_B_MAJOR_VERSION);
+               minor = *(rx_payload + MCI_GPM_COEX_B_MINOR_VERSION);
+               ath9k_btcoex_ar9003_mci_set_bt_version(ah, major, minor);
+               break;
+       case MCI_GPM_COEX_STATUS_QUERY:
+               ath9k_btcoex_ar9003_mci_send_wlan_channels(ah);
+               break;
+       case MCI_GPM_COEX_BT_PROFILE_INFO:
+               memcpy(&profile_info,
+                      (rx_payload + MCI_GPM_COEX_B_PROFILE_TYPE), 10);
+
+               if ((profile_info.type == MCI_GPM_COEX_PROFILE_UNKNOWN) ||
+                   (profile_info.type >= MCI_GPM_COEX_PROFILE_MAX)) {
+                       ath_dbg(common, MCI,
+                               "Illegal profile type = %d, state = %d\n",
+                               profile_info.type,
+                               profile_info.start);
+                       break;
+               }
+
+               ath_mci_process_profile(sc, &profile_info);
+               break;
+       case MCI_GPM_COEX_BT_STATUS_UPDATE:
+               profile_status.is_link = *(rx_payload +
+                                          MCI_GPM_COEX_B_STATUS_TYPE);
+               profile_status.conn_handle = *(rx_payload +
+                                              MCI_GPM_COEX_B_STATUS_LINKID);
+               profile_status.is_critical = *(rx_payload +
+                                              MCI_GPM_COEX_B_STATUS_STATE);
+
+               seq_num = *((u32 *)(rx_payload + 12));
+               ath_dbg(common, MCI,
+                       "BT_Status_Update: is_link=%d, linkId=%d, state=%d, SEQ=%u\n",
+                       profile_status.is_link, profile_status.conn_handle,
+                       profile_status.is_critical, seq_num);
+
+               ath_mci_process_status(sc, &profile_status);
+               break;
+       default:
+               ath_dbg(common, MCI, "Unknown GPM COEX message = 0x%02x\n", opcode);
+               break;
+       }
+}
+
+int ath_mci_setup(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_mci_coex *mci = &sc->mci_coex;
+       struct ath_mci_buf *buf = &mci->sched_buf;
+
+       buf->bf_addr = dma_alloc_coherent(sc->dev,
+                                 ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE,
+                                 &buf->bf_paddr, GFP_KERNEL);
+
+       if (buf->bf_addr == NULL) {
+               ath_dbg(common, FATAL, "MCI buffer alloc failed\n");
+               return -ENOMEM;
+       }
+
+       memset(buf->bf_addr, MCI_GPM_RSVD_PATTERN,
+              ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE);
+
+       mci->sched_buf.bf_len = ATH_MCI_SCHED_BUF_SIZE;
+
+       mci->gpm_buf.bf_len = ATH_MCI_GPM_BUF_SIZE;
+       mci->gpm_buf.bf_addr = (u8 *)mci->sched_buf.bf_addr + mci->sched_buf.bf_len;
+       mci->gpm_buf.bf_paddr = mci->sched_buf.bf_paddr + mci->sched_buf.bf_len;
+
+       ath9k_btcoex_ar9003_mci_setup(sc->sc_ah, mci->gpm_buf.bf_paddr,
+                        mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4),
+                        mci->sched_buf.bf_paddr);
+
+       INIT_WORK(&sc->mci_work, ath9k_mci_work);
+       ath_dbg(common, MCI, "MCI Initialized\n");
+
+       return 0;
+}
+
+void ath_mci_cleanup(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_mci_coex *mci = &sc->mci_coex;
+       struct ath_mci_buf *buf = &mci->sched_buf;
+
+       if (buf->bf_addr)
+               dma_free_coherent(sc->dev,
+                                 ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE,
+                                 buf->bf_addr, buf->bf_paddr);
+
+       ath9k_btcoex_ar9003_mci_cleanup(ah);
+
+       ath_dbg(common, MCI, "MCI De-Initialized\n");
+}
+
+void ath_mci_intr(struct ath_softc *sc)
+{
+       struct ath_mci_coex *mci = &sc->mci_coex;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
+       u32 mci_int, mci_int_rxmsg;
+       u32 offset, subtype, opcode;
+       u32 *pgpm;
+       u32 more_data = MCI_GPM_MORE;
+       bool skip_gpm = false;
+
+       ath9k_btcoex_ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg);
+
+       if (ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_ENABLE) == 0) {
+               ath9k_btcoex_ar9003_mci_get_next_gpm_offset(ah, true, NULL);
+               return;
+       }
+
+       if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) {
+               u32 payload[4] = { 0xffffffff, 0xffffffff,
+                                  0xffffffff, 0xffffff00};
+
+               /*
+                * The following REMOTE_RESET and SYS_WAKING used to sent
+                * only when BT wake up. Now they are always sent, as a
+                * recovery method to reset BT MCI's RX alignment.
+                */
+               ath9k_btcoex_ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0,
+                                       payload, 16, true, false);
+               ath9k_btcoex_ar9003_mci_send_message(ah, MCI_SYS_WAKING, 0,
+                                       NULL, 0, true, false);
+
+               mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE;
+               ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_RESET_REQ_WAKE);
+
+               /*
+                * always do this for recovery and 2G/5G toggling and LNA_TRANS
+                */
+               ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE);
+       }
+
+       if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING) {
+               mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING;
+
+               if ((mci_hw->bt_state == MCI_BT_SLEEP) &&
+                   (ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP) !=
+                    MCI_BT_SLEEP))
+                       ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE);
+       }
+
+       if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) {
+               mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING;
+
+               if ((mci_hw->bt_state == MCI_BT_AWAKE) &&
+                   (ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP) !=
+                    MCI_BT_AWAKE))
+                       mci_hw->bt_state = MCI_BT_SLEEP;
+       }
+
+       if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) ||
+           (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) {
+               ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_RECOVER_RX);
+               skip_gpm = true;
+       }
+
+       if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO) {
+               mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO;
+               offset = ath9k_btcoex_ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET);
+       }
+
+       if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_GPM) {
+               mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_GPM;
+
+               while (more_data == MCI_GPM_MORE) {
+
+                       pgpm = mci->gpm_buf.bf_addr;
+                       offset = ath9k_btcoex_ar9003_mci_get_next_gpm_offset(ah, false,
+                                                               &more_data);
+
+                       if (offset == MCI_GPM_INVALID)
+                               break;
+
+                       pgpm += (offset >> 2);
+
+                       /*
+                        * The first dword is timer.
+                        * The real data starts from 2nd dword.
+                        */
+                       subtype = MCI_GPM_TYPE(pgpm);
+                       opcode = MCI_GPM_OPCODE(pgpm);
+
+                       if (skip_gpm)
+                               goto recycle;
+
+                       if (MCI_GPM_IS_CAL_TYPE(subtype)) {
+                               ath_mci_cal_msg(sc, subtype, (u8 *)pgpm);
+                       } else {
+                               switch (subtype) {
+                               case MCI_GPM_COEX_AGENT:
+                                       ath_mci_msg(sc, opcode, (u8 *)pgpm);
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+               recycle:
+                       MCI_GPM_RECYCLE(pgpm);
+               }
+       }
+
+       if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_HW_MSG_MASK) {
+               if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL)
+                       mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL;
+
+               if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_LNA_INFO)
+                       mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_INFO;
+
+               if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
+                       int value_dbm = MS(mci_hw->cont_status,
+                                          AR_MCI_CONT_RSSI_POWER);
+
+                       mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_INFO;
+
+                       ath_dbg(common, MCI,
+                               "MCI CONT_INFO: (%s) pri = %d pwr = %d dBm\n",
+                               MS(mci_hw->cont_status, AR_MCI_CONT_TXRX) ?
+                               "tx" : "rx",
+                               MS(mci_hw->cont_status, AR_MCI_CONT_PRIORITY),
+                               value_dbm);
+               }
+
+               if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_NACK)
+                       mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_NACK;
+
+               if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_RST)
+                       mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_RST;
+       }
+
+       if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) ||
+           (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT))
+               mci_int &= ~(AR_MCI_INTERRUPT_RX_INVALID_HDR |
+                            AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT);
+}
+
+void ath_mci_enable(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+       if (!common->btcoex_enabled)
+               return;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
+               sc->sc_ah->imask |= ATH9K_INT_MCI;
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/mci.h b/drivers/net/wireless/ath/ath9k_btcoex/mci.h
new file mode 100644 (file)
index 0000000..fc14eea
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MCI_H
+#define MCI_H
+
+#include "ar9003_mci.h"
+
+#define ATH_MCI_SCHED_BUF_SIZE         (16 * 16) /* 16 entries, 4 dword each */
+#define ATH_MCI_GPM_MAX_ENTRY          16
+#define ATH_MCI_GPM_BUF_SIZE           (ATH_MCI_GPM_MAX_ENTRY * 16)
+#define ATH_MCI_DEF_BT_PERIOD          40
+#define ATH_MCI_BDR_DUTY_CYCLE         20
+#define ATH_MCI_MAX_DUTY_CYCLE         90
+
+#define ATH_MCI_DEF_AGGR_LIMIT         6 /* in 0.24 ms */
+#define ATH_MCI_MAX_ACL_PROFILE                7
+#define ATH_MCI_MAX_SCO_PROFILE                1
+#define ATH_MCI_MAX_PROFILE            (ATH_MCI_MAX_ACL_PROFILE +\
+                                        ATH_MCI_MAX_SCO_PROFILE)
+
+#define INC_PROF(_mci, _info) do {              \
+               switch (_info->type) {           \
+               case MCI_GPM_COEX_PROFILE_RFCOMM:\
+                       _mci->num_other_acl++;   \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_A2DP:  \
+                       _mci->num_a2dp++;        \
+                       if (!_info->edr)         \
+                               _mci->num_bdr++; \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_HID:   \
+                       _mci->num_hid++;         \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_BNEP:  \
+                       _mci->num_pan++;         \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_VOICE: \
+                       _mci->num_sco++;         \
+                       break;                   \
+               default:                         \
+                       break;                   \
+               }                                \
+       } while (0)
+
+#define DEC_PROF(_mci, _info) do {              \
+               switch (_info->type) {           \
+               case MCI_GPM_COEX_PROFILE_RFCOMM:\
+                       _mci->num_other_acl--;   \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_A2DP:  \
+                       _mci->num_a2dp--;        \
+                       if (!_info->edr)         \
+                               _mci->num_bdr--; \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_HID:   \
+                       _mci->num_hid--;         \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_BNEP:  \
+                       _mci->num_pan--;         \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_VOICE: \
+                       _mci->num_sco--;         \
+                       break;                   \
+               default:                         \
+                       break;                   \
+               }                                \
+       } while (0)
+
+#define NUM_PROF(_mci) (_mci->num_other_acl + _mci->num_a2dp + \
+                        _mci->num_hid + _mci->num_pan + _mci->num_sco)
+
+struct ath_mci_profile_info {
+       u8 type;
+       u8 conn_handle;
+       bool start;
+       bool master;
+       bool edr;
+       u8 voice_type;
+       u16 T;          /* Voice: Tvoice, HID: Tsniff,        in slots */
+       u8 W;           /* Voice: Wvoice, HID: Sniff timeout, in slots */
+       u8 A;           /*                HID: Sniff attempt, in slots */
+       struct list_head list;
+};
+
+struct ath_mci_profile_status {
+       bool is_critical;
+       bool is_link;
+       u8 conn_handle;
+};
+
+struct ath_mci_profile {
+       struct list_head info;
+       DECLARE_BITMAP(status, ATH_MCI_MAX_PROFILE);
+       u16 aggr_limit;
+       u8 num_mgmt;
+       u8 num_sco;
+       u8 num_a2dp;
+       u8 num_hid;
+       u8 num_pan;
+       u8 num_other_acl;
+       u8 num_bdr;
+};
+
+struct ath_mci_buf {
+       void *bf_addr;          /* virtual addr of desc */
+       dma_addr_t bf_paddr;    /* physical addr of buffer */
+       u32 bf_len;             /* len of data */
+};
+
+struct ath_mci_coex {
+       struct ath_mci_buf sched_buf;
+       struct ath_mci_buf gpm_buf;
+};
+
+void ath_mci_flush_profile(struct ath_mci_profile *mci);
+int ath_mci_setup(struct ath_softc *sc);
+void ath_mci_cleanup(struct ath_softc *sc);
+void ath_mci_intr(struct ath_softc *sc);
+
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+void ath_mci_enable(struct ath_softc *sc);
+#else
+static inline void ath_mci_enable(struct ath_softc *sc)
+{
+}
+#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
+
+#endif /* MCI_H*/
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/pci.c b/drivers/net/wireless/ath/ath9k_btcoex/pci.c
new file mode 100644 (file)
index 0000000..0f9a2c7
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include <linux/ath9k_platform.h>
+#include <linux/module.h>
+#include "ath9k.h"
+
+static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
+       { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E  AR9462 */
+       { 0 }
+};
+
+
+/* return bus cachesize in 4B word units */
+static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
+{
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+       u8 u8tmp;
+
+       pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, &u8tmp);
+       *csz = (int)u8tmp;
+
+       /*
+        * This check was put in to avoid "unpleasant" consequences if
+        * the bootrom has not fully initialized all PCI devices.
+        * Sometimes the cache line size register is not set
+        */
+
+       if (*csz == 0)
+               *csz = DEFAULT_CACHELINE >> 2;   /* Use the default size */
+}
+
+static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
+{
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+       struct ath9k_platform_data *pdata = sc->dev->platform_data;
+
+       if (pdata) {
+               if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
+                       ath_err(common,
+                               "%s: eeprom read failed, offset %08x is out of range\n",
+                               __func__, off);
+               }
+
+               *data = pdata->eeprom_data[off];
+       } else {
+               struct ath_hw *ah = (struct ath_hw *) common->ah;
+
+               common->ops->read(ah, AR5416_EEPROM_OFFSET +
+                                     (off << AR5416_EEPROM_S));
+
+               if (!ath9k_btcoex_ath9k_hw_wait(ah,
+                                  AR_EEPROM_STATUS_DATA,
+                                  AR_EEPROM_STATUS_DATA_BUSY |
+                                  AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
+                                  AH_WAIT_TIMEOUT)) {
+                       return false;
+               }
+
+               *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA),
+                          AR_EEPROM_STATUS_DATA_VAL);
+       }
+
+       return true;
+}
+
+static void ath_pci_extn_synch_enable(struct ath_common *common)
+{
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+       struct pci_dev *pdev = to_pci_dev(sc->dev);
+       u8 lnkctl;
+
+       pci_read_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, &lnkctl);
+       lnkctl |= PCI_EXP_LNKCTL_ES;
+       pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
+}
+
+/* Need to be called after we discover btcoex capabilities */
+static void ath_pci_aspm_init(struct ath_common *common)
+{
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct pci_dev *pdev = to_pci_dev(sc->dev);
+       struct pci_dev *parent;
+       int pos;
+       u8 aspm;
+
+       if (!ah->is_pciexpress)
+               return;
+
+       pos = pci_pcie_cap(pdev);
+       if (!pos)
+               return;
+
+       parent = pdev->bus->self;
+       if (!parent)
+               return;
+
+       if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
+               /* Bluetooth coexistance requires disabling ASPM. */
+               pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);
+               aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+               pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm);
+
+               /*
+                * Both upstream and downstream PCIe components should
+                * have the same ASPM settings.
+                */
+               pos = pci_pcie_cap(parent);
+               pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);
+               aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+               pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm);
+
+               ath_info(common, "Disabling ASPM since BTCOEX is enabled\n");
+               return;
+       }
+
+       pos = pci_pcie_cap(parent);
+       pci_read_config_byte(parent, pos +  PCI_EXP_LNKCTL, &aspm);
+       if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
+               ah->aspm_enabled = true;
+               /* Initialize PCIe PM and SERDES registers. */
+               ath9k_hw_configpcipowersave(ah, false);
+               ath_info(common, "ASPM enabled: 0x%x\n", aspm);
+       }
+}
+
+static const struct ath_bus_ops ath_pci_bus_ops = {
+       .ath_bus_type = ATH_PCI,
+       .read_cachesize = ath_pci_read_cachesize,
+       .eeprom_read = ath_pci_eeprom_read,
+       .extn_synch_en = ath_pci_extn_synch_enable,
+       .aspm_init = ath_pci_aspm_init,
+};
+
+static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       void __iomem *mem;
+       struct ath_softc *sc;
+       struct ieee80211_hw *hw;
+       u8 csz;
+       u32 val;
+       int ret = 0;
+       char hw_name[64];
+
+       if (pci_enable_device(pdev))
+               return -EIO;
+
+       ret =  pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (ret) {
+               printk(KERN_ERR "ath9k: 32-bit DMA not available\n");
+               goto err_dma;
+       }
+
+       ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (ret) {
+               printk(KERN_ERR "ath9k: 32-bit DMA consistent "
+                       "DMA enable failed\n");
+               goto err_dma;
+       }
+
+       /*
+        * Cache line size is used to size and align various
+        * structures used to communicate with the hardware.
+        */
+       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+       if (csz == 0) {
+               /*
+                * Linux 2.4.18 (at least) writes the cache line size
+                * register as a 16-bit wide register which is wrong.
+                * We must have this setup properly for rx buffer
+                * DMA to work so force a reasonable value here if it
+                * comes up zero.
+                */
+               csz = L1_CACHE_BYTES / sizeof(u32);
+               pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+       }
+       /*
+        * The default setting of latency timer yields poor results,
+        * set it to the value used by other systems. It may be worth
+        * tweaking this setting more.
+        */
+       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+       pci_set_master(pdev);
+
+       /*
+        * Disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state.
+        */
+       pci_read_config_dword(pdev, 0x40, &val);
+       if ((val & 0x0000ff00) != 0)
+               pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+       ret = pci_request_region(pdev, 0, "ath9k");
+       if (ret) {
+               dev_err(&pdev->dev, "PCI memory region reserve error\n");
+               ret = -ENODEV;
+               goto err_region;
+       }
+
+       mem = pci_iomap(pdev, 0, 0);
+       if (!mem) {
+               printk(KERN_ERR "PCI memory map error\n") ;
+               ret = -EIO;
+               goto err_iomap;
+       }
+
+       hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
+       if (!hw) {
+               dev_err(&pdev->dev, "No memory for ieee80211_hw\n");
+               ret = -ENOMEM;
+               goto err_alloc_hw;
+       }
+
+       SET_IEEE80211_DEV(hw, &pdev->dev);
+       pci_set_drvdata(pdev, hw);
+
+       sc = hw->priv;
+       sc->hw = hw;
+       sc->dev = &pdev->dev;
+       sc->mem = mem;
+
+       /* Will be cleared in ath9k_start() */
+       set_bit(SC_OP_INVALID, &sc->sc_flags);
+
+       ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc);
+       if (ret) {
+               dev_err(&pdev->dev, "request_irq failed\n");
+               goto err_irq;
+       }
+
+       sc->irq = pdev->irq;
+
+       ret = ath9k_init_device(id->device, sc, &ath_pci_bus_ops);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to initialize device\n");
+               goto err_init;
+       }
+
+       ath9k_btcoex_ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
+       wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+                  hw_name, (unsigned long)mem, pdev->irq);
+
+       return 0;
+
+err_init:
+       free_irq(sc->irq, sc);
+err_irq:
+       ieee80211_free_hw(hw);
+err_alloc_hw:
+       pci_iounmap(pdev, mem);
+err_iomap:
+       pci_release_region(pdev, 0);
+err_region:
+       /* Nothing */
+err_dma:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void ath_pci_remove(struct pci_dev *pdev)
+{
+       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+       struct ath_softc *sc = hw->priv;
+       void __iomem *mem = sc->mem;
+
+       if (!is_ath9k_unloaded)
+               sc->sc_ah->ah_flags |= AH_UNPLUGGED;
+       ath9k_deinit_device(sc);
+       free_irq(sc->irq, sc);
+       ieee80211_free_hw(sc->hw);
+
+       pci_iounmap(pdev, mem);
+       pci_disable_device(pdev);
+       pci_release_region(pdev, 0);
+}
+
+#ifdef CONFIG_PM
+
+static int ath_pci_suspend(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+       struct ath_softc *sc = hw->priv;
+
+       /* The device has to be moved to FULLSLEEP forcibly.
+        * Otherwise the chip never moved to full sleep,
+        * when no interface is up.
+        */
+       ath9k_btcoex_ath9k_hw_disable(sc->sc_ah);
+       ath9k_btcoex_ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
+
+       return 0;
+}
+
+static int ath_pci_resume(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       u32 val;
+
+       /*
+        * Suspend/Resume resets the PCI configuration space, so we have to
+        * re-disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state
+        */
+       pci_read_config_dword(pdev, 0x40, &val);
+       if ((val & 0x0000ff00) != 0)
+               pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+       return 0;
+}
+
+static const struct dev_pm_ops ath9k_pm_ops = {
+       .suspend = ath_pci_suspend,
+       .resume = ath_pci_resume,
+       .freeze = ath_pci_suspend,
+       .thaw = ath_pci_resume,
+       .poweroff = ath_pci_suspend,
+       .restore = ath_pci_resume,
+};
+
+#define ATH9K_PM_OPS   (&ath9k_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define ATH9K_PM_OPS   NULL
+
+#endif /* !CONFIG_PM */
+
+
+MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
+
+static struct pci_driver ath_pci_driver = {
+       .name       = "ath9k",
+       .id_table   = ath_pci_id_table,
+       .probe      = ath_pci_probe,
+       .remove     = ath_pci_remove,
+       .driver.pm  = ATH9K_PM_OPS,
+};
+
+int ath_pci_init(void)
+{
+       return pci_register_driver(&ath_pci_driver);
+}
+
+void ath_pci_exit(void)
+{
+       pci_unregister_driver(&ath_pci_driver);
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/phy.h b/drivers/net/wireless/ath/ath9k_btcoex/phy.h
new file mode 100644 (file)
index 0000000..8b38030
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef PHY_H
+#define PHY_H
+
+#define CHANSEL_DIV            15
+#define CHANSEL_2G(_freq)      (((_freq) * 0x10000) / CHANSEL_DIV)
+#define CHANSEL_5G(_freq)      (((_freq) * 0x8000) / CHANSEL_DIV)
+
+#define AR_PHY_BASE     0x9800
+#define AR_PHY(_n)      (AR_PHY_BASE + ((_n)<<2))
+
+#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX   0x0007E000
+#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13
+#define AR_PHY_TX_GAIN_CLC       0x0000001E
+#define AR_PHY_TX_GAIN_CLC_S     1
+#define AR_PHY_TX_GAIN           0x0007F000
+#define AR_PHY_TX_GAIN_S         12
+
+#define AR_PHY_CLC_TBL1      0xa35c
+#define AR_PHY_CLC_I0        0x07ff0000
+#define AR_PHY_CLC_I0_S      16
+#define AR_PHY_CLC_Q0        0x0000ffd0
+#define AR_PHY_CLC_Q0_S      5
+
+#define ANTSWAP_AB 0x0001
+#define REDUCE_CHAIN_0 0x00000050
+#define REDUCE_CHAIN_1 0x00000051
+#define AR_PHY_CHIP_ID 0x9818
+
+#define        AR_PHY_TIMING11_SPUR_FREQ_SD            0x3FF00000
+#define        AR_PHY_TIMING11_SPUR_FREQ_SD_S          20
+
+#define AR_PHY_PLL_CONTROL 0x16180
+#define AR_PHY_PLL_MODE 0x16184
+
+#endif
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/rc.c b/drivers/net/wireless/ath/ath9k_btcoex/rc.c
new file mode 100644 (file)
index 0000000..63a1724
--- /dev/null
@@ -0,0 +1,1618 @@
+/*
+ * Copyright (c) 2004 Video54 Technologies, Inc.
+ * Copyright (c) 2004-2011 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/slab.h>
+#include <linux/export.h>
+
+#include "ath9k.h"
+
+static const struct ath_rate_table ar5416_11na_ratetable = {
+       68,
+       8, /* MCS start */
+       {
+               [0] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000,
+                       5400, 0, 12, 0, 0, 0, 0 }, /* 6 Mb */
+               [1] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000,
+                       7800,  1, 18, 0, 1, 1, 1 }, /* 9 Mb */
+               [2] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000,
+                       10000, 2, 24, 2, 2, 2, 2 }, /* 12 Mb */
+               [3] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000,
+                       13900, 3, 36, 2, 3, 3, 3 }, /* 18 Mb */
+               [4] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000,
+                       17300, 4, 48, 4, 4, 4, 4 }, /* 24 Mb */
+               [5] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000,
+                       23000, 5, 72, 4, 5, 5, 5 }, /* 36 Mb */
+               [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000,
+                       27400, 6, 96, 4, 6, 6, 6 }, /* 48 Mb */
+               [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000,
+                       29300, 7, 108, 4, 7, 7, 7 }, /* 54 Mb */
+               [8] = { RC_HT_SDT_2040, WLAN_RC_PHY_HT_20_SS, 6500,
+                       6400, 0, 0, 0, 38, 8, 38 }, /* 6.5 Mb */
+               [9] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000,
+                       12700, 1, 1, 2, 39, 9, 39 }, /* 13 Mb */
+               [10] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500,
+                       18800, 2, 2, 2, 40, 10, 40 }, /* 19.5 Mb */
+               [11] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000,
+                       25000, 3, 3, 4, 41, 11, 41 }, /* 26 Mb */
+               [12] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000,
+                       36700, 4, 4, 4, 42, 12, 42 }, /* 39 Mb */
+               [13] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000,
+                       48100, 5, 5, 4, 43, 13, 43 }, /* 52 Mb */
+               [14] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500,
+                       53500, 6, 6, 4, 44, 14, 44 }, /* 58.5 Mb */
+               [15] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000,
+                       59000, 7, 7, 4, 45, 16, 46 }, /* 65 Mb */
+               [16] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200,
+                       65400, 7, 7, 4, 45, 16, 46 }, /* 75 Mb */
+               [17] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000,
+                       12700, 8, 8, 0, 47, 17, 47 }, /* 13 Mb */
+               [18] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000,
+                       24800, 9, 9, 2, 48, 18, 48 }, /* 26 Mb */
+               [19] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000,
+                       36600, 10, 10, 2, 49, 19, 49 }, /* 39 Mb */
+               [20] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000,
+                       48100, 11, 11, 4, 50, 20, 50 }, /* 52 Mb */
+               [21] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000,
+                       69500, 12, 12, 4, 51, 21, 51 }, /* 78 Mb */
+               [22] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000,
+                       89500, 13, 13, 4, 52, 22, 52 }, /* 104 Mb */
+               [23] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000,
+                       98900, 14, 14, 4, 53, 23, 53 }, /* 117 Mb */
+               [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000,
+                       108300, 15, 15, 4, 54, 25, 55 }, /* 130 Mb */
+               [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400,
+                       120000, 15, 15, 4, 54, 25, 55 }, /* 144.4 Mb */
+               [26] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500,
+                       17400, 16, 16, 0, 56, 26, 56 }, /* 19.5 Mb */
+               [27] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000,
+                       35100, 17, 17, 2, 57, 27, 57 }, /* 39 Mb */
+               [28] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500,
+                       52600, 18, 18, 2, 58, 28, 58 }, /* 58.5 Mb */
+               [29] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000,
+                       70400, 19, 19, 4, 59, 29, 59 }, /* 78 Mb */
+               [30] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000,
+                       104900, 20, 20, 4, 60, 31, 61 }, /* 117 Mb */
+               [31] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000,
+                       115800, 20, 20, 4, 60, 31, 61 }, /* 130 Mb*/
+               [32] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000,
+                       137200, 21, 21, 4, 62, 33, 63 }, /* 156 Mb */
+               [33] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300,
+                       151100, 21, 21, 4, 62, 33, 63 }, /* 173.3 Mb */
+               [34] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500,
+                       152800, 22, 22, 4, 64, 35, 65 }, /* 175.5 Mb */
+               [35] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000,
+                       168400, 22, 22, 4, 64, 35, 65 }, /* 195 Mb*/
+               [36] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000,
+                       168400, 23, 23, 4, 66, 37, 67 }, /* 195 Mb */
+               [37] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700,
+                       185000, 23, 23, 4, 66, 37, 67 }, /* 216.7 Mb */
+               [38] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500,
+                       13200, 0, 0, 0, 38, 38, 38 }, /* 13.5 Mb*/
+               [39] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500,
+                       25900, 1, 1, 2, 39, 39, 39 }, /* 27.0 Mb*/
+               [40] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500,
+                       38600, 2, 2, 2, 40, 40, 40 }, /* 40.5 Mb*/
+               [41] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000,
+                       49800, 3, 3, 4, 41, 41, 41 }, /* 54 Mb */
+               [42] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500,
+                       72200, 4, 4, 4, 42, 42, 42 }, /* 81 Mb */
+               [43] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 108000,
+                       92900, 5, 5, 4, 43, 43, 43 }, /* 108 Mb */
+               [44] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500,
+                       102700, 6, 6, 4, 44, 44, 44 }, /* 121.5 Mb*/
+               [45] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000,
+                       112000, 7, 7, 4, 45, 46, 46 }, /* 135 Mb */
+               [46] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000,
+                       122000, 7, 7, 4, 45, 46, 46 }, /* 150 Mb */
+               [47] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000,
+                       25800, 8, 8, 0, 47, 47, 47 }, /* 27 Mb */
+               [48] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000,
+                       49800, 9, 9, 2, 48, 48, 48 }, /* 54 Mb */
+               [49] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000,
+                       71900, 10, 10, 2, 49, 49, 49 }, /* 81 Mb */
+               [50] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000,
+                       92500, 11, 11, 4, 50, 50, 50 }, /* 108 Mb */
+               [51] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000,
+                       130300, 12, 12, 4, 51, 51, 51 }, /* 162 Mb */
+               [52] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000,
+                       162800, 13, 13, 4, 52, 52, 52 }, /* 216 Mb */
+               [53] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000,
+                       178200, 14, 14, 4, 53, 53, 53 }, /* 243 Mb */
+               [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000,
+                       192100, 15, 15, 4, 54, 55, 55 }, /* 270 Mb */
+               [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000,
+                       207000, 15, 15, 4, 54, 55, 55 }, /* 300 Mb */
+               [56] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500,
+                       36100, 16, 16, 0, 56, 56, 56 }, /* 40.5 Mb */
+               [57] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000,
+                       72900, 17, 17, 2, 57, 57, 57 }, /* 81 Mb */
+               [58] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500,
+                       108300, 18, 18, 2, 58, 58, 58 }, /* 121.5 Mb */
+               [59] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000,
+                       142000, 19, 19, 4, 59, 59, 59 }, /*  162 Mb */
+               [60] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
+                       205100, 20, 20, 4, 60, 61, 61 }, /*  243 Mb */
+               [61] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
+                       224700, 20, 20, 4, 60, 61, 61 }, /*  270 Mb */
+               [62] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
+                       263100, 21, 21, 4, 62, 63, 63 }, /*  324 Mb */
+               [63] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
+                       288000, 21, 21, 4, 62, 63, 63 }, /*  360 Mb */
+               [64] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500,
+                       290700, 22, 22, 4, 64, 65, 65 }, /* 364.5 Mb */
+               [65] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000,
+                       317200, 22, 22, 4, 64, 65, 65 }, /* 405 Mb */
+               [66] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000,
+                       317200, 23, 23, 4, 66, 67, 67 }, /* 405 Mb */
+               [67] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000,
+                       346400, 23, 23, 4, 66, 67, 67 }, /* 450 Mb */
+       },
+       50,  /* probe interval */
+       WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
+};
+
+/* 4ms frame limit not used for NG mode.  The values filled
+ * for HT are the 64K max aggregate limit */
+
+static const struct ath_rate_table ar5416_11ng_ratetable = {
+       72,
+       12, /* MCS start */
+       {
+               [0] = { RC_ALL, WLAN_RC_PHY_CCK, 1000,
+                       900, 0, 2, 0, 0, 0, 0 }, /* 1 Mb */
+               [1] = { RC_ALL, WLAN_RC_PHY_CCK, 2000,
+                       1900, 1, 4, 1, 1, 1, 1 }, /* 2 Mb */
+               [2] = { RC_ALL, WLAN_RC_PHY_CCK, 5500,
+                       4900, 2, 11, 2, 2, 2, 2 }, /* 5.5 Mb */
+               [3] = { RC_ALL, WLAN_RC_PHY_CCK, 11000,
+                       8100, 3, 22, 3, 3, 3, 3 }, /* 11 Mb */
+               [4] = { RC_INVALID, WLAN_RC_PHY_OFDM, 6000,
+                       5400, 4, 12, 4, 4, 4, 4 }, /* 6 Mb */
+               [5] = { RC_INVALID, WLAN_RC_PHY_OFDM, 9000,
+                       7800, 5, 18, 4, 5, 5, 5 }, /* 9 Mb */
+               [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000,
+                       10100, 6, 24, 6, 6, 6, 6 }, /* 12 Mb */
+               [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000,
+                       14100, 7, 36, 6, 7, 7, 7 }, /* 18 Mb */
+               [8] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000,
+                       17700, 8, 48, 8, 8, 8, 8 }, /* 24 Mb */
+               [9] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000,
+                       23700, 9, 72, 8, 9, 9, 9 }, /* 36 Mb */
+               [10] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000,
+                       27400, 10, 96, 8, 10, 10, 10 }, /* 48 Mb */
+               [11] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000,
+                       30900, 11, 108, 8, 11, 11, 11 }, /* 54 Mb */
+               [12] = { RC_INVALID, WLAN_RC_PHY_HT_20_SS, 6500,
+                       6400, 0, 0, 4, 42, 12, 42 }, /* 6.5 Mb */
+               [13] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000,
+                       12700, 1, 1, 6, 43, 13, 43 }, /* 13 Mb */
+               [14] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500,
+                       18800, 2, 2, 6, 44, 14, 44 }, /* 19.5 Mb*/
+               [15] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000,
+                       25000, 3, 3, 8, 45, 15, 45 }, /* 26 Mb */
+               [16] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000,
+                       36700, 4, 4, 8, 46, 16, 46 }, /* 39 Mb */
+               [17] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000,
+                       48100, 5, 5, 8, 47, 17, 47 }, /* 52 Mb */
+               [18] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500,
+                       53500, 6, 6, 8, 48, 18, 48 }, /* 58.5 Mb */
+               [19] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000,
+                       59000, 7, 7, 8, 49, 20, 50 }, /* 65 Mb */
+               [20] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200,
+                       65400, 7, 7, 8, 49, 20, 50 }, /* 65 Mb*/
+               [21] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000,
+                       12700, 8, 8, 4, 51, 21, 51 }, /* 13 Mb */
+               [22] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000,
+                       24800, 9, 9, 6, 52, 22, 52 }, /* 26 Mb */
+               [23] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000,
+                       36600, 10, 10, 6, 53, 23, 53 }, /* 39 Mb */
+               [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000,
+                       48100, 11, 11, 8, 54, 24, 54 }, /* 52 Mb */
+               [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000,
+                       69500, 12, 12, 8, 55, 25, 55 }, /* 78 Mb */
+               [26] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000,
+                       89500, 13, 13, 8, 56, 26, 56 }, /* 104 Mb */
+               [27] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000,
+                       98900, 14, 14, 8, 57, 27, 57 }, /* 117 Mb */
+               [28] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000,
+                       108300, 15, 15, 8, 58, 29, 59 }, /* 130 Mb */
+               [29] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400,
+                       120000, 15, 15, 8, 58, 29, 59 }, /* 144.4 Mb */
+               [30] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500,
+                       17400, 16, 16, 4, 60, 30, 60 }, /* 19.5 Mb */
+               [31] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000,
+                       35100, 17, 17, 6, 61, 31, 61 }, /* 39 Mb */
+               [32] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500,
+                       52600, 18, 18, 6, 62, 32, 62 }, /* 58.5 Mb */
+               [33] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000,
+                       70400, 19, 19, 8, 63, 33, 63 }, /* 78 Mb */
+               [34] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000,
+                       104900, 20, 20, 8, 64, 35, 65 }, /* 117 Mb */
+               [35] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000,
+                       115800, 20, 20, 8, 64, 35, 65 }, /* 130 Mb */
+               [36] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000,
+                       137200, 21, 21, 8, 66, 37, 67 }, /* 156 Mb */
+               [37] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300,
+                       151100, 21, 21, 8, 66, 37, 67 }, /* 173.3 Mb */
+               [38] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500,
+                       152800, 22, 22, 8, 68, 39, 69 }, /* 175.5 Mb */
+               [39] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000,
+                       168400, 22, 22, 8, 68, 39, 69 }, /* 195 Mb */
+               [40] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000,
+                       168400, 23, 23, 8, 70, 41, 71 }, /* 195 Mb */
+               [41] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700,
+                       185000, 23, 23, 8, 70, 41, 71 }, /* 216.7 Mb */
+               [42] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500,
+                       13200, 0, 0, 8, 42, 42, 42 }, /* 13.5 Mb */
+               [43] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500,
+                       25900, 1, 1, 8, 43, 43, 43 }, /* 27.0 Mb */
+               [44] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500,
+                       38600, 2, 2, 8, 44, 44, 44 }, /* 40.5 Mb */
+               [45] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000,
+                       49800, 3, 3, 8, 45, 45, 45 }, /* 54 Mb */
+               [46] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500,
+                       72200, 4, 4, 8, 46, 46, 46 }, /* 81 Mb */
+               [47] = { RC_HT_S_40 , WLAN_RC_PHY_HT_40_SS, 108000,
+                       92900, 5, 5, 8, 47, 47, 47 }, /* 108 Mb */
+               [48] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500,
+                       102700, 6, 6, 8, 48, 48, 48 }, /* 121.5 Mb */
+               [49] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000,
+                       112000, 7, 7, 8, 49, 50, 50 }, /* 135 Mb */
+               [50] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000,
+                       122000, 7, 7, 8, 49, 50, 50 }, /* 150 Mb */
+               [51] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000,
+                       25800, 8, 8, 8, 51, 51, 51 }, /* 27 Mb */
+               [52] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000,
+                       49800, 9, 9, 8, 52, 52, 52 }, /* 54 Mb */
+               [53] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000,
+                       71900, 10, 10, 8, 53, 53, 53 }, /* 81 Mb */
+               [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000,
+                       92500, 11, 11, 8, 54, 54, 54 }, /* 108 Mb */
+               [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000,
+                       130300, 12, 12, 8, 55, 55, 55 }, /* 162 Mb */
+               [56] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000,
+                       162800, 13, 13, 8, 56, 56, 56 }, /* 216 Mb */
+               [57] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000,
+                       178200, 14, 14, 8, 57, 57, 57 }, /* 243 Mb */
+               [58] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000,
+                       192100, 15, 15, 8, 58, 59, 59 }, /* 270 Mb */
+               [59] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000,
+                       207000, 15, 15, 8, 58, 59, 59 }, /* 300 Mb */
+               [60] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500,
+                       36100, 16, 16, 8, 60, 60, 60 }, /* 40.5 Mb */
+               [61] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000,
+                       72900, 17, 17, 8, 61, 61, 61 }, /* 81 Mb */
+               [62] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500,
+                       108300, 18, 18, 8, 62, 62, 62 }, /* 121.5 Mb */
+               [63] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000,
+                       142000, 19, 19, 8, 63, 63, 63 }, /* 162 Mb */
+               [64] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
+                       205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */
+               [65] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
+                       224700, 20, 20, 8, 64, 65, 65 }, /* 270 Mb */
+               [66] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
+                       263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */
+               [67] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
+                       288000, 21, 21, 8, 66, 67, 67 }, /* 360 Mb */
+               [68] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500,
+                       290700, 22, 22, 8, 68, 69, 69 }, /* 364.5 Mb */
+               [69] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000,
+                       317200, 22, 22, 8, 68, 69, 69 }, /* 405 Mb */
+               [70] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000,
+                       317200, 23, 23, 8, 70, 71, 71 }, /* 405 Mb */
+               [71] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000,
+                       346400, 23, 23, 8, 70, 71, 71 }, /* 450 Mb */
+       },
+       50,  /* probe interval */
+       WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
+};
+
+static const struct ath_rate_table ar5416_11a_ratetable = {
+       8,
+       0,
+       {
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+                       5400, 0, 12, 0},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+                       7800,  1, 18, 0},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+                       10000, 2, 24, 2},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+                       13900, 3, 36, 2},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+                       17300, 4, 48, 4},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+                       23000, 5, 72, 4},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+                       27400, 6, 96, 4},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+                       29300, 7, 108, 4},
+       },
+       50,  /* probe interval */
+       0,   /* Phy rates allowed initially */
+};
+
+static const struct ath_rate_table ar5416_11g_ratetable = {
+       12,
+       0,
+       {
+               { RC_L_SDT, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
+                       900, 0, 2, 0},
+               { RC_L_SDT, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
+                       1900, 1, 4, 1},
+               { RC_L_SDT, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
+                       4900, 2, 11, 2},
+               { RC_L_SDT, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
+                       8100, 3, 22, 3},
+               { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+                       5400, 4, 12, 4},
+               { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+                       7800, 5, 18, 4},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+                       10000, 6, 24, 6},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+                       13900, 7, 36, 6},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+                       17300, 8, 48, 8},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+                       23000, 9, 72, 8},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+                       27400, 10, 96, 8},
+               { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+                       29300, 11, 108, 8},
+       },
+       50,  /* probe interval */
+       0,   /* Phy rates allowed initially */
+};
+
+static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
+                               struct ieee80211_tx_rate *rate)
+{
+       int rix = 0, i = 0;
+       static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
+
+       if (!(rate->flags & IEEE80211_TX_RC_MCS))
+               return rate->idx;
+
+       while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) {
+               rix++; i++;
+       }
+
+       rix += rate->idx + rate_table->mcs_start;
+
+       if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+           (rate->flags & IEEE80211_TX_RC_SHORT_GI))
+               rix = rate_table->info[rix].ht_index;
+       else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+               rix = rate_table->info[rix].sgi_index;
+       else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+               rix = rate_table->info[rix].cw40index;
+
+       return rix;
+}
+
+static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
+                                  struct ath_rate_priv *ath_rc_priv)
+{
+       u8 i, j, idx, idx_next;
+
+       for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
+               for (j = 0; j <= i-1; j++) {
+                       idx = ath_rc_priv->valid_rate_index[j];
+                       idx_next = ath_rc_priv->valid_rate_index[j+1];
+
+                       if (rate_table->info[idx].ratekbps >
+                               rate_table->info[idx_next].ratekbps) {
+                               ath_rc_priv->valid_rate_index[j] = idx_next;
+                               ath_rc_priv->valid_rate_index[j+1] = idx;
+                       }
+               }
+       }
+}
+
+static void ath_rc_init_valid_rate_idx(struct ath_rate_priv *ath_rc_priv)
+{
+       u8 i;
+
+       for (i = 0; i < ath_rc_priv->rate_table_size; i++)
+               ath_rc_priv->valid_rate_index[i] = 0;
+}
+
+static inline void ath_rc_set_valid_rate_idx(struct ath_rate_priv *ath_rc_priv,
+                                          u8 index, int valid_tx_rate)
+{
+       BUG_ON(index > ath_rc_priv->rate_table_size);
+       ath_rc_priv->valid_rate_index[index] = !!valid_tx_rate;
+}
+
+static inline
+int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table,
+                               struct ath_rate_priv *ath_rc_priv,
+                               u8 cur_valid_txrate,
+                               u8 *next_idx)
+{
+       u8 i;
+
+       for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) {
+               if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
+                       *next_idx = ath_rc_priv->valid_rate_index[i+1];
+                       return 1;
+               }
+       }
+
+       /* No more valid rates */
+       *next_idx = 0;
+
+       return 0;
+}
+
+/* Return true only for single stream */
+
+static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
+{
+       if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG))
+               return 0;
+       if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
+               return 0;
+       if (WLAN_RC_PHY_TS(phy) && !(capflag & WLAN_RC_TS_FLAG))
+               return 0;
+       if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
+               return 0;
+       if (!ignore_cw && WLAN_RC_PHY_HT(phy))
+               if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
+                       return 0;
+       return 1;
+}
+
+static inline int
+ath_rc_get_lower_rix(const struct ath_rate_table *rate_table,
+                    struct ath_rate_priv *ath_rc_priv,
+                    u8 cur_valid_txrate, u8 *next_idx)
+{
+       int8_t i;
+
+       for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) {
+               if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
+                       *next_idx = ath_rc_priv->valid_rate_index[i-1];
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
+                                const struct ath_rate_table *rate_table,
+                                u32 capflag)
+{
+       u8 i, hi = 0;
+
+       for (i = 0; i < rate_table->rate_cnt; i++) {
+               if (rate_table->info[i].rate_flags & RC_LEGACY) {
+                       u32 phy = rate_table->info[i].phy;
+                       u8 valid_rate_count = 0;
+
+                       if (!ath_rc_valid_phyrate(phy, capflag, 0))
+                               continue;
+
+                       valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
+
+                       ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
+                       ath_rc_priv->valid_phy_ratecnt[phy] += 1;
+                       ath_rc_set_valid_rate_idx(ath_rc_priv, i, 1);
+                       hi = i;
+               }
+       }
+
+       return hi;
+}
+
+static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
+                               const struct ath_rate_table *rate_table,
+                               struct ath_rateset *rateset,
+                               u32 capflag)
+{
+       u8 i, j, hi = 0;
+
+       /* Use intersection of working rates and valid rates */
+       for (i = 0; i < rateset->rs_nrates; i++) {
+               for (j = 0; j < rate_table->rate_cnt; j++) {
+                       u32 phy = rate_table->info[j].phy;
+                       u16 rate_flags = rate_table->info[j].rate_flags;
+                       u8 rate = rateset->rs_rates[i];
+                       u8 dot11rate = rate_table->info[j].dot11rate;
+
+                       /* We allow a rate only if its valid and the
+                        * capflag matches one of the validity
+                        * (VALID/VALID_20/VALID_40) flags */
+
+                       if ((rate == dot11rate) &&
+                           (rate_flags & WLAN_RC_CAP_MODE(capflag)) ==
+                           WLAN_RC_CAP_MODE(capflag) &&
+                           (rate_flags & WLAN_RC_CAP_STREAM(capflag)) &&
+                           !WLAN_RC_PHY_HT(phy)) {
+                               u8 valid_rate_count = 0;
+
+                               if (!ath_rc_valid_phyrate(phy, capflag, 0))
+                                       continue;
+
+                               valid_rate_count =
+                                       ath_rc_priv->valid_phy_ratecnt[phy];
+
+                               ath_rc_priv->valid_phy_rateidx[phy]
+                                       [valid_rate_count] = j;
+                               ath_rc_priv->valid_phy_ratecnt[phy] += 1;
+                               ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
+                               hi = max(hi, j);
+                       }
+               }
+       }
+
+       return hi;
+}
+
+static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
+                                 const struct ath_rate_table *rate_table,
+                                 struct ath_rateset *rateset, u32 capflag)
+{
+       u8 i, j, hi = 0;
+
+       /* Use intersection of working rates and valid rates */
+       for (i = 0; i < rateset->rs_nrates; i++) {
+               for (j = 0; j < rate_table->rate_cnt; j++) {
+                       u32 phy = rate_table->info[j].phy;
+                       u16 rate_flags = rate_table->info[j].rate_flags;
+                       u8 rate = rateset->rs_rates[i];
+                       u8 dot11rate = rate_table->info[j].dot11rate;
+
+                       if ((rate != dot11rate) || !WLAN_RC_PHY_HT(phy) ||
+                           !(rate_flags & WLAN_RC_CAP_STREAM(capflag)) ||
+                           !WLAN_RC_PHY_HT_VALID(rate_flags, capflag))
+                               continue;
+
+                       if (!ath_rc_valid_phyrate(phy, capflag, 0))
+                               continue;
+
+                       ath_rc_priv->valid_phy_rateidx[phy]
+                               [ath_rc_priv->valid_phy_ratecnt[phy]] = j;
+                       ath_rc_priv->valid_phy_ratecnt[phy] += 1;
+                       ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
+                       hi = max(hi, j);
+               }
+       }
+
+       return hi;
+}
+
+/* Finds the highest rate index we can use */
+static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
+                                struct ath_rate_priv *ath_rc_priv,
+                                const struct ath_rate_table *rate_table,
+                                int *is_probing,
+                                bool legacy)
+{
+       u32 best_thruput, this_thruput, now_msec;
+       u8 rate, next_rate, best_rate, maxindex, minindex;
+       int8_t index = 0;
+
+       now_msec = jiffies_to_msecs(jiffies);
+       *is_probing = 0;
+       best_thruput = 0;
+       maxindex = ath_rc_priv->max_valid_rate-1;
+       minindex = 0;
+       best_rate = minindex;
+
+       /*
+        * Try the higher rate first. It will reduce memory moving time
+        * if we have very good channel characteristics.
+        */
+       for (index = maxindex; index >= minindex ; index--) {
+               u8 per_thres;
+
+               rate = ath_rc_priv->valid_rate_index[index];
+               if (legacy && !(rate_table->info[rate].rate_flags & RC_LEGACY))
+                       continue;
+               if (rate > ath_rc_priv->rate_max_phy)
+                       continue;
+
+               /*
+                * For TCP the average collision rate is around 11%,
+                * so we ignore PERs less than this.  This is to
+                * prevent the rate we are currently using (whose
+                * PER might be in the 10-15 range because of TCP
+                * collisions) looking worse than the next lower
+                * rate whose PER has decayed close to 0.  If we
+                * used to next lower rate, its PER would grow to
+                * 10-15 and we would be worse off then staying
+                * at the current rate.
+                */
+               per_thres = ath_rc_priv->per[rate];
+               if (per_thres < 12)
+                       per_thres = 12;
+
+               this_thruput = rate_table->info[rate].user_ratekbps *
+                       (100 - per_thres);
+
+               if (best_thruput <= this_thruput) {
+                       best_thruput = this_thruput;
+                       best_rate    = rate;
+               }
+       }
+
+       rate = best_rate;
+
+       /*
+        * Must check the actual rate (ratekbps) to account for
+        * non-monoticity of 11g's rate table
+        */
+
+       if (rate >= ath_rc_priv->rate_max_phy) {
+               rate = ath_rc_priv->rate_max_phy;
+
+               /* Probe the next allowed phy state */
+               if (ath_rc_get_nextvalid_txrate(rate_table,
+                                       ath_rc_priv, rate, &next_rate) &&
+                   (now_msec - ath_rc_priv->probe_time >
+                    rate_table->probe_interval) &&
+                   (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
+                       rate = next_rate;
+                       ath_rc_priv->probe_rate = rate;
+                       ath_rc_priv->probe_time = now_msec;
+                       ath_rc_priv->hw_maxretry_pktcnt = 0;
+                       *is_probing = 1;
+               }
+       }
+
+       if (rate > (ath_rc_priv->rate_table_size - 1))
+               rate = ath_rc_priv->rate_table_size - 1;
+
+       if (RC_TS_ONLY(rate_table->info[rate].rate_flags) &&
+           (ath_rc_priv->ht_cap & WLAN_RC_TS_FLAG))
+               return rate;
+
+       if (RC_DS_OR_LATER(rate_table->info[rate].rate_flags) &&
+           (ath_rc_priv->ht_cap & (WLAN_RC_DS_FLAG | WLAN_RC_TS_FLAG)))
+               return rate;
+
+       if (RC_SS_OR_LEGACY(rate_table->info[rate].rate_flags))
+               return rate;
+
+       /* This should not happen */
+       WARN_ON_ONCE(1);
+
+       rate = ath_rc_priv->valid_rate_index[0];
+
+       return rate;
+}
+
+static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table,
+                                  struct ieee80211_tx_rate *rate,
+                                  struct ieee80211_tx_rate_control *txrc,
+                                  u8 tries, u8 rix, int rtsctsenable)
+{
+       rate->count = tries;
+       rate->idx = rate_table->info[rix].ratecode;
+
+       if (txrc->short_preamble)
+               rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
+       if (txrc->rts || rtsctsenable)
+               rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
+
+       if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) {
+               rate->flags |= IEEE80211_TX_RC_MCS;
+               if (WLAN_RC_PHY_40(rate_table->info[rix].phy) &&
+                   conf_is_ht40(&txrc->hw->conf))
+                       rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+               if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
+                       rate->flags |= IEEE80211_TX_RC_SHORT_GI;
+       }
+}
+
+static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
+                                  const struct ath_rate_table *rate_table,
+                                  struct ieee80211_tx_info *tx_info)
+{
+       struct ieee80211_tx_rate *rates = tx_info->control.rates;
+       int i = 0, rix = 0, cix, enable_g_protection = 0;
+
+       /* get the cix for the lowest valid rix */
+       for (i = 3; i >= 0; i--) {
+               if (rates[i].count && (rates[i].idx >= 0)) {
+                       rix = ath_rc_get_rateindex(rate_table, &rates[i]);
+                       break;
+               }
+       }
+       cix = rate_table->info[rix].ctrl_rate;
+
+       /* All protection frames are transmited at 2Mb/s for 802.11g,
+        * otherwise we transmit them at 1Mb/s */
+       if (sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ &&
+           !conf_is_ht(&sc->hw->conf))
+               enable_g_protection = 1;
+
+       /*
+        * If 802.11g protection is enabled, determine whether to use RTS/CTS or
+        * just CTS.  Note that this is only done for OFDM/HT unicast frames.
+        */
+       if ((tx_info->control.vif &&
+            tx_info->control.vif->bss_conf.use_cts_prot) &&
+           (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM ||
+            WLAN_RC_PHY_HT(rate_table->info[rix].phy))) {
+               rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT;
+               cix = rate_table->info[enable_g_protection].ctrl_rate;
+       }
+
+       tx_info->control.rts_cts_rate_idx = cix;
+}
+
+static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
+                        struct ieee80211_tx_rate_control *txrc)
+{
+       struct ath_softc *sc = priv;
+       struct ath_rate_priv *ath_rc_priv = priv_sta;
+       const struct ath_rate_table *rate_table;
+       struct sk_buff *skb = txrc->skb;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_tx_rate *rates = tx_info->control.rates;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       __le16 fc = hdr->frame_control;
+       u8 try_per_rate, i = 0, rix;
+       int is_probe = 0;
+
+       if (rate_control_send_low(sta, priv_sta, txrc))
+               return;
+
+       /*
+        * For Multi Rate Retry we use a different number of
+        * retry attempt counts. This ends up looking like this:
+        *
+        * MRR[0] = 4
+        * MRR[1] = 4
+        * MRR[2] = 4
+        * MRR[3] = 8
+        *
+        */
+       try_per_rate = 4;
+
+       rate_table = ath_rc_priv->rate_table;
+       rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
+                                    &is_probe, false);
+
+       /*
+        * If we're in HT mode and both us and our peer supports LDPC.
+        * We don't need to check our own device's capabilities as our own
+        * ht capabilities would have already been intersected with our peer's.
+        */
+       if (conf_is_ht(&sc->hw->conf) &&
+           (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
+               tx_info->flags |= IEEE80211_TX_CTL_LDPC;
+
+       if (conf_is_ht(&sc->hw->conf) &&
+           (sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))
+               tx_info->flags |= (1 << IEEE80211_TX_CTL_STBC_SHIFT);
+
+       if (is_probe) {
+               /* set one try for probe rates. For the
+                * probes don't enable rts */
+               ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
+                                      1, rix, 0);
+
+               /* Get the next tried/allowed rate. No RTS for the next series
+                * after the probe rate
+                */
+               ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
+               ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
+                                      try_per_rate, rix, 0);
+
+               tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+       } else {
+               /* Set the chosen rate. No RTS for first series entry. */
+               ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
+                                      try_per_rate, rix, 0);
+       }
+
+       /* Fill in the other rates for multirate retry */
+       for ( ; i < 3; i++) {
+
+               ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
+               /* All other rates in the series have RTS enabled */
+               ath_rc_rate_set_series(rate_table, &rates[i], txrc,
+                                      try_per_rate, rix, 1);
+       }
+
+       /* Use twice the number of tries for the last MRR segment. */
+       try_per_rate = 8;
+
+       /*
+        * If the last rate in the rate series is MCS and has
+        * more than 80% of per thresh, then use a legacy rate
+        * as last retry to ensure that the frame is tried in both
+        * MCS and legacy rate.
+        */
+       ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
+       if (WLAN_RC_PHY_HT(rate_table->info[rix].phy) &&
+           (ath_rc_priv->per[rix] > 45))
+               rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
+                               &is_probe, true);
+
+       /* All other rates in the series have RTS enabled */
+       ath_rc_rate_set_series(rate_table, &rates[i], txrc,
+                              try_per_rate, rix, 1);
+       /*
+        * NB:Change rate series to enable aggregation when operating
+        * at lower MCS rates. When first rate in series is MCS2
+        * in HT40 @ 2.4GHz, series should look like:
+        *
+        * {MCS2, MCS1, MCS0, MCS0}.
+        *
+        * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should
+        * look like:
+        *
+        * {MCS3, MCS2, MCS1, MCS1}
+        *
+        * So, set fourth rate in series to be same as third one for
+        * above conditions.
+        */
+       if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
+           (conf_is_ht(&sc->hw->conf))) {
+               u8 dot11rate = rate_table->info[rix].dot11rate;
+               u8 phy = rate_table->info[rix].phy;
+               if (i == 4 &&
+                   ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
+                    (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
+                       rates[3].idx = rates[2].idx;
+                       rates[3].flags = rates[2].flags;
+               }
+       }
+
+       /*
+        * Force hardware to use computed duration for next
+        * fragment by disabling multi-rate retry, which
+        * updates duration based on the multi-rate duration table.
+        *
+        * FIXME: Fix duration
+        */
+       if (ieee80211_has_morefrags(fc) ||
+           (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
+               rates[1].count = rates[2].count = rates[3].count = 0;
+               rates[1].idx = rates[2].idx = rates[3].idx = 0;
+               rates[0].count = ATH_TXMAXTRY;
+       }
+
+       /* Setup RTS/CTS */
+       ath_rc_rate_set_rtscts(sc, rate_table, tx_info);
+}
+
+static void ath_rc_update_per(struct ath_softc *sc,
+                             const struct ath_rate_table *rate_table,
+                             struct ath_rate_priv *ath_rc_priv,
+                                 struct ieee80211_tx_info *tx_info,
+                             int tx_rate, int xretries, int retries,
+                             u32 now_msec)
+{
+       int count, n_bad_frames;
+       u8 last_per;
+       static const u32 nretry_to_per_lookup[10] = {
+               100 * 0 / 1,
+               100 * 1 / 4,
+               100 * 1 / 2,
+               100 * 3 / 4,
+               100 * 4 / 5,
+               100 * 5 / 6,
+               100 * 6 / 7,
+               100 * 7 / 8,
+               100 * 8 / 9,
+               100 * 9 / 10
+       };
+
+       last_per = ath_rc_priv->per[tx_rate];
+       n_bad_frames = tx_info->status.ampdu_len - tx_info->status.ampdu_ack_len;
+
+       if (xretries) {
+               if (xretries == 1) {
+                       ath_rc_priv->per[tx_rate] += 30;
+                       if (ath_rc_priv->per[tx_rate] > 100)
+                               ath_rc_priv->per[tx_rate] = 100;
+               } else {
+                       /* xretries == 2 */
+                       count = ARRAY_SIZE(nretry_to_per_lookup);
+                       if (retries >= count)
+                               retries = count - 1;
+
+                       /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
+                       ath_rc_priv->per[tx_rate] =
+                               (u8)(last_per - (last_per >> 3) + (100 >> 3));
+               }
+
+               /* xretries == 1 or 2 */
+
+               if (ath_rc_priv->probe_rate == tx_rate)
+                       ath_rc_priv->probe_rate = 0;
+
+       } else { /* xretries == 0 */
+               count = ARRAY_SIZE(nretry_to_per_lookup);
+               if (retries >= count)
+                       retries = count - 1;
+
+               if (n_bad_frames) {
+                       /* new_PER = 7/8*old_PER + 1/8*(currentPER)
+                        * Assuming that n_frames is not 0.  The current PER
+                        * from the retries is 100 * retries / (retries+1),
+                        * since the first retries attempts failed, and the
+                        * next one worked.  For the one that worked,
+                        * n_bad_frames subframes out of n_frames wored,
+                        * so the PER for that part is
+                        * 100 * n_bad_frames / n_frames, and it contributes
+                        * 100 * n_bad_frames / (n_frames * (retries+1)) to
+                        * the above PER.  The expression below is a
+                        * simplified version of the sum of these two terms.
+                        */
+                       if (tx_info->status.ampdu_len > 0) {
+                               int n_frames, n_bad_tries;
+                               u8 cur_per, new_per;
+
+                               n_bad_tries = retries * tx_info->status.ampdu_len +
+                                       n_bad_frames;
+                               n_frames = tx_info->status.ampdu_len * (retries + 1);
+                               cur_per = (100 * n_bad_tries / n_frames) >> 3;
+                               new_per = (u8)(last_per - (last_per >> 3) + cur_per);
+                               ath_rc_priv->per[tx_rate] = new_per;
+                       }
+               } else {
+                       ath_rc_priv->per[tx_rate] =
+                               (u8)(last_per - (last_per >> 3) +
+                                    (nretry_to_per_lookup[retries] >> 3));
+               }
+
+
+               /*
+                * If we got at most one retry then increase the max rate if
+                * this was a probe.  Otherwise, ignore the probe.
+                */
+               if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
+                       if (retries > 0 || 2 * n_bad_frames > tx_info->status.ampdu_len) {
+                               /*
+                                * Since we probed with just a single attempt,
+                                * any retries means the probe failed.  Also,
+                                * if the attempt worked, but more than half
+                                * the subframes were bad then also consider
+                                * the probe a failure.
+                                */
+                               ath_rc_priv->probe_rate = 0;
+                       } else {
+                               u8 probe_rate = 0;
+
+                               ath_rc_priv->rate_max_phy =
+                                       ath_rc_priv->probe_rate;
+                               probe_rate = ath_rc_priv->probe_rate;
+
+                               if (ath_rc_priv->per[probe_rate] > 30)
+                                       ath_rc_priv->per[probe_rate] = 20;
+
+                               ath_rc_priv->probe_rate = 0;
+
+                               /*
+                                * Since this probe succeeded, we allow the next
+                                * probe twice as soon.  This allows the maxRate
+                                * to move up faster if the probes are
+                                * successful.
+                                */
+                               ath_rc_priv->probe_time =
+                                       now_msec - rate_table->probe_interval / 2;
+                       }
+               }
+
+               if (retries > 0) {
+                       /*
+                        * Don't update anything.  We don't know if
+                        * this was because of collisions or poor signal.
+                        */
+                       ath_rc_priv->hw_maxretry_pktcnt = 0;
+               } else {
+                       /*
+                        * It worked with no retries. First ignore bogus (small)
+                        * rssi_ack values.
+                        */
+                       if (tx_rate == ath_rc_priv->rate_max_phy &&
+                           ath_rc_priv->hw_maxretry_pktcnt < 255) {
+                               ath_rc_priv->hw_maxretry_pktcnt++;
+                       }
+
+               }
+       }
+}
+
+static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
+                                  int xretries, int retries, u8 per)
+{
+       struct ath_rc_stats *stats = &rc->rcstats[rix];
+
+       stats->xretries += xretries;
+       stats->retries += retries;
+       stats->per = per;
+}
+
+/* Update PER, RSSI and whatever else that the code thinks it is doing.
+   If you can make sense of all this, you really need to go out more. */
+
+static void ath_rc_update_ht(struct ath_softc *sc,
+                            struct ath_rate_priv *ath_rc_priv,
+                            struct ieee80211_tx_info *tx_info,
+                            int tx_rate, int xretries, int retries)
+{
+       u32 now_msec = jiffies_to_msecs(jiffies);
+       int rate;
+       u8 last_per;
+       const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
+       int size = ath_rc_priv->rate_table_size;
+
+       if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
+               return;
+
+       last_per = ath_rc_priv->per[tx_rate];
+
+       /* Update PER first */
+       ath_rc_update_per(sc, rate_table, ath_rc_priv,
+                         tx_info, tx_rate, xretries,
+                         retries, now_msec);
+
+       /*
+        * If this rate looks bad (high PER) then stop using it for
+        * a while (except if we are probing).
+        */
+       if (ath_rc_priv->per[tx_rate] >= 55 && tx_rate > 0 &&
+           rate_table->info[tx_rate].ratekbps <=
+           rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
+               ath_rc_get_lower_rix(rate_table, ath_rc_priv,
+                                    (u8)tx_rate, &ath_rc_priv->rate_max_phy);
+
+               /* Don't probe for a little while. */
+               ath_rc_priv->probe_time = now_msec;
+       }
+
+       /* Make sure the rates below this have lower PER */
+       /* Monotonicity is kept only for rates below the current rate. */
+       if (ath_rc_priv->per[tx_rate] < last_per) {
+               for (rate = tx_rate - 1; rate >= 0; rate--) {
+
+                       if (ath_rc_priv->per[rate] >
+                           ath_rc_priv->per[rate+1]) {
+                               ath_rc_priv->per[rate] =
+                                       ath_rc_priv->per[rate+1];
+                       }
+               }
+       }
+
+       /* Maintain monotonicity for rates above the current rate */
+       for (rate = tx_rate; rate < size - 1; rate++) {
+               if (ath_rc_priv->per[rate+1] <
+                   ath_rc_priv->per[rate])
+                       ath_rc_priv->per[rate+1] =
+                               ath_rc_priv->per[rate];
+       }
+
+       /* Every so often, we reduce the thresholds
+        * and PER (different for CCK and OFDM). */
+       if (now_msec - ath_rc_priv->per_down_time >=
+           rate_table->probe_interval) {
+               for (rate = 0; rate < size; rate++) {
+                       ath_rc_priv->per[rate] =
+                               7 * ath_rc_priv->per[rate] / 8;
+               }
+
+               ath_rc_priv->per_down_time = now_msec;
+       }
+
+       ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries,
+                              ath_rc_priv->per[tx_rate]);
+
+}
+
+
+static void ath_rc_tx_status(struct ath_softc *sc,
+                            struct ath_rate_priv *ath_rc_priv,
+                            struct ieee80211_tx_info *tx_info,
+                            int final_ts_idx, int xretries, int long_retry)
+{
+       const struct ath_rate_table *rate_table;
+       struct ieee80211_tx_rate *rates = tx_info->status.rates;
+       u8 flags;
+       u32 i = 0, rix;
+
+       rate_table = ath_rc_priv->rate_table;
+
+       /*
+        * If the first rate is not the final index, there
+        * are intermediate rate failures to be processed.
+        */
+       if (final_ts_idx != 0) {
+               /* Process intermediate rates that failed.*/
+               for (i = 0; i < final_ts_idx ; i++) {
+                       if (rates[i].count != 0 && (rates[i].idx >= 0)) {
+                               flags = rates[i].flags;
+
+                               /* If HT40 and we have switched mode from
+                                * 40 to 20 => don't update */
+
+                               if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+                                   !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
+                                       return;
+
+                               rix = ath_rc_get_rateindex(rate_table, &rates[i]);
+                               ath_rc_update_ht(sc, ath_rc_priv, tx_info,
+                                               rix, xretries ? 1 : 2,
+                                               rates[i].count);
+                       }
+               }
+       } else {
+               /*
+                * Handle the special case of MIMO PS burst, where the second
+                * aggregate is sent out with only one rate and one try.
+                * Treating it as an excessive retry penalizes the rate
+                * inordinately.
+                */
+               if (rates[0].count == 1 && xretries == 1)
+                       xretries = 2;
+       }
+
+       flags = rates[i].flags;
+
+       /* If HT40 and we have switched mode from 40 to 20 => don't update */
+       if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+           !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
+               return;
+
+       rix = ath_rc_get_rateindex(rate_table, &rates[i]);
+       ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries, long_retry);
+}
+
+static const
+struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
+                                            enum ieee80211_band band,
+                                            bool is_ht)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+       switch(band) {
+       case IEEE80211_BAND_2GHZ:
+               if (is_ht)
+                       return &ar5416_11ng_ratetable;
+               return &ar5416_11g_ratetable;
+       case IEEE80211_BAND_5GHZ:
+               if (is_ht)
+                       return &ar5416_11na_ratetable;
+               return &ar5416_11a_ratetable;
+       default:
+               ath_dbg(common, CONFIG, "Invalid band\n");
+               return NULL;
+       }
+}
+
+static void ath_rc_init(struct ath_softc *sc,
+                       struct ath_rate_priv *ath_rc_priv,
+                       struct ieee80211_supported_band *sband,
+                       struct ieee80211_sta *sta,
+                       const struct ath_rate_table *rate_table)
+{
+       struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_rateset *ht_mcs = &ath_rc_priv->neg_ht_rates;
+       u8 i, j, k, hi = 0, hthi = 0;
+
+       /* Initial rate table size. Will change depending
+        * on the working rate set */
+       ath_rc_priv->rate_table_size = RATE_TABLE_SIZE;
+
+       /* Initialize thresholds according to the global rate table */
+       for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
+               ath_rc_priv->per[i] = 0;
+       }
+
+       /* Determine the valid rates */
+       ath_rc_init_valid_rate_idx(ath_rc_priv);
+
+       for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
+               for (j = 0; j < RATE_TABLE_SIZE; j++)
+                       ath_rc_priv->valid_phy_rateidx[i][j] = 0;
+               ath_rc_priv->valid_phy_ratecnt[i] = 0;
+       }
+
+       if (!rateset->rs_nrates) {
+               /* No working rate, just initialize valid rates */
+               hi = ath_rc_init_validrates(ath_rc_priv, rate_table,
+                                           ath_rc_priv->ht_cap);
+       } else {
+               /* Use intersection of working rates and valid rates */
+               hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table,
+                                          rateset, ath_rc_priv->ht_cap);
+               if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
+                       hthi = ath_rc_setvalid_htrates(ath_rc_priv,
+                                                      rate_table,
+                                                      ht_mcs,
+                                                      ath_rc_priv->ht_cap);
+               }
+               hi = max(hi, hthi);
+       }
+
+       ath_rc_priv->rate_table_size = hi + 1;
+       ath_rc_priv->rate_max_phy = 0;
+       BUG_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE);
+
+       for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
+               for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
+                       ath_rc_priv->valid_rate_index[k++] =
+                               ath_rc_priv->valid_phy_rateidx[i][j];
+               }
+
+               if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1)
+                   || !ath_rc_priv->valid_phy_ratecnt[i])
+                       continue;
+
+               ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
+       }
+       BUG_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE);
+       BUG_ON(k > RATE_TABLE_SIZE);
+
+       ath_rc_priv->max_valid_rate = k;
+       ath_rc_sort_validrates(rate_table, ath_rc_priv);
+       ath_rc_priv->rate_max_phy = (k > 4) ?
+                                       ath_rc_priv->valid_rate_index[k-4] :
+                                       ath_rc_priv->valid_rate_index[k-1];
+       ath_rc_priv->rate_table = rate_table;
+
+       ath_dbg(common, CONFIG, "RC Initialized with capabilities: 0x%x\n",
+               ath_rc_priv->ht_cap);
+}
+
+static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
+                              bool is_cw40, bool is_sgi)
+{
+       u8 caps = 0;
+
+       if (sta->ht_cap.ht_supported) {
+               caps = WLAN_RC_HT_FLAG;
+               if (sta->ht_cap.mcs.rx_mask[1] && sta->ht_cap.mcs.rx_mask[2])
+                       caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG;
+               else if (sta->ht_cap.mcs.rx_mask[1])
+                       caps |= WLAN_RC_DS_FLAG;
+               if (is_cw40)
+                       caps |= WLAN_RC_40_FLAG;
+               if (is_sgi)
+                       caps |= WLAN_RC_SGI_FLAG;
+       }
+
+       return caps;
+}
+
+static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta,
+                             u8 tidno)
+{
+       struct ath_node *an = (struct ath_node *)sta->drv_priv;
+       struct ath_atx_tid *txtid;
+
+       if (!sta->ht_cap.ht_supported)
+               return false;
+
+       txtid = ATH_AN_2_TID(an, tidno);
+
+       if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS)))
+                       return true;
+       return false;
+}
+
+
+/***********************************/
+/* mac80211 Rate Control callbacks */
+/***********************************/
+
+static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
+{
+       struct ath_rc_stats *stats;
+
+       stats = &rc->rcstats[final_rate];
+       stats->success++;
+}
+
+
+static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
+                         struct ieee80211_sta *sta, void *priv_sta,
+                         struct sk_buff *skb)
+{
+       struct ath_softc *sc = priv;
+       struct ath_rate_priv *ath_rc_priv = priv_sta;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr;
+       int final_ts_idx = 0, tx_status = 0;
+       int long_retry = 0;
+       __le16 fc;
+       int i;
+
+       hdr = (struct ieee80211_hdr *)skb->data;
+       fc = hdr->frame_control;
+       for (i = 0; i < sc->hw->max_rates; i++) {
+               struct ieee80211_tx_rate *rate = &tx_info->status.rates[i];
+               if (rate->idx < 0 || !rate->count)
+                       break;
+
+               final_ts_idx = i;
+               long_retry = rate->count - 1;
+       }
+
+       if (!priv_sta || !ieee80211_is_data(fc))
+               return;
+
+       /* This packet was aggregated but doesn't carry status info */
+       if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
+           !(tx_info->flags & IEEE80211_TX_STAT_AMPDU))
+               return;
+
+       if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
+               return;
+
+       if (!(tx_info->flags & IEEE80211_TX_STAT_ACK))
+               tx_status = 1;
+
+       ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
+                        long_retry);
+
+       /* Check if aggregation has to be enabled for this tid */
+       if (conf_is_ht(&sc->hw->conf) &&
+           !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
+               if (ieee80211_is_data_qos(fc) &&
+                   skb_get_queue_mapping(skb) != IEEE80211_AC_VO) {
+                       u8 *qc, tid;
+
+                       qc = ieee80211_get_qos_ctl(hdr);
+                       tid = qc[0] & 0xf;
+
+                       if(ath_tx_aggr_check(sc, sta, tid))
+                               ieee80211_start_tx_ba_session(sta, tid, 0);
+               }
+       }
+
+       ath_debug_stat_rc(ath_rc_priv,
+               ath_rc_get_rateindex(ath_rc_priv->rate_table,
+                       &tx_info->status.rates[final_ts_idx]));
+}
+
+static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
+                          struct ieee80211_sta *sta, void *priv_sta)
+{
+       struct ath_softc *sc = priv;
+       struct ath_rate_priv *ath_rc_priv = priv_sta;
+       const struct ath_rate_table *rate_table;
+       bool is_cw40, is_sgi = false;
+       int i, j = 0;
+
+       for (i = 0; i < sband->n_bitrates; i++) {
+               if (sta->supp_rates[sband->band] & BIT(i)) {
+                       ath_rc_priv->neg_rates.rs_rates[j]
+                               = (sband->bitrates[i].bitrate * 2) / 10;
+                       j++;
+               }
+       }
+       ath_rc_priv->neg_rates.rs_nrates = j;
+
+       if (sta->ht_cap.ht_supported) {
+               for (i = 0, j = 0; i < 77; i++) {
+                       if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
+                               ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
+                       if (j == ATH_RATE_MAX)
+                               break;
+               }
+               ath_rc_priv->neg_ht_rates.rs_nrates = j;
+       }
+
+       is_cw40 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
+
+       if (is_cw40)
+               is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
+       else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
+               is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
+
+       /* Choose rate table first */
+
+       rate_table = ath_choose_rate_table(sc, sband->band,
+                             sta->ht_cap.ht_supported);
+
+       ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi);
+       ath_rc_init(sc, priv_sta, sband, sta, rate_table);
+}
+
+static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
+                           struct ieee80211_sta *sta, void *priv_sta,
+                           u32 changed, enum nl80211_channel_type oper_chan_type)
+{
+       struct ath_softc *sc = priv;
+       struct ath_rate_priv *ath_rc_priv = priv_sta;
+       const struct ath_rate_table *rate_table = NULL;
+       bool oper_cw40 = false, oper_sgi;
+       bool local_cw40 = !!(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG);
+       bool local_sgi = !!(ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG);
+
+       /* FIXME: Handle AP mode later when we support CWM */
+
+       if (changed & IEEE80211_RC_HT_CHANGED) {
+               if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+                       return;
+
+               if (oper_chan_type == NL80211_CHAN_HT40MINUS ||
+                   oper_chan_type == NL80211_CHAN_HT40PLUS)
+                       oper_cw40 = true;
+
+               if (oper_cw40)
+                       oper_sgi = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+                                  true : false;
+               else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
+                       oper_sgi = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+                                  true : false;
+               else
+                       oper_sgi = false;
+
+               if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) {
+                       rate_table = ath_choose_rate_table(sc, sband->band,
+                                                  sta->ht_cap.ht_supported);
+                       ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta,
+                                                  oper_cw40, oper_sgi);
+                       ath_rc_init(sc, priv_sta, sband, sta, rate_table);
+
+                       ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG,
+                               "Operating HT Bandwidth changed to: %d\n",
+                               sc->hw->conf.channel_type);
+               }
+       }
+}
+
+#ifdef CONFIG_ATH9K_DEBUGFS
+
+static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       struct ath_rate_priv *rc = file->private_data;
+       char *buf;
+       unsigned int len = 0, max;
+       int i = 0;
+       ssize_t retval;
+
+       if (rc->rate_table == NULL)
+               return 0;
+
+       max = 80 + rc->rate_table_size * 1024 + 1;
+       buf = kmalloc(max, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       len += sprintf(buf, "%6s %6s %6s "
+                      "%10s %10s %10s %10s\n",
+                      "HT", "MCS", "Rate",
+                      "Success", "Retries", "XRetries", "PER");
+
+       for (i = 0; i < rc->rate_table_size; i++) {
+               u32 ratekbps = rc->rate_table->info[i].ratekbps;
+               struct ath_rc_stats *stats = &rc->rcstats[i];
+               char mcs[5];
+               char htmode[5];
+               int used_mcs = 0, used_htmode = 0;
+
+               if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) {
+                       used_mcs = snprintf(mcs, 5, "%d",
+                               rc->rate_table->info[i].ratecode);
+
+                       if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy))
+                               used_htmode = snprintf(htmode, 5, "HT40");
+                       else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy))
+                               used_htmode = snprintf(htmode, 5, "HT20");
+                       else
+                               used_htmode = snprintf(htmode, 5, "????");
+               }
+
+               mcs[used_mcs] = '\0';
+               htmode[used_htmode] = '\0';
+
+               len += snprintf(buf + len, max - len,
+                       "%6s %6s %3u.%d: "
+                       "%10u %10u %10u %10u\n",
+                       htmode,
+                       mcs,
+                       ratekbps / 1000,
+                       (ratekbps % 1000) / 100,
+                       stats->success,
+                       stats->retries,
+                       stats->xretries,
+                       stats->per);
+       }
+
+       if (len > max)
+               len = max;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+       return retval;
+}
+
+static const struct file_operations fops_rcstat = {
+       .read = read_file_rcstat,
+       .open = simple_open,
+       .owner = THIS_MODULE
+};
+
+static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
+                                    struct dentry *dir)
+{
+       struct ath_rate_priv *rc = priv_sta;
+       debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat);
+}
+
+#endif /* CONFIG_ATH9K_DEBUGFS */
+
+static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+{
+       return hw->priv;
+}
+
+static void ath_rate_free(void *priv)
+{
+       return;
+}
+
+static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
+{
+       struct ath_softc *sc = priv;
+       struct ath_rate_priv *rate_priv;
+
+       rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp);
+       if (!rate_priv) {
+               ath_err(ath9k_hw_common(sc->sc_ah),
+                       "Unable to allocate private rc structure\n");
+               return NULL;
+       }
+
+       return rate_priv;
+}
+
+static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
+                             void *priv_sta)
+{
+       struct ath_rate_priv *rate_priv = priv_sta;
+       kfree(rate_priv);
+}
+
+static struct rate_control_ops ath_rate_ops = {
+       .module = NULL,
+       .name = "ath9k_btcoex_rate_cotnrol",
+       .tx_status = ath_tx_status,
+       .get_rate = ath_get_rate,
+       .rate_init = ath_rate_init,
+       .rate_update = ath_rate_update,
+       .alloc = ath_rate_alloc,
+       .free = ath_rate_free,
+       .alloc_sta = ath_rate_alloc_sta,
+       .free_sta = ath_rate_free_sta,
+#ifdef CONFIG_ATH9K_DEBUGFS
+       .add_sta_debugfs = ath_rate_add_sta_debugfs,
+#endif
+};
+
+int ath_rate_control_register(void)
+{
+       return ieee80211_rate_control_register(&ath_rate_ops);
+}
+
+void ath_rate_control_unregister(void)
+{
+       ieee80211_rate_control_unregister(&ath_rate_ops);
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/rc.h b/drivers/net/wireless/ath/ath9k_btcoex/rc.h
new file mode 100644 (file)
index 0000000..75f8e9b
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2004 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004 Video54 Technologies, Inc.
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef RC_H
+#define RC_H
+
+#include "hw.h"
+
+struct ath_softc;
+
+#define ATH_RATE_MAX     30
+#define RATE_TABLE_SIZE  72
+
+#define RC_INVALID     0x0000
+#define RC_LEGACY      0x0001
+#define RC_SS          0x0002
+#define RC_DS          0x0004
+#define RC_TS          0x0008
+#define RC_HT_20       0x0010
+#define RC_HT_40       0x0020
+
+#define RC_STREAM_MASK 0xe
+#define RC_DS_OR_LATER(f)      ((((f) & RC_STREAM_MASK) == RC_DS) || \
+                               (((f) & RC_STREAM_MASK) == (RC_DS | RC_TS)))
+#define RC_TS_ONLY(f)          (((f) & RC_STREAM_MASK) == RC_TS)
+#define RC_SS_OR_LEGACY(f)     ((f) & (RC_SS | RC_LEGACY))
+
+#define RC_HT_2040             (RC_HT_20 | RC_HT_40)
+#define RC_ALL_STREAM          (RC_SS | RC_DS | RC_TS)
+#define RC_L_SD                        (RC_LEGACY | RC_SS | RC_DS)
+#define RC_L_SDT               (RC_LEGACY | RC_SS | RC_DS | RC_TS)
+#define RC_HT_S_20             (RC_HT_20 | RC_SS)
+#define RC_HT_D_20             (RC_HT_20 | RC_DS)
+#define RC_HT_T_20             (RC_HT_20 | RC_TS)
+#define RC_HT_S_40             (RC_HT_40 | RC_SS)
+#define RC_HT_D_40             (RC_HT_40 | RC_DS)
+#define RC_HT_T_40             (RC_HT_40 | RC_TS)
+
+#define RC_HT_SD_20            (RC_HT_20 | RC_SS | RC_DS)
+#define RC_HT_DT_20            (RC_HT_20 | RC_DS | RC_TS)
+#define RC_HT_SD_40            (RC_HT_40 | RC_SS | RC_DS)
+#define RC_HT_DT_40            (RC_HT_40 | RC_DS | RC_TS)
+
+#define RC_HT_SD_2040          (RC_HT_2040 | RC_SS | RC_DS)
+#define RC_HT_SDT_2040         (RC_HT_2040 | RC_SS | RC_DS | RC_TS)
+
+#define RC_HT_SDT_20           (RC_HT_20 | RC_SS | RC_DS | RC_TS)
+#define RC_HT_SDT_40           (RC_HT_40 | RC_SS | RC_DS | RC_TS)
+
+#define RC_ALL                 (RC_LEGACY | RC_HT_2040 | RC_ALL_STREAM)
+
+enum {
+       WLAN_RC_PHY_OFDM,
+       WLAN_RC_PHY_CCK,
+       WLAN_RC_PHY_HT_20_SS,
+       WLAN_RC_PHY_HT_20_DS,
+       WLAN_RC_PHY_HT_20_TS,
+       WLAN_RC_PHY_HT_40_SS,
+       WLAN_RC_PHY_HT_40_DS,
+       WLAN_RC_PHY_HT_40_TS,
+       WLAN_RC_PHY_HT_20_SS_HGI,
+       WLAN_RC_PHY_HT_20_DS_HGI,
+       WLAN_RC_PHY_HT_20_TS_HGI,
+       WLAN_RC_PHY_HT_40_SS_HGI,
+       WLAN_RC_PHY_HT_40_DS_HGI,
+       WLAN_RC_PHY_HT_40_TS_HGI,
+       WLAN_RC_PHY_MAX
+};
+
+#define WLAN_RC_PHY_DS(_phy)   ((_phy == WLAN_RC_PHY_HT_20_DS)         \
+                               || (_phy == WLAN_RC_PHY_HT_40_DS)       \
+                               || (_phy == WLAN_RC_PHY_HT_20_DS_HGI)   \
+                               || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+#define WLAN_RC_PHY_TS(_phy)   ((_phy == WLAN_RC_PHY_HT_20_TS)         \
+                               || (_phy == WLAN_RC_PHY_HT_40_TS)       \
+                               || (_phy == WLAN_RC_PHY_HT_20_TS_HGI)   \
+                               || (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
+#define WLAN_RC_PHY_20(_phy)   ((_phy == WLAN_RC_PHY_HT_20_SS)         \
+                               || (_phy == WLAN_RC_PHY_HT_20_DS)       \
+                               || (_phy == WLAN_RC_PHY_HT_20_TS)       \
+                               || (_phy == WLAN_RC_PHY_HT_20_SS_HGI)   \
+                               || (_phy == WLAN_RC_PHY_HT_20_DS_HGI)   \
+                               || (_phy == WLAN_RC_PHY_HT_20_TS_HGI))
+#define WLAN_RC_PHY_40(_phy)   ((_phy == WLAN_RC_PHY_HT_40_SS)         \
+                               || (_phy == WLAN_RC_PHY_HT_40_DS)       \
+                               || (_phy == WLAN_RC_PHY_HT_40_TS)       \
+                               || (_phy == WLAN_RC_PHY_HT_40_SS_HGI)   \
+                               || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)   \
+                               || (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
+#define WLAN_RC_PHY_SGI(_phy)  ((_phy == WLAN_RC_PHY_HT_20_SS_HGI)      \
+                               || (_phy == WLAN_RC_PHY_HT_20_DS_HGI)   \
+                               || (_phy == WLAN_RC_PHY_HT_20_TS_HGI)   \
+                               || (_phy == WLAN_RC_PHY_HT_40_SS_HGI)   \
+                               || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)   \
+                               || (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
+
+#define WLAN_RC_PHY_HT(_phy)    (_phy >= WLAN_RC_PHY_HT_20_SS)
+
+#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ?      \
+       ((capflag & WLAN_RC_40_FLAG) ? RC_HT_40 : RC_HT_20) : RC_LEGACY))
+
+#define WLAN_RC_CAP_STREAM(capflag) (((capflag & WLAN_RC_TS_FLAG) ?    \
+       (RC_TS) : ((capflag & WLAN_RC_DS_FLAG) ? RC_DS : RC_SS)))
+
+/* Return TRUE if flag supports HT20 && client supports HT20 or
+ * return TRUE if flag supports HT40 && client supports HT40.
+ * This is used becos some rates overlap between HT20/HT40.
+ */
+#define WLAN_RC_PHY_HT_VALID(flag, capflag)                    \
+       (((flag & RC_HT_20) && !(capflag & WLAN_RC_40_FLAG)) || \
+        ((flag & RC_HT_40) && (capflag & WLAN_RC_40_FLAG)))
+
+#define WLAN_RC_DS_FLAG         (0x01)
+#define WLAN_RC_TS_FLAG         (0x02)
+#define WLAN_RC_40_FLAG         (0x04)
+#define WLAN_RC_SGI_FLAG        (0x08)
+#define WLAN_RC_HT_FLAG         (0x10)
+
+/**
+ * struct ath_rate_table - Rate Control table
+ * @rate_cnt: total number of rates for the given wireless mode
+ * @mcs_start: MCS rate index offset
+ * @rate_flags: Rate Control flags
+ * @phy: CCK/OFDM/HT20/HT40
+ * @ratekbps: rate in Kbits per second
+ * @user_ratekbps: user rate in Kbits per second
+ * @ratecode: rate that goes into HW descriptors
+ * @dot11rate: value that goes into supported
+ *     rates info element of MLME
+ * @ctrl_rate: Index of next lower basic rate, used for duration computation
+ * @cw40index: Index of rates having 40MHz channel width
+ * @sgi_index: Index of rates having Short Guard Interval
+ * @ht_index: high throughput rates having 40MHz channel width and
+ *     Short Guard Interval
+ * @probe_interval: interval for rate control to probe for other rates
+ * @initial_ratemax: initial ratemax value
+ */
+struct ath_rate_table {
+       int rate_cnt;
+       int mcs_start;
+       struct {
+               u16 rate_flags;
+               u8 phy;
+               u32 ratekbps;
+               u32 user_ratekbps;
+               u8 ratecode;
+               u8 dot11rate;
+               u8 ctrl_rate;
+               u8 cw40index;
+               u8 sgi_index;
+               u8 ht_index;
+       } info[RATE_TABLE_SIZE];
+       u32 probe_interval;
+       u8 initial_ratemax;
+};
+
+struct ath_rateset {
+       u8 rs_nrates;
+       u8 rs_rates[ATH_RATE_MAX];
+};
+
+struct ath_rc_stats {
+       u32 success;
+       u32 retries;
+       u32 xretries;
+       u8 per;
+};
+
+/**
+ * struct ath_rate_priv - Rate Control priv data
+ * @state: RC state
+ * @probe_rate: rate we are probing at
+ * @probe_time: msec timestamp for last probe
+ * @hw_maxretry_pktcnt: num of packets since we got HW max retry error
+ * @max_valid_rate: maximum number of valid rate
+ * @per_down_time: msec timestamp for last PER down step
+ * @valid_phy_ratecnt: valid rate count
+ * @rate_max_phy: phy index for the max rate
+ * @per: PER for every valid rate in %
+ * @probe_interval: interval for ratectrl to probe for other rates
+ * @ht_cap: HT capabilities
+ * @neg_rates: Negotatied rates
+ * @neg_ht_rates: Negotiated HT rates
+ */
+struct ath_rate_priv {
+       u8 rate_table_size;
+       u8 probe_rate;
+       u8 hw_maxretry_pktcnt;
+       u8 max_valid_rate;
+       u8 valid_rate_index[RATE_TABLE_SIZE];
+       u8 ht_cap;
+       u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
+       u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
+       u8 rate_max_phy;
+       u8 per[RATE_TABLE_SIZE];
+       u32 probe_time;
+       u32 per_down_time;
+       u32 probe_interval;
+       struct ath_rateset neg_rates;
+       struct ath_rateset neg_ht_rates;
+       const struct ath_rate_table *rate_table;
+
+       struct dentry *debugfs_rcstats;
+       struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
+};
+
+#ifdef CONFIG_ATH9K_RATE_CONTROL
+int ath_rate_control_register(void);
+void ath_rate_control_unregister(void);
+#else
+static inline int ath_rate_control_register(void)
+{
+       return 0;
+}
+
+static inline void ath_rate_control_unregister(void)
+{
+}
+#endif
+
+#endif /* RC_H */
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/recv.c b/drivers/net/wireless/ath/ath9k_btcoex/recv.c
new file mode 100644 (file)
index 0000000..770ccaf
--- /dev/null
@@ -0,0 +1,1252 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/dma-mapping.h>
+#include "ath9k.h"
+#include "ar9003_mac.h"
+
+#define SKB_CB_ATHBUF(__skb)   (*((struct ath_buf **)__skb->cb))
+
+static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
+{
+       return sc->ps_enabled &&
+              (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP);
+}
+
+/*
+ * Setup and link descriptors.
+ *
+ * 11N: we can no longer afford to self link the last descriptor.
+ * MAC acknowledges BA status as long as it copies frames to host
+ * buffer (or rx fifo). This can incorrectly acknowledge packets
+ * to a sender if last desc is self-linked.
+ */
+static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_desc *ds;
+       struct sk_buff *skb;
+
+       ATH_RXBUF_RESET(bf);
+
+       ds = bf->bf_desc;
+       ds->ds_link = 0; /* link to null */
+       ds->ds_data = bf->bf_buf_addr;
+
+       /* virtual addr of the beginning of the buffer. */
+       skb = bf->bf_mpdu;
+       BUG_ON(skb == NULL);
+       ds->ds_vdata = skb->data;
+
+       /*
+        * setup rx descriptors. The rx_bufsize here tells the hardware
+        * how much data it can DMA to us and that we are prepared
+        * to process
+        */
+       ath9k_btcoex_ath9k_hw_setuprxdesc(ah, ds,
+                            common->rx_bufsize,
+                            0);
+
+       if (sc->rx.rxlink == NULL)
+               ath9k_btcoex_ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+       else
+               *sc->rx.rxlink = bf->bf_daddr;
+
+       sc->rx.rxlink = &ds->ds_link;
+}
+
+static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
+{
+       /* XXX block beacon interrupts */
+       ath9k_btcoex_ath9k_hw_setantenna(sc->sc_ah, antenna);
+       sc->rx.defant = antenna;
+       sc->rx.rxotherant = 0;
+}
+
+static void ath_opmode_init(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       u32 rfilt, mfilt[2];
+
+       /* configure rx filter */
+       rfilt = ath_calcrxfilter(sc);
+       ath9k_btcoex_ath9k_hw_setrxfilter(ah, rfilt);
+
+       /* configure bssid mask */
+       ath_hw_setbssidmask(common);
+
+       /* configure operational mode */
+       ath9k_btcoex_ath9k_hw_setopmode(ah);
+
+       /* calculate and install multicast filter */
+       mfilt[0] = mfilt[1] = ~0;
+       ath9k_btcoex_ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
+}
+
+static bool ath_rx_edma_buf_link(struct ath_softc *sc,
+                                enum ath9k_rx_qtype qtype)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_rx_edma *rx_edma;
+       struct sk_buff *skb;
+       struct ath_buf *bf;
+
+       rx_edma = &sc->rx.rx_edma[qtype];
+       if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize)
+               return false;
+
+       bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
+       list_del_init(&bf->list);
+
+       skb = bf->bf_mpdu;
+
+       ATH_RXBUF_RESET(bf);
+       memset(skb->data, 0, ah->caps.rx_status_len);
+       dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+                               ah->caps.rx_status_len, DMA_TO_DEVICE);
+
+       SKB_CB_ATHBUF(skb) = bf;
+       ath9k_btcoex_ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype);
+       skb_queue_tail(&rx_edma->rx_fifo, skb);
+
+       return true;
+}
+
+static void ath_rx_addbuffer_edma(struct ath_softc *sc,
+                                 enum ath9k_rx_qtype qtype, int size)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_buf *bf, *tbf;
+
+       if (list_empty(&sc->rx.rxbuf)) {
+               ath_dbg(common, QUEUE, "No free rx buf available\n");
+               return;
+       }
+
+       list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list)
+               if (!ath_rx_edma_buf_link(sc, qtype))
+                       break;
+
+}
+
+static void ath_rx_remove_buffer(struct ath_softc *sc,
+                                enum ath9k_rx_qtype qtype)
+{
+       struct ath_buf *bf;
+       struct ath_rx_edma *rx_edma;
+       struct sk_buff *skb;
+
+       rx_edma = &sc->rx.rx_edma[qtype];
+
+       while ((skb = skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
+               bf = SKB_CB_ATHBUF(skb);
+               BUG_ON(!bf);
+               list_add_tail(&bf->list, &sc->rx.rxbuf);
+       }
+}
+
+static void ath_rx_edma_cleanup(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_buf *bf;
+
+       ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
+       ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
+
+       list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+               if (bf->bf_mpdu) {
+                       dma_unmap_single(sc->dev, bf->bf_buf_addr,
+                                       common->rx_bufsize,
+                                       DMA_BIDIRECTIONAL);
+                       dev_kfree_skb_any(bf->bf_mpdu);
+                       bf->bf_buf_addr = 0;
+                       bf->bf_mpdu = NULL;
+               }
+       }
+
+       INIT_LIST_HEAD(&sc->rx.rxbuf);
+
+       kfree(sc->rx.rx_bufptr);
+       sc->rx.rx_bufptr = NULL;
+}
+
+static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size)
+{
+       skb_queue_head_init(&rx_edma->rx_fifo);
+       rx_edma->rx_fifo_hwsize = size;
+}
+
+static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
+       struct sk_buff *skb;
+       struct ath_buf *bf;
+       int error = 0, i;
+       u32 size;
+
+       ath9k_btcoex_ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
+                                   ah->caps.rx_status_len);
+
+       ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_LP],
+                              ah->caps.rx_lp_qdepth);
+       ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP],
+                              ah->caps.rx_hp_qdepth);
+
+       size = sizeof(struct ath_buf) * nbufs;
+       bf = kzalloc(size, GFP_KERNEL);
+       if (!bf)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&sc->rx.rxbuf);
+       sc->rx.rx_bufptr = bf;
+
+       for (i = 0; i < nbufs; i++, bf++) {
+               skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL);
+               if (!skb) {
+                       error = -ENOMEM;
+                       goto rx_init_fail;
+               }
+
+               memset(skb->data, 0, common->rx_bufsize);
+               bf->bf_mpdu = skb;
+
+               bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+                                                common->rx_bufsize,
+                                                DMA_BIDIRECTIONAL);
+               if (unlikely(dma_mapping_error(sc->dev,
+                                               bf->bf_buf_addr))) {
+                               dev_kfree_skb_any(skb);
+                               bf->bf_mpdu = NULL;
+                               bf->bf_buf_addr = 0;
+                               ath_err(common,
+                                       "dma_mapping_error() on RX init\n");
+                               error = -ENOMEM;
+                               goto rx_init_fail;
+               }
+
+               list_add_tail(&bf->list, &sc->rx.rxbuf);
+       }
+
+       return 0;
+
+rx_init_fail:
+       ath_rx_edma_cleanup(sc);
+       return error;
+}
+
+static void ath_edma_start_recv(struct ath_softc *sc)
+{
+       spin_lock_bh(&sc->rx.rxbuflock);
+
+       ath9k_hw_rxena(sc->sc_ah);
+
+       ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
+                             sc->rx.rx_edma[ATH9K_RX_QUEUE_HP].rx_fifo_hwsize);
+
+       ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
+                             sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
+
+       ath_opmode_init(sc);
+
+       ath9k_btcoex_ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
+
+       spin_unlock_bh(&sc->rx.rxbuflock);
+}
+
+static void ath_edma_stop_recv(struct ath_softc *sc)
+{
+       ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
+       ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
+}
+
+int ath_rx_init(struct ath_softc *sc, int nbufs)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct sk_buff *skb;
+       struct ath_buf *bf;
+       int error = 0;
+
+       spin_lock_init(&sc->sc_pcu_lock);
+       spin_lock_init(&sc->rx.rxbuflock);
+       clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);
+
+       common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
+                            sc->sc_ah->caps.rx_status_len;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               return ath_rx_edma_init(sc, nbufs);
+       } else {
+               ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
+                       common->cachelsz, common->rx_bufsize);
+
+               /* Initialize rx descriptors */
+
+               error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
+                               "rx", nbufs, 1, 0);
+               if (error != 0) {
+                       ath_err(common,
+                               "failed to allocate rx descriptors: %d\n",
+                               error);
+                       goto err;
+               }
+
+               list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+                       skb = ath_rxbuf_alloc(common, common->rx_bufsize,
+                                             GFP_KERNEL);
+                       if (skb == NULL) {
+                               error = -ENOMEM;
+                               goto err;
+                       }
+
+                       bf->bf_mpdu = skb;
+                       bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+                                       common->rx_bufsize,
+                                       DMA_FROM_DEVICE);
+                       if (unlikely(dma_mapping_error(sc->dev,
+                                                       bf->bf_buf_addr))) {
+                               dev_kfree_skb_any(skb);
+                               bf->bf_mpdu = NULL;
+                               bf->bf_buf_addr = 0;
+                               ath_err(common,
+                                       "dma_mapping_error() on RX init\n");
+                               error = -ENOMEM;
+                               goto err;
+                       }
+               }
+               sc->rx.rxlink = NULL;
+       }
+
+err:
+       if (error)
+               ath_rx_cleanup(sc);
+
+       return error;
+}
+
+void ath_rx_cleanup(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct sk_buff *skb;
+       struct ath_buf *bf;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               ath_rx_edma_cleanup(sc);
+               return;
+       } else {
+               list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+                       skb = bf->bf_mpdu;
+                       if (skb) {
+                               dma_unmap_single(sc->dev, bf->bf_buf_addr,
+                                               common->rx_bufsize,
+                                               DMA_FROM_DEVICE);
+                               dev_kfree_skb(skb);
+                               bf->bf_buf_addr = 0;
+                               bf->bf_mpdu = NULL;
+                       }
+               }
+
+               if (sc->rx.rxdma.dd_desc_len != 0)
+                       ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
+       }
+}
+
+/*
+ * Calculate the receive filter according to the
+ * operating mode and state:
+ *
+ * o always accept unicast, broadcast, and multicast traffic
+ * o maintain current state of phy error reception (the hal
+ *   may enable phy error frames for noise immunity work)
+ * o probe request frames are accepted only when operating in
+ *   hostap, adhoc, or monitor modes
+ * o enable promiscuous mode according to the interface state
+ * o accept beacons:
+ *   - when operating in adhoc mode so the 802.11 layer creates
+ *     node table entries for peers,
+ *   - when operating in station mode for collecting rssi data when
+ *     the station is otherwise quiet, or
+ *   - when operating as a repeater so we see repeater-sta beacons
+ *   - when scanning
+ */
+
+u32 ath_calcrxfilter(struct ath_softc *sc)
+{
+       u32 rfilt;
+
+       rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
+               | ATH9K_RX_FILTER_MCAST;
+
+       if (sc->rx.rxfilter & FIF_PROBE_REQ)
+               rfilt |= ATH9K_RX_FILTER_PROBEREQ;
+
+       /*
+        * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station
+        * mode interface or when in monitor mode. AP mode does not need this
+        * since it receives all in-BSS frames anyway.
+        */
+       if (sc->sc_ah->is_monitoring)
+               rfilt |= ATH9K_RX_FILTER_PROM;
+
+       if (sc->rx.rxfilter & FIF_CONTROL)
+               rfilt |= ATH9K_RX_FILTER_CONTROL;
+
+       if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
+           (sc->nvifs <= 1) &&
+           !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC))
+               rfilt |= ATH9K_RX_FILTER_MYBEACON;
+       else
+               rfilt |= ATH9K_RX_FILTER_BEACON;
+
+       if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
+           (sc->rx.rxfilter & FIF_PSPOLL))
+               rfilt |= ATH9K_RX_FILTER_PSPOLL;
+
+       if (conf_is_ht(&sc->hw->conf))
+               rfilt |= ATH9K_RX_FILTER_COMP_BAR;
+
+       if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
+               /* The following may also be needed for other older chips */
+               if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160)
+                       rfilt |= ATH9K_RX_FILTER_PROM;
+               rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
+       }
+
+       return rfilt;
+
+}
+
+int ath_startrecv(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_buf *bf, *tbf;
+
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               ath_edma_start_recv(sc);
+               return 0;
+       }
+
+       spin_lock_bh(&sc->rx.rxbuflock);
+       if (list_empty(&sc->rx.rxbuf))
+               goto start_recv;
+
+       sc->rx.rxlink = NULL;
+       list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
+               ath_rx_buf_link(sc, bf);
+       }
+
+       /* We could have deleted elements so the list may be empty now */
+       if (list_empty(&sc->rx.rxbuf))
+               goto start_recv;
+
+       bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
+       ath9k_btcoex_ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+       ath9k_hw_rxena(ah);
+
+start_recv:
+       ath_opmode_init(sc);
+       ath9k_btcoex_ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
+
+       spin_unlock_bh(&sc->rx.rxbuflock);
+
+       return 0;
+}
+
+bool ath_stoprecv(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       bool stopped, reset = false;
+
+       spin_lock_bh(&sc->rx.rxbuflock);
+       ath9k_btcoex_ath9k_hw_abortpcurecv(ah);
+       ath9k_btcoex_ath9k_hw_setrxfilter(ah, 0);
+       stopped = ath9k_btcoex_ath9k_hw_stopdmarecv(ah, &reset);
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+               ath_edma_stop_recv(sc);
+       else
+               sc->rx.rxlink = NULL;
+       spin_unlock_bh(&sc->rx.rxbuflock);
+
+       if (!(ah->ah_flags & AH_UNPLUGGED) &&
+           unlikely(!stopped)) {
+               ath_err(ath9k_hw_common(sc->sc_ah),
+                       "Could not stop RX, we could be "
+                       "confusing the DMA engine when we start RX up\n");
+               ATH_DBG_WARN_ON_ONCE(!stopped);
+       }
+       return stopped && !reset;
+}
+
+void ath_flushrecv(struct ath_softc *sc)
+{
+       set_bit(SC_OP_RXFLUSH, &sc->sc_flags);
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+               ath_rx_tasklet(sc, 1, true);
+       ath_rx_tasklet(sc, 1, false);
+       clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);
+}
+
+static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
+{
+       /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */
+       struct ieee80211_mgmt *mgmt;
+       u8 *pos, *end, id, elen;
+       struct ieee80211_tim_ie *tim;
+
+       mgmt = (struct ieee80211_mgmt *)skb->data;
+       pos = mgmt->u.beacon.variable;
+       end = skb->data + skb->len;
+
+       while (pos + 2 < end) {
+               id = *pos++;
+               elen = *pos++;
+               if (pos + elen > end)
+                       break;
+
+               if (id == WLAN_EID_TIM) {
+                       if (elen < sizeof(*tim))
+                               break;
+                       tim = (struct ieee80211_tim_ie *) pos;
+                       if (tim->dtim_count != 0)
+                               break;
+                       return tim->bitmap_ctrl & 0x01;
+               }
+
+               pos += elen;
+       }
+
+       return false;
+}
+
+static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+       if (skb->len < 24 + 8 + 2 + 2)
+               return;
+
+       sc->ps_flags &= ~PS_WAIT_FOR_BEACON;
+
+       if (sc->ps_flags & PS_BEACON_SYNC) {
+               sc->ps_flags &= ~PS_BEACON_SYNC;
+               ath_dbg(common, PS,
+                       "Reconfigure Beacon timers based on timestamp from the AP\n");
+               ath9k_set_beacon(sc);
+       }
+
+       if (ath_beacon_dtim_pending_cab(skb)) {
+               /*
+                * Remain awake waiting for buffered broadcast/multicast
+                * frames. If the last broadcast/multicast frame is not
+                * received properly, the next beacon frame will work as
+                * a backup trigger for returning into NETWORK SLEEP state,
+                * so we are waiting for it as well.
+                */
+               ath_dbg(common, PS,
+                       "Received DTIM beacon indicating buffered broadcast/multicast frame(s)\n");
+               sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON;
+               return;
+       }
+
+       if (sc->ps_flags & PS_WAIT_FOR_CAB) {
+               /*
+                * This can happen if a broadcast frame is dropped or the AP
+                * fails to send a frame indicating that all CAB frames have
+                * been delivered.
+                */
+               sc->ps_flags &= ~PS_WAIT_FOR_CAB;
+               ath_dbg(common, PS, "PS wait for CAB frames timed out\n");
+       }
+}
+
+static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)
+{
+       struct ieee80211_hdr *hdr;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+       hdr = (struct ieee80211_hdr *)skb->data;
+
+       /* Process Beacon and CAB receive in PS state */
+       if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc))
+           && mybeacon)
+               ath_rx_ps_beacon(sc, skb);
+       else if ((sc->ps_flags & PS_WAIT_FOR_CAB) &&
+                (ieee80211_is_data(hdr->frame_control) ||
+                 ieee80211_is_action(hdr->frame_control)) &&
+                is_multicast_ether_addr(hdr->addr1) &&
+                !ieee80211_has_moredata(hdr->frame_control)) {
+               /*
+                * No more broadcast/multicast frames to be received at this
+                * point.
+                */
+               sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON);
+               ath_dbg(common, PS,
+                       "All PS CAB frames received, back to sleep\n");
+       } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) &&
+                  !is_multicast_ether_addr(hdr->addr1) &&
+                  !ieee80211_has_morefrags(hdr->frame_control)) {
+               sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA;
+               ath_dbg(common, PS,
+                       "Going back to sleep after having received PS-Poll data (0x%lx)\n",
+                       sc->ps_flags & (PS_WAIT_FOR_BEACON |
+                                       PS_WAIT_FOR_CAB |
+                                       PS_WAIT_FOR_PSPOLL_DATA |
+                                       PS_WAIT_FOR_TX_ACK));
+       }
+}
+
+static bool ath_edma_get_buffers(struct ath_softc *sc,
+                                enum ath9k_rx_qtype qtype,
+                                struct ath_rx_status *rs,
+                                struct ath_buf **dest)
+{
+       struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct sk_buff *skb;
+       struct ath_buf *bf;
+       int ret;
+
+       skb = skb_peek(&rx_edma->rx_fifo);
+       if (!skb)
+               return false;
+
+       bf = SKB_CB_ATHBUF(skb);
+       BUG_ON(!bf);
+
+       dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
+                               common->rx_bufsize, DMA_FROM_DEVICE);
+
+       ret = ath9k_btcoex_ath9k_hw_process_rxdesc_edma(ah, rs, skb->data);
+       if (ret == -EINPROGRESS) {
+               /*let device gain the buffer again*/
+               dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+                               common->rx_bufsize, DMA_FROM_DEVICE);
+               return false;
+       }
+
+       __skb_unlink(skb, &rx_edma->rx_fifo);
+       if (ret == -EINVAL) {
+               /* corrupt descriptor, skip this one and the following one */
+               list_add_tail(&bf->list, &sc->rx.rxbuf);
+               ath_rx_edma_buf_link(sc, qtype);
+
+               skb = skb_peek(&rx_edma->rx_fifo);
+               if (skb) {
+                       bf = SKB_CB_ATHBUF(skb);
+                       BUG_ON(!bf);
+
+                       __skb_unlink(skb, &rx_edma->rx_fifo);
+                       list_add_tail(&bf->list, &sc->rx.rxbuf);
+                       ath_rx_edma_buf_link(sc, qtype);
+               }
+
+               bf = NULL;
+       }
+
+       *dest = bf;
+       return true;
+}
+
+static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc,
+                                               struct ath_rx_status *rs,
+                                               enum ath9k_rx_qtype qtype)
+{
+       struct ath_buf *bf = NULL;
+
+       while (ath_edma_get_buffers(sc, qtype, rs, &bf)) {
+               if (!bf)
+                       continue;
+
+               return bf;
+       }
+       return NULL;
+}
+
+static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
+                                          struct ath_rx_status *rs)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_desc *ds;
+       struct ath_buf *bf;
+       int ret;
+
+       if (list_empty(&sc->rx.rxbuf)) {
+               sc->rx.rxlink = NULL;
+               return NULL;
+       }
+
+       bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
+       ds = bf->bf_desc;
+
+       /*
+        * Must provide the virtual address of the current
+        * descriptor, the physical address, and the virtual
+        * address of the next descriptor in the h/w chain.
+        * This allows the HAL to look ahead to see if the
+        * hardware is done with a descriptor by checking the
+        * done bit in the following descriptor and the address
+        * of the current descriptor the DMA engine is working
+        * on.  All this is necessary because of our use of
+        * a self-linked list to avoid rx overruns.
+        */
+       ret = ath9k_btcoex_ath9k_hw_rxprocdesc(ah, ds, rs);
+       if (ret == -EINPROGRESS) {
+               struct ath_rx_status trs;
+               struct ath_buf *tbf;
+               struct ath_desc *tds;
+
+               memset(&trs, 0, sizeof(trs));
+               if (list_is_last(&bf->list, &sc->rx.rxbuf)) {
+                       sc->rx.rxlink = NULL;
+                       return NULL;
+               }
+
+               tbf = list_entry(bf->list.next, struct ath_buf, list);
+
+               /*
+                * On some hardware the descriptor status words could
+                * get corrupted, including the done bit. Because of
+                * this, check if the next descriptor's done bit is
+                * set or not.
+                *
+                * If the next descriptor's done bit is set, the current
+                * descriptor has been corrupted. Force s/w to discard
+                * this descriptor and continue...
+                */
+
+               tds = tbf->bf_desc;
+               ret = ath9k_btcoex_ath9k_hw_rxprocdesc(ah, tds, &trs);
+               if (ret == -EINPROGRESS)
+                       return NULL;
+       }
+
+       if (!bf->bf_mpdu)
+               return bf;
+
+       /*
+        * Synchronize the DMA transfer with CPU before
+        * 1. accessing the frame
+        * 2. requeueing the same buffer to h/w
+        */
+       dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
+                       common->rx_bufsize,
+                       DMA_FROM_DEVICE);
+
+       return bf;
+}
+
+/* Assumes you've already done the endian to CPU conversion */
+static bool ath9k_rx_accept(struct ath_common *common,
+                           struct ieee80211_hdr *hdr,
+                           struct ieee80211_rx_status *rxs,
+                           struct ath_rx_status *rx_stats,
+                           bool *decrypt_error)
+{
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+       bool is_mc, is_valid_tkip, strip_mic, mic_error;
+       struct ath_hw *ah = common->ah;
+       __le16 fc;
+       u8 rx_status_len = ah->caps.rx_status_len;
+
+       fc = hdr->frame_control;
+
+       is_mc = !!is_multicast_ether_addr(hdr->addr1);
+       is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
+               test_bit(rx_stats->rs_keyix, common->tkip_keymap);
+       strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
+               ieee80211_has_protected(fc) &&
+               !(rx_stats->rs_status &
+               (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
+                ATH9K_RXERR_KEYMISS));
+
+       /*
+        * Key miss events are only relevant for pairwise keys where the
+        * descriptor does contain a valid key index. This has been observed
+        * mostly with CCMP encryption.
+        */
+       if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID)
+               rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
+
+       if (!rx_stats->rs_datalen)
+               return false;
+        /*
+         * rs_status follows rs_datalen so if rs_datalen is too large
+         * we can take a hint that hardware corrupted it, so ignore
+         * those frames.
+         */
+       if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len))
+               return false;
+
+       /* Only use error bits from the last fragment */
+       if (rx_stats->rs_more)
+               return true;
+
+       mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
+               !ieee80211_has_morefrags(fc) &&
+               !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
+               (rx_stats->rs_status & ATH9K_RXERR_MIC);
+
+       /*
+        * The rx_stats->rs_status will not be set until the end of the
+        * chained descriptors so it can be ignored if rs_more is set. The
+        * rs_more will be false at the last element of the chained
+        * descriptors.
+        */
+       if (rx_stats->rs_status != 0) {
+               u8 status_mask;
+
+               if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
+                       rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
+                       mic_error = false;
+               }
+               if (rx_stats->rs_status & ATH9K_RXERR_PHY)
+                       return false;
+
+               if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
+                   (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
+                       *decrypt_error = true;
+                       mic_error = false;
+               }
+
+               /*
+                * Reject error frames with the exception of
+                * decryption and MIC failures. For monitor mode,
+                * we also ignore the CRC error.
+                */
+               status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
+                             ATH9K_RXERR_KEYMISS;
+
+               if (ah->is_monitoring && (sc->rx.rxfilter & FIF_FCSFAIL))
+                       status_mask |= ATH9K_RXERR_CRC;
+
+               if (rx_stats->rs_status & ~status_mask)
+                       return false;
+       }
+
+       /*
+        * For unicast frames the MIC error bit can have false positives,
+        * so all MIC error reports need to be validated in software.
+        * False negatives are not common, so skip software verification
+        * if the hardware considers the MIC valid.
+        */
+       if (strip_mic)
+               rxs->flag |= RX_FLAG_MMIC_STRIPPED;
+       else if (is_mc && mic_error)
+               rxs->flag |= RX_FLAG_MMIC_ERROR;
+
+       return true;
+}
+
+static int ath9k_process_rate(struct ath_common *common,
+                             struct ieee80211_hw *hw,
+                             struct ath_rx_status *rx_stats,
+                             struct ieee80211_rx_status *rxs)
+{
+       struct ieee80211_supported_band *sband;
+       enum ieee80211_band band;
+       unsigned int i = 0;
+
+       band = hw->conf.channel->band;
+       sband = hw->wiphy->bands[band];
+
+       if (rx_stats->rs_rate & 0x80) {
+               /* HT rate */
+               rxs->flag |= RX_FLAG_HT;
+               if (rx_stats->rs_flags & ATH9K_RX_2040)
+                       rxs->flag |= RX_FLAG_40MHZ;
+               if (rx_stats->rs_flags & ATH9K_RX_GI)
+                       rxs->flag |= RX_FLAG_SHORT_GI;
+               rxs->rate_idx = rx_stats->rs_rate & 0x7f;
+               return 0;
+       }
+
+       for (i = 0; i < sband->n_bitrates; i++) {
+               if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
+                       rxs->rate_idx = i;
+                       return 0;
+               }
+               if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
+                       rxs->flag |= RX_FLAG_SHORTPRE;
+                       rxs->rate_idx = i;
+                       return 0;
+               }
+       }
+
+       /*
+        * No valid hardware bitrate found -- we should not get here
+        * because hardware has already validated this frame as OK.
+        */
+       ath_dbg(common, ANY,
+               "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
+               rx_stats->rs_rate);
+
+       return -EINVAL;
+}
+
+static void ath9k_process_rssi(struct ath_common *common,
+                              struct ieee80211_hw *hw,
+                              struct ieee80211_hdr *hdr,
+                              struct ath_rx_status *rx_stats)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = common->ah;
+       int last_rssi;
+       int rssi = rx_stats->rs_rssi;
+
+       if (!rx_stats->is_mybeacon ||
+           ((ah->opmode != NL80211_IFTYPE_STATION) &&
+            (ah->opmode != NL80211_IFTYPE_ADHOC)))
+               return;
+
+       if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
+               ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
+
+       last_rssi = sc->last_rssi;
+       if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+               rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
+       if (rssi < 0)
+               rssi = 0;
+
+       /* Update Beacon RSSI, this is used by ANI. */
+       ah->stats.avgbrssi = rssi;
+}
+
+/*
+ * For Decrypt or Demic errors, we only mark packet status here and always push
+ * up the frame up to let mac80211 handle the actual error case, be it no
+ * decryption key or real decryption error. This let us keep statistics there.
+ */
+static int ath9k_rx_skb_preprocess(struct ath_common *common,
+                                  struct ieee80211_hw *hw,
+                                  struct ieee80211_hdr *hdr,
+                                  struct ath_rx_status *rx_stats,
+                                  struct ieee80211_rx_status *rx_status,
+                                  bool *decrypt_error)
+{
+       struct ath_hw *ah = common->ah;
+
+       /*
+        * everything but the rate is checked here, the rate check is done
+        * separately to avoid doing two lookups for a rate for each frame.
+        */
+       if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
+               return -EINVAL;
+
+       /* Only use status info from the last fragment */
+       if (rx_stats->rs_more)
+               return 0;
+
+       ath9k_process_rssi(common, hw, hdr, rx_stats);
+
+       if (ath9k_process_rate(common, hw, rx_stats, rx_status))
+               return -EINVAL;
+
+       rx_status->band = hw->conf.channel->band;
+       rx_status->freq = hw->conf.channel->center_freq;
+       rx_status->signal = ah->noise + rx_stats->rs_rssi;
+       rx_status->antenna = rx_stats->rs_antenna;
+       rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+       if (rx_stats->rs_moreaggr)
+               rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+
+       return 0;
+}
+
+static void ath9k_rx_skb_postprocess(struct ath_common *common,
+                                    struct sk_buff *skb,
+                                    struct ath_rx_status *rx_stats,
+                                    struct ieee80211_rx_status *rxs,
+                                    bool decrypt_error)
+{
+       struct ath_hw *ah = common->ah;
+       struct ieee80211_hdr *hdr;
+       int hdrlen, padpos, padsize;
+       u8 keyix;
+       __le16 fc;
+
+       /* see if any padding is done by the hw and remove it */
+       hdr = (struct ieee80211_hdr *) skb->data;
+       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+       fc = hdr->frame_control;
+       padpos = ath9k_btcoex_ath9k_cmn_padpos(hdr->frame_control);
+
+       /* The MAC header is padded to have 32-bit boundary if the
+        * packet payload is non-zero. The general calculation for
+        * padsize would take into account odd header lengths:
+        * padsize = (4 - padpos % 4) % 4; However, since only
+        * even-length headers are used, padding can only be 0 or 2
+        * bytes and we can optimize this a bit. In addition, we must
+        * not try to remove padding from short control frames that do
+        * not have payload. */
+       padsize = padpos & 3;
+       if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
+               memmove(skb->data + padsize, skb->data, padpos);
+               skb_pull(skb, padsize);
+       }
+
+       keyix = rx_stats->rs_keyix;
+
+       if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
+           ieee80211_has_protected(fc)) {
+               rxs->flag |= RX_FLAG_DECRYPTED;
+       } else if (ieee80211_has_protected(fc)
+                  && !decrypt_error && skb->len >= hdrlen + 4) {
+               keyix = skb->data[hdrlen + 3] >> 6;
+
+               if (test_bit(keyix, common->keymap))
+                       rxs->flag |= RX_FLAG_DECRYPTED;
+       }
+       if (ah->sw_mgmt_crypto &&
+           (rxs->flag & RX_FLAG_DECRYPTED) &&
+           ieee80211_is_mgmt(fc))
+               /* Use software decrypt for management frames. */
+               rxs->flag &= ~RX_FLAG_DECRYPTED;
+}
+
+int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
+{
+       struct ath_buf *bf;
+       struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb;
+       struct ieee80211_rx_status *rxs;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_hw *hw = sc->hw;
+       struct ieee80211_hdr *hdr;
+       int retval;
+       bool decrypt_error = false;
+       struct ath_rx_status rs;
+       enum ath9k_rx_qtype qtype;
+       bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+       int dma_type;
+       u8 rx_status_len = ah->caps.rx_status_len;
+       u64 tsf = 0;
+       u32 tsf_lower = 0;
+       unsigned long flags;
+
+       if (edma)
+               dma_type = DMA_BIDIRECTIONAL;
+       else
+               dma_type = DMA_FROM_DEVICE;
+
+       qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
+       spin_lock_bh(&sc->rx.rxbuflock);
+
+       tsf = ath9k_btcoex_ath9k_hw_gettsf64(ah);
+       tsf_lower = tsf & 0xffffffff;
+
+       do {
+               /* If handling rx interrupt and flush is in progress => exit */
+               if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0))
+                       break;
+
+               memset(&rs, 0, sizeof(rs));
+               if (edma)
+                       bf = ath_edma_get_next_rx_buf(sc, &rs, qtype);
+               else
+                       bf = ath_get_next_rx_buf(sc, &rs);
+
+               if (!bf)
+                       break;
+
+               skb = bf->bf_mpdu;
+               if (!skb)
+                       continue;
+
+               /*
+                * Take frame header from the first fragment and RX status from
+                * the last one.
+                */
+               if (sc->rx.frag)
+                       hdr_skb = sc->rx.frag;
+               else
+                       hdr_skb = skb;
+
+               hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
+               rxs = IEEE80211_SKB_RXCB(hdr_skb);
+               if (ieee80211_is_beacon(hdr->frame_control) &&
+                   !is_zero_ether_addr(common->curbssid) &&
+                   !compare_ether_addr(hdr->addr3, common->curbssid))
+                       rs.is_mybeacon = true;
+               else
+                       rs.is_mybeacon = false;
+
+               sc->rx.num_pkts++;
+               ath_debug_stat_rx(sc, &rs);
+
+               /*
+                * If we're asked to flush receive queue, directly
+                * chain it back at the queue without processing it.
+                */
+               if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags))
+                       goto requeue_drop_frag;
+
+               memset(rxs, 0, sizeof(struct ieee80211_rx_status));
+
+               if (rs.is_mybeacon)
+                       ath_start_rx_poll(sc, 300);
+
+               rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
+               if (rs.rs_tstamp > tsf_lower &&
+                   unlikely(rs.rs_tstamp - tsf_lower > 0x10000000))
+                       rxs->mactime -= 0x100000000ULL;
+
+               if (rs.rs_tstamp < tsf_lower &&
+                   unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
+                       rxs->mactime += 0x100000000ULL;
+
+               retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
+                                                rxs, &decrypt_error);
+               if (retval)
+                       goto requeue_drop_frag;
+
+               /* Ensure we always have an skb to requeue once we are done
+                * processing the current buffer's skb */
+               requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC);
+
+               /* If there is no memory we ignore the current RX'd frame,
+                * tell hardware it can give us a new frame using the old
+                * skb and put it at the tail of the sc->rx.rxbuf list for
+                * processing. */
+               if (!requeue_skb)
+                       goto requeue_drop_frag;
+
+               /* Unmap the frame */
+               dma_unmap_single(sc->dev, bf->bf_buf_addr,
+                                common->rx_bufsize,
+                                dma_type);
+
+               skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len);
+               if (ah->caps.rx_status_len)
+                       skb_pull(skb, ah->caps.rx_status_len);
+
+               if (!rs.rs_more)
+                       ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
+                                                rxs, decrypt_error);
+
+               /* We will now give hardware our shiny new allocated skb */
+               bf->bf_mpdu = requeue_skb;
+               bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
+                                                common->rx_bufsize,
+                                                dma_type);
+               if (unlikely(dma_mapping_error(sc->dev,
+                         bf->bf_buf_addr))) {
+                       dev_kfree_skb_any(requeue_skb);
+                       bf->bf_mpdu = NULL;
+                       bf->bf_buf_addr = 0;
+                       ath_err(common, "dma_mapping_error() on RX\n");
+                       ieee80211_rx(hw, skb);
+                       break;
+               }
+
+               if (rs.rs_more) {
+                       /*
+                        * rs_more indicates chained descriptors which can be
+                        * used to link buffers together for a sort of
+                        * scatter-gather operation.
+                        */
+                       if (sc->rx.frag) {
+                               /* too many fragments - cannot handle frame */
+                               dev_kfree_skb_any(sc->rx.frag);
+                               dev_kfree_skb_any(skb);
+                               skb = NULL;
+                       }
+                       sc->rx.frag = skb;
+                       goto requeue;
+               }
+
+               if (sc->rx.frag) {
+                       int space = skb->len - skb_tailroom(hdr_skb);
+
+                       if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
+                               dev_kfree_skb(skb);
+                               goto requeue_drop_frag;
+                       }
+
+                       sc->rx.frag = NULL;
+
+                       skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len),
+                                                 skb->len);
+                       dev_kfree_skb_any(skb);
+                       skb = hdr_skb;
+               }
+
+
+               if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) {
+
+                       /*
+                        * change the default rx antenna if rx diversity
+                        * chooses the other antenna 3 times in a row.
+                        */
+                       if (sc->rx.defant != rs.rs_antenna) {
+                               if (++sc->rx.rxotherant >= 3)
+                                       ath_setdefantenna(sc, rs.rs_antenna);
+                       } else {
+                               sc->rx.rxotherant = 0;
+                       }
+
+               }
+
+               if (rxs->flag & RX_FLAG_MMIC_STRIPPED)
+                       skb_trim(skb, skb->len - 8);
+
+               spin_lock_irqsave(&sc->sc_pm_lock, flags);
+
+               if ((sc->ps_flags & (PS_WAIT_FOR_BEACON |
+                                    PS_WAIT_FOR_CAB |
+                                    PS_WAIT_FOR_PSPOLL_DATA)) ||
+                   ath9k_check_auto_sleep(sc))
+                       ath_rx_ps(sc, skb, rs.is_mybeacon);
+               spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+
+               if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
+                       ath_ant_comb_scan(sc, &rs);
+
+               ieee80211_rx(hw, skb);
+
+requeue_drop_frag:
+               if (sc->rx.frag) {
+                       dev_kfree_skb_any(sc->rx.frag);
+                       sc->rx.frag = NULL;
+               }
+requeue:
+               if (edma) {
+                       list_add_tail(&bf->list, &sc->rx.rxbuf);
+                       ath_rx_edma_buf_link(sc, qtype);
+               } else {
+                       list_move_tail(&bf->list, &sc->rx.rxbuf);
+                       ath_rx_buf_link(sc, bf);
+                       if (!flush)
+                               ath9k_hw_rxena(ah);
+               }
+       } while (1);
+
+       spin_unlock_bh(&sc->rx.rxbuflock);
+
+       if (!(ah->imask & ATH9K_INT_RXEOL)) {
+               ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+               ath9k_btcoex_ath9k_hw_set_interrupts(ah);
+       }
+
+       return 0;
+}
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/reg.h b/drivers/net/wireless/ath/ath9k_btcoex/reg.h
new file mode 100644 (file)
index 0000000..b6ee737
--- /dev/null
@@ -0,0 +1,2207 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef REG_H
+#define REG_H
+
+#include "../reg.h"
+
+#define AR_CR                0x0008
+#define AR_CR_RXE            (AR_SREV_9300_20_OR_LATER(ah) ? 0x0000000c : 0x00000004)
+#define AR_CR_RXD            0x00000020
+#define AR_CR_SWI            0x00000040
+
+#define AR_RXDP              0x000C
+
+#define AR_CFG               0x0014
+#define AR_CFG_SWTD          0x00000001
+#define AR_CFG_SWTB          0x00000002
+#define AR_CFG_SWRD          0x00000004
+#define AR_CFG_SWRB          0x00000008
+#define AR_CFG_SWRG          0x00000010
+#define AR_CFG_AP_ADHOC_INDICATION 0x00000020
+#define AR_CFG_PHOK          0x00000100
+#define AR_CFG_CLK_GATE_DIS  0x00000400
+#define AR_CFG_EEBS          0x00000200
+#define AR_CFG_PCI_MASTER_REQ_Q_THRESH         0x00060000
+#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S       17
+
+#define AR_RXBP_THRESH       0x0018
+#define AR_RXBP_THRESH_HP    0x0000000f
+#define AR_RXBP_THRESH_HP_S  0
+#define AR_RXBP_THRESH_LP    0x00003f00
+#define AR_RXBP_THRESH_LP_S  8
+
+#define AR_MIRT              0x0020
+#define AR_MIRT_VAL          0x0000ffff
+#define AR_MIRT_VAL_S        16
+
+#define AR_IER               0x0024
+#define AR_IER_ENABLE        0x00000001
+#define AR_IER_DISABLE       0x00000000
+
+#define AR_TIMT              0x0028
+#define AR_TIMT_LAST         0x0000ffff
+#define AR_TIMT_LAST_S       0
+#define AR_TIMT_FIRST        0xffff0000
+#define AR_TIMT_FIRST_S      16
+
+#define AR_RIMT              0x002C
+#define AR_RIMT_LAST         0x0000ffff
+#define AR_RIMT_LAST_S       0
+#define AR_RIMT_FIRST        0xffff0000
+#define AR_RIMT_FIRST_S      16
+
+#define AR_DMASIZE_4B        0x00000000
+#define AR_DMASIZE_8B        0x00000001
+#define AR_DMASIZE_16B       0x00000002
+#define AR_DMASIZE_32B       0x00000003
+#define AR_DMASIZE_64B       0x00000004
+#define AR_DMASIZE_128B      0x00000005
+#define AR_DMASIZE_256B      0x00000006
+#define AR_DMASIZE_512B      0x00000007
+
+#define AR_TXCFG             0x0030
+#define AR_TXCFG_DMASZ_MASK  0x00000007
+#define AR_TXCFG_DMASZ_4B    0
+#define AR_TXCFG_DMASZ_8B    1
+#define AR_TXCFG_DMASZ_16B   2
+#define AR_TXCFG_DMASZ_32B   3
+#define AR_TXCFG_DMASZ_64B   4
+#define AR_TXCFG_DMASZ_128B  5
+#define AR_TXCFG_DMASZ_256B  6
+#define AR_TXCFG_DMASZ_512B  7
+#define AR_FTRIG             0x000003F0
+#define AR_FTRIG_S           4
+#define AR_FTRIG_IMMED       0x00000000
+#define AR_FTRIG_64B         0x00000010
+#define AR_FTRIG_128B        0x00000020
+#define AR_FTRIG_192B        0x00000030
+#define AR_FTRIG_256B        0x00000040
+#define AR_FTRIG_512B        0x00000080
+#define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800
+
+#define AR_RXCFG             0x0034
+#define AR_RXCFG_CHIRP       0x00000008
+#define AR_RXCFG_ZLFDMA      0x00000010
+#define AR_RXCFG_DMASZ_MASK  0x00000007
+#define AR_RXCFG_DMASZ_4B    0
+#define AR_RXCFG_DMASZ_8B    1
+#define AR_RXCFG_DMASZ_16B   2
+#define AR_RXCFG_DMASZ_32B   3
+#define AR_RXCFG_DMASZ_64B   4
+#define AR_RXCFG_DMASZ_128B  5
+#define AR_RXCFG_DMASZ_256B  6
+#define AR_RXCFG_DMASZ_512B  7
+
+#define AR_TOPS              0x0044
+#define AR_TOPS_MASK         0x0000FFFF
+
+#define AR_RXNPTO            0x0048
+#define AR_RXNPTO_MASK       0x000003FF
+
+#define AR_TXNPTO            0x004C
+#define AR_TXNPTO_MASK       0x000003FF
+#define AR_TXNPTO_QCU_MASK   0x000FFC00
+
+#define AR_RPGTO             0x0050
+#define AR_RPGTO_MASK        0x000003FF
+
+#define AR_RPCNT             0x0054
+#define AR_RPCNT_MASK        0x0000001F
+
+#define AR_MACMISC           0x0058
+#define AR_MACMISC_PCI_EXT_FORCE        0x00000010
+#define AR_MACMISC_DMA_OBS              0x000001E0
+#define AR_MACMISC_DMA_OBS_S            5
+#define AR_MACMISC_DMA_OBS_LINE_0       0
+#define AR_MACMISC_DMA_OBS_LINE_1       1
+#define AR_MACMISC_DMA_OBS_LINE_2       2
+#define AR_MACMISC_DMA_OBS_LINE_3       3
+#define AR_MACMISC_DMA_OBS_LINE_4       4
+#define AR_MACMISC_DMA_OBS_LINE_5       5
+#define AR_MACMISC_DMA_OBS_LINE_6       6
+#define AR_MACMISC_DMA_OBS_LINE_7       7
+#define AR_MACMISC_DMA_OBS_LINE_8       8
+#define AR_MACMISC_MISC_OBS             0x00000E00
+#define AR_MACMISC_MISC_OBS_S           9
+#define AR_MACMISC_MISC_OBS_BUS_LSB     0x00007000
+#define AR_MACMISC_MISC_OBS_BUS_LSB_S   12
+#define AR_MACMISC_MISC_OBS_BUS_MSB     0x00038000
+#define AR_MACMISC_MISC_OBS_BUS_MSB_S   15
+#define AR_MACMISC_MISC_OBS_BUS_1       1
+
+#define AR_DATABUF_SIZE                0x0060
+#define AR_DATABUF_SIZE_MASK   0x00000FFF
+
+#define AR_GTXTO    0x0064
+#define AR_GTXTO_TIMEOUT_COUNTER    0x0000FFFF
+#define AR_GTXTO_TIMEOUT_LIMIT      0xFFFF0000
+#define AR_GTXTO_TIMEOUT_LIMIT_S    16
+
+#define AR_GTTM     0x0068
+#define AR_GTTM_USEC          0x00000001
+#define AR_GTTM_IGNORE_IDLE   0x00000002
+#define AR_GTTM_RESET_IDLE    0x00000004
+#define AR_GTTM_CST_USEC      0x00000008
+
+#define AR_CST         0x006C
+#define AR_CST_TIMEOUT_COUNTER    0x0000FFFF
+#define AR_CST_TIMEOUT_LIMIT      0xFFFF0000
+#define AR_CST_TIMEOUT_LIMIT_S    16
+
+#define AR_HP_RXDP 0x0074
+#define AR_LP_RXDP 0x0078
+
+#define AR_ISR               0x0080
+#define AR_ISR_RXOK          0x00000001
+#define AR_ISR_RXDESC        0x00000002
+#define AR_ISR_HP_RXOK      0x00000001
+#define AR_ISR_LP_RXOK      0x00000002
+#define AR_ISR_RXERR         0x00000004
+#define AR_ISR_RXNOPKT       0x00000008
+#define AR_ISR_RXEOL         0x00000010
+#define AR_ISR_RXORN         0x00000020
+#define AR_ISR_TXOK          0x00000040
+#define AR_ISR_TXDESC        0x00000080
+#define AR_ISR_TXERR         0x00000100
+#define AR_ISR_TXNOPKT       0x00000200
+#define AR_ISR_TXEOL         0x00000400
+#define AR_ISR_TXURN         0x00000800
+#define AR_ISR_MIB           0x00001000
+#define AR_ISR_SWI           0x00002000
+#define AR_ISR_RXPHY         0x00004000
+#define AR_ISR_RXKCM         0x00008000
+#define AR_ISR_SWBA          0x00010000
+#define AR_ISR_BRSSI         0x00020000
+#define AR_ISR_BMISS         0x00040000
+#define AR_ISR_BNR           0x00100000
+#define AR_ISR_RXCHIRP       0x00200000
+#define AR_ISR_BCNMISC       0x00800000
+#define AR_ISR_TIM           0x00800000
+#define AR_ISR_QCBROVF       0x02000000
+#define AR_ISR_QCBRURN       0x04000000
+#define AR_ISR_QTRIG         0x08000000
+#define AR_ISR_GENTMR        0x10000000
+
+#define AR_ISR_TXMINTR       0x00080000
+#define AR_ISR_RXMINTR       0x01000000
+#define AR_ISR_TXINTM        0x40000000
+#define AR_ISR_RXINTM        0x80000000
+
+#define AR_ISR_S0               0x0084
+#define AR_ISR_S0_QCU_TXOK      0x000003FF
+#define AR_ISR_S0_QCU_TXOK_S    0
+#define AR_ISR_S0_QCU_TXDESC    0x03FF0000
+#define AR_ISR_S0_QCU_TXDESC_S  16
+
+#define AR_ISR_S1              0x0088
+#define AR_ISR_S1_QCU_TXERR    0x000003FF
+#define AR_ISR_S1_QCU_TXERR_S  0
+#define AR_ISR_S1_QCU_TXEOL    0x03FF0000
+#define AR_ISR_S1_QCU_TXEOL_S  16
+
+#define AR_ISR_S2              0x008c
+#define AR_ISR_S2_QCU_TXURN    0x000003FF
+#define AR_ISR_S2_BB_WATCHDOG  0x00010000
+#define AR_ISR_S2_CST          0x00400000
+#define AR_ISR_S2_GTT          0x00800000
+#define AR_ISR_S2_TIM          0x01000000
+#define AR_ISR_S2_CABEND       0x02000000
+#define AR_ISR_S2_DTIMSYNC     0x04000000
+#define AR_ISR_S2_BCNTO        0x08000000
+#define AR_ISR_S2_CABTO        0x10000000
+#define AR_ISR_S2_DTIM         0x20000000
+#define AR_ISR_S2_TSFOOR       0x40000000
+#define AR_ISR_S2_TBTT_TIME    0x80000000
+
+#define AR_ISR_S3             0x0090
+#define AR_ISR_S3_QCU_QCBROVF    0x000003FF
+#define AR_ISR_S3_QCU_QCBRURN    0x03FF0000
+
+#define AR_ISR_S4              0x0094
+#define AR_ISR_S4_QCU_QTRIG    0x000003FF
+#define AR_ISR_S4_RESV0        0xFFFFFC00
+
+#define AR_ISR_S5                   0x0098
+#define AR_ISR_S5_TIMER_TRIG        0x000000FF
+#define AR_ISR_S5_TIMER_THRESH      0x0007FE00
+#define AR_ISR_S5_TIM_TIMER         0x00000010
+#define AR_ISR_S5_DTIM_TIMER        0x00000020
+#define AR_IMR_S5                   0x00b8
+#define AR_IMR_S5_TIM_TIMER         0x00000010
+#define AR_IMR_S5_DTIM_TIMER        0x00000020
+#define AR_ISR_S5_GENTIMER_TRIG     0x0000FF80
+#define AR_ISR_S5_GENTIMER_TRIG_S   0
+#define AR_ISR_S5_GENTIMER_THRESH   0xFF800000
+#define AR_ISR_S5_GENTIMER_THRESH_S 16
+#define AR_IMR_S5_GENTIMER_TRIG     0x0000FF80
+#define AR_IMR_S5_GENTIMER_TRIG_S   0
+#define AR_IMR_S5_GENTIMER_THRESH   0xFF800000
+#define AR_IMR_S5_GENTIMER_THRESH_S 16
+
+#define AR_IMR               0x00a0
+#define AR_IMR_RXOK          0x00000001
+#define AR_IMR_RXDESC        0x00000002
+#define AR_IMR_RXOK_HP      0x00000001
+#define AR_IMR_RXOK_LP      0x00000002
+#define AR_IMR_RXERR         0x00000004
+#define AR_IMR_RXNOPKT       0x00000008
+#define AR_IMR_RXEOL         0x00000010
+#define AR_IMR_RXORN         0x00000020
+#define AR_IMR_TXOK          0x00000040
+#define AR_IMR_TXDESC        0x00000080
+#define AR_IMR_TXERR         0x00000100
+#define AR_IMR_TXNOPKT       0x00000200
+#define AR_IMR_TXEOL         0x00000400
+#define AR_IMR_TXURN         0x00000800
+#define AR_IMR_MIB           0x00001000
+#define AR_IMR_SWI           0x00002000
+#define AR_IMR_RXPHY         0x00004000
+#define AR_IMR_RXKCM         0x00008000
+#define AR_IMR_SWBA          0x00010000
+#define AR_IMR_BRSSI         0x00020000
+#define AR_IMR_BMISS         0x00040000
+#define AR_IMR_BNR           0x00100000
+#define AR_IMR_RXCHIRP       0x00200000
+#define AR_IMR_BCNMISC       0x00800000
+#define AR_IMR_TIM           0x00800000
+#define AR_IMR_QCBROVF       0x02000000
+#define AR_IMR_QCBRURN       0x04000000
+#define AR_IMR_QTRIG         0x08000000
+#define AR_IMR_GENTMR        0x10000000
+
+#define AR_IMR_TXMINTR       0x00080000
+#define AR_IMR_RXMINTR       0x01000000
+#define AR_IMR_TXINTM        0x40000000
+#define AR_IMR_RXINTM        0x80000000
+
+#define AR_IMR_S0               0x00a4
+#define AR_IMR_S0_QCU_TXOK      0x000003FF
+#define AR_IMR_S0_QCU_TXOK_S    0
+#define AR_IMR_S0_QCU_TXDESC    0x03FF0000
+#define AR_IMR_S0_QCU_TXDESC_S  16
+
+#define AR_IMR_S1              0x00a8
+#define AR_IMR_S1_QCU_TXERR    0x000003FF
+#define AR_IMR_S1_QCU_TXERR_S  0
+#define AR_IMR_S1_QCU_TXEOL    0x03FF0000
+#define AR_IMR_S1_QCU_TXEOL_S  16
+
+#define AR_IMR_S2              0x00ac
+#define AR_IMR_S2_QCU_TXURN    0x000003FF
+#define AR_IMR_S2_QCU_TXURN_S  0
+#define AR_IMR_S2_CST          0x00400000
+#define AR_IMR_S2_GTT          0x00800000
+#define AR_IMR_S2_TIM          0x01000000
+#define AR_IMR_S2_CABEND       0x02000000
+#define AR_IMR_S2_DTIMSYNC     0x04000000
+#define AR_IMR_S2_BCNTO        0x08000000
+#define AR_IMR_S2_CABTO        0x10000000
+#define AR_IMR_S2_DTIM         0x20000000
+#define AR_IMR_S2_TSFOOR       0x40000000
+
+#define AR_IMR_S3                0x00b0
+#define AR_IMR_S3_QCU_QCBROVF    0x000003FF
+#define AR_IMR_S3_QCU_QCBRURN    0x03FF0000
+#define AR_IMR_S3_QCU_QCBRURN_S  16
+
+#define AR_IMR_S4              0x00b4
+#define AR_IMR_S4_QCU_QTRIG    0x000003FF
+#define AR_IMR_S4_RESV0        0xFFFFFC00
+
+#define AR_IMR_S5              0x00b8
+#define AR_IMR_S5_TIMER_TRIG        0x000000FF
+#define AR_IMR_S5_TIMER_THRESH      0x0000FF00
+
+
+#define AR_ISR_RAC            0x00c0
+#define AR_ISR_S0_S           0x00c4
+#define AR_ISR_S0_QCU_TXOK      0x000003FF
+#define AR_ISR_S0_QCU_TXOK_S    0
+#define AR_ISR_S0_QCU_TXDESC    0x03FF0000
+#define AR_ISR_S0_QCU_TXDESC_S  16
+
+#define AR_ISR_S1_S           0x00c8
+#define AR_ISR_S1_QCU_TXERR    0x000003FF
+#define AR_ISR_S1_QCU_TXERR_S  0
+#define AR_ISR_S1_QCU_TXEOL    0x03FF0000
+#define AR_ISR_S1_QCU_TXEOL_S  16
+
+#define AR_ISR_S2_S           (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d0 : 0x00cc)
+#define AR_ISR_S3_S           (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d4 : 0x00d0)
+#define AR_ISR_S4_S           (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d8 : 0x00d4)
+#define AR_ISR_S5_S           (AR_SREV_9300_20_OR_LATER(ah) ? 0x00dc : 0x00d8)
+#define AR_DMADBG_0           0x00e0
+#define AR_DMADBG_1           0x00e4
+#define AR_DMADBG_2           0x00e8
+#define AR_DMADBG_3           0x00ec
+#define AR_DMADBG_4           0x00f0
+#define AR_DMADBG_5           0x00f4
+#define AR_DMADBG_6           0x00f8
+#define AR_DMADBG_7           0x00fc
+
+#define AR_NUM_QCU      10
+#define AR_QCU_0        0x0001
+#define AR_QCU_1        0x0002
+#define AR_QCU_2        0x0004
+#define AR_QCU_3        0x0008
+#define AR_QCU_4        0x0010
+#define AR_QCU_5        0x0020
+#define AR_QCU_6        0x0040
+#define AR_QCU_7        0x0080
+#define AR_QCU_8        0x0100
+#define AR_QCU_9        0x0200
+
+#define AR_Q0_TXDP           0x0800
+#define AR_Q1_TXDP           0x0804
+#define AR_Q2_TXDP           0x0808
+#define AR_Q3_TXDP           0x080c
+#define AR_Q4_TXDP           0x0810
+#define AR_Q5_TXDP           0x0814
+#define AR_Q6_TXDP           0x0818
+#define AR_Q7_TXDP           0x081c
+#define AR_Q8_TXDP           0x0820
+#define AR_Q9_TXDP           0x0824
+#define AR_QTXDP(_i)    (AR_Q0_TXDP + ((_i)<<2))
+
+#define AR_Q_STATUS_RING_START 0x830
+#define AR_Q_STATUS_RING_END   0x834
+
+#define AR_Q_TXE             0x0840
+#define AR_Q_TXE_M           0x000003FF
+
+#define AR_Q_TXD             0x0880
+#define AR_Q_TXD_M           0x000003FF
+
+#define AR_Q0_CBRCFG         0x08c0
+#define AR_Q1_CBRCFG         0x08c4
+#define AR_Q2_CBRCFG         0x08c8
+#define AR_Q3_CBRCFG         0x08cc
+#define AR_Q4_CBRCFG         0x08d0
+#define AR_Q5_CBRCFG         0x08d4
+#define AR_Q6_CBRCFG         0x08d8
+#define AR_Q7_CBRCFG         0x08dc
+#define AR_Q8_CBRCFG         0x08e0
+#define AR_Q9_CBRCFG         0x08e4
+#define AR_QCBRCFG(_i)      (AR_Q0_CBRCFG + ((_i)<<2))
+#define AR_Q_CBRCFG_INTERVAL     0x00FFFFFF
+#define AR_Q_CBRCFG_INTERVAL_S   0
+#define AR_Q_CBRCFG_OVF_THRESH   0xFF000000
+#define AR_Q_CBRCFG_OVF_THRESH_S 24
+
+#define AR_Q0_RDYTIMECFG         0x0900
+#define AR_Q1_RDYTIMECFG         0x0904
+#define AR_Q2_RDYTIMECFG         0x0908
+#define AR_Q3_RDYTIMECFG         0x090c
+#define AR_Q4_RDYTIMECFG         0x0910
+#define AR_Q5_RDYTIMECFG         0x0914
+#define AR_Q6_RDYTIMECFG         0x0918
+#define AR_Q7_RDYTIMECFG         0x091c
+#define AR_Q8_RDYTIMECFG         0x0920
+#define AR_Q9_RDYTIMECFG         0x0924
+#define AR_QRDYTIMECFG(_i)       (AR_Q0_RDYTIMECFG + ((_i)<<2))
+#define AR_Q_RDYTIMECFG_DURATION   0x00FFFFFF
+#define AR_Q_RDYTIMECFG_DURATION_S 0
+#define AR_Q_RDYTIMECFG_EN         0x01000000
+
+#define AR_Q_ONESHOTARM_SC       0x0940
+#define AR_Q_ONESHOTARM_SC_M     0x000003FF
+#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00
+
+#define AR_Q_ONESHOTARM_CC       0x0980
+#define AR_Q_ONESHOTARM_CC_M     0x000003FF
+#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00
+
+#define AR_Q0_MISC         0x09c0
+#define AR_Q1_MISC         0x09c4
+#define AR_Q2_MISC         0x09c8
+#define AR_Q3_MISC         0x09cc
+#define AR_Q4_MISC         0x09d0
+#define AR_Q5_MISC         0x09d4
+#define AR_Q6_MISC         0x09d8
+#define AR_Q7_MISC         0x09dc
+#define AR_Q8_MISC         0x09e0
+#define AR_Q9_MISC         0x09e4
+#define AR_QMISC(_i)       (AR_Q0_MISC + ((_i)<<2))
+#define AR_Q_MISC_FSP                     0x0000000F
+#define AR_Q_MISC_FSP_ASAP                0
+#define AR_Q_MISC_FSP_CBR                 1
+#define AR_Q_MISC_FSP_DBA_GATED           2
+#define AR_Q_MISC_FSP_TIM_GATED           3
+#define AR_Q_MISC_FSP_BEACON_SENT_GATED   4
+#define AR_Q_MISC_FSP_BEACON_RCVD_GATED   5
+#define AR_Q_MISC_ONE_SHOT_EN             0x00000010
+#define AR_Q_MISC_CBR_INCR_DIS1           0x00000020
+#define AR_Q_MISC_CBR_INCR_DIS0           0x00000040
+#define AR_Q_MISC_BEACON_USE              0x00000080
+#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN   0x00000100
+#define AR_Q_MISC_RDYTIME_EXP_POLICY      0x00000200
+#define AR_Q_MISC_RESET_CBR_EXP_CTR       0x00000400
+#define AR_Q_MISC_DCU_EARLY_TERM_REQ      0x00000800
+#define AR_Q_MISC_RESV0                   0xFFFFF000
+
+#define AR_Q0_STS         0x0a00
+#define AR_Q1_STS         0x0a04
+#define AR_Q2_STS         0x0a08
+#define AR_Q3_STS         0x0a0c
+#define AR_Q4_STS         0x0a10
+#define AR_Q5_STS         0x0a14
+#define AR_Q6_STS         0x0a18
+#define AR_Q7_STS         0x0a1c
+#define AR_Q8_STS         0x0a20
+#define AR_Q9_STS         0x0a24
+#define AR_QSTS(_i)       (AR_Q0_STS + ((_i)<<2))
+#define AR_Q_STS_PEND_FR_CNT          0x00000003
+#define AR_Q_STS_RESV0                0x000000FC
+#define AR_Q_STS_CBR_EXP_CNT          0x0000FF00
+#define AR_Q_STS_RESV1                0xFFFF0000
+
+#define AR_Q_RDYTIMESHDN    0x0a40
+#define AR_Q_RDYTIMESHDN_M  0x000003FF
+
+/* MAC Descriptor CRC check */
+#define AR_Q_DESC_CRCCHK    0xa44
+/* Enable CRC check on the descriptor fetched from host */
+#define AR_Q_DESC_CRCCHK_EN 1
+
+#define AR_NUM_DCU      10
+#define AR_DCU_0        0x0001
+#define AR_DCU_1        0x0002
+#define AR_DCU_2        0x0004
+#define AR_DCU_3        0x0008
+#define AR_DCU_4        0x0010
+#define AR_DCU_5        0x0020
+#define AR_DCU_6        0x0040
+#define AR_DCU_7        0x0080
+#define AR_DCU_8        0x0100
+#define AR_DCU_9        0x0200
+
+#define AR_D0_QCUMASK     0x1000
+#define AR_D1_QCUMASK     0x1004
+#define AR_D2_QCUMASK     0x1008
+#define AR_D3_QCUMASK     0x100c
+#define AR_D4_QCUMASK     0x1010
+#define AR_D5_QCUMASK     0x1014
+#define AR_D6_QCUMASK     0x1018
+#define AR_D7_QCUMASK     0x101c
+#define AR_D8_QCUMASK     0x1020
+#define AR_D9_QCUMASK     0x1024
+#define AR_DQCUMASK(_i)   (AR_D0_QCUMASK + ((_i)<<2))
+#define AR_D_QCUMASK         0x000003FF
+#define AR_D_QCUMASK_RESV0   0xFFFFFC00
+
+#define AR_D_TXBLK_CMD  0x1038
+#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i))
+
+#define AR_D0_LCL_IFS     0x1040
+#define AR_D1_LCL_IFS     0x1044
+#define AR_D2_LCL_IFS     0x1048
+#define AR_D3_LCL_IFS     0x104c
+#define AR_D4_LCL_IFS     0x1050
+#define AR_D5_LCL_IFS     0x1054
+#define AR_D6_LCL_IFS     0x1058
+#define AR_D7_LCL_IFS     0x105c
+#define AR_D8_LCL_IFS     0x1060
+#define AR_D9_LCL_IFS     0x1064
+#define AR_DLCL_IFS(_i)   (AR_D0_LCL_IFS + ((_i)<<2))
+#define AR_D_LCL_IFS_CWMIN       0x000003FF
+#define AR_D_LCL_IFS_CWMIN_S     0
+#define AR_D_LCL_IFS_CWMAX       0x000FFC00
+#define AR_D_LCL_IFS_CWMAX_S     10
+#define AR_D_LCL_IFS_AIFS        0x0FF00000
+#define AR_D_LCL_IFS_AIFS_S      20
+
+#define AR_D_LCL_IFS_RESV0    0xF0000000
+
+#define AR_D0_RETRY_LIMIT     0x1080
+#define AR_D1_RETRY_LIMIT     0x1084
+#define AR_D2_RETRY_LIMIT     0x1088
+#define AR_D3_RETRY_LIMIT     0x108c
+#define AR_D4_RETRY_LIMIT     0x1090
+#define AR_D5_RETRY_LIMIT     0x1094
+#define AR_D6_RETRY_LIMIT     0x1098
+#define AR_D7_RETRY_LIMIT     0x109c
+#define AR_D8_RETRY_LIMIT     0x10a0
+#define AR_D9_RETRY_LIMIT     0x10a4
+#define AR_DRETRY_LIMIT(_i)   (AR_D0_RETRY_LIMIT + ((_i)<<2))
+#define AR_D_RETRY_LIMIT_FR_SH       0x0000000F
+#define AR_D_RETRY_LIMIT_FR_SH_S     0
+#define AR_D_RETRY_LIMIT_STA_SH      0x00003F00
+#define AR_D_RETRY_LIMIT_STA_SH_S    8
+#define AR_D_RETRY_LIMIT_STA_LG      0x000FC000
+#define AR_D_RETRY_LIMIT_STA_LG_S    14
+#define AR_D_RETRY_LIMIT_RESV0       0xFFF00000
+
+#define AR_D0_CHNTIME     0x10c0
+#define AR_D1_CHNTIME     0x10c4
+#define AR_D2_CHNTIME     0x10c8
+#define AR_D3_CHNTIME     0x10cc
+#define AR_D4_CHNTIME     0x10d0
+#define AR_D5_CHNTIME     0x10d4
+#define AR_D6_CHNTIME     0x10d8
+#define AR_D7_CHNTIME     0x10dc
+#define AR_D8_CHNTIME     0x10e0
+#define AR_D9_CHNTIME     0x10e4
+#define AR_DCHNTIME(_i)   (AR_D0_CHNTIME + ((_i)<<2))
+#define AR_D_CHNTIME_DUR         0x000FFFFF
+#define AR_D_CHNTIME_DUR_S       0
+#define AR_D_CHNTIME_EN          0x00100000
+#define AR_D_CHNTIME_RESV0       0xFFE00000
+
+#define AR_D0_MISC        0x1100
+#define AR_D1_MISC        0x1104
+#define AR_D2_MISC        0x1108
+#define AR_D3_MISC        0x110c
+#define AR_D4_MISC        0x1110
+#define AR_D5_MISC        0x1114
+#define AR_D6_MISC        0x1118
+#define AR_D7_MISC        0x111c
+#define AR_D8_MISC        0x1120
+#define AR_D9_MISC        0x1124
+#define AR_DMISC(_i)      (AR_D0_MISC + ((_i)<<2))
+#define AR_D_MISC_BKOFF_THRESH        0x0000003F
+#define AR_D_MISC_RETRY_CNT_RESET_EN  0x00000040
+#define AR_D_MISC_CW_RESET_EN         0x00000080
+#define AR_D_MISC_FRAG_WAIT_EN        0x00000100
+#define AR_D_MISC_FRAG_BKOFF_EN       0x00000200
+#define AR_D_MISC_CW_BKOFF_EN         0x00001000
+#define AR_D_MISC_VIR_COL_HANDLING    0x0000C000
+#define AR_D_MISC_VIR_COL_HANDLING_S  14
+#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0
+#define AR_D_MISC_VIR_COL_HANDLING_IGNORE  1
+#define AR_D_MISC_BEACON_USE          0x00010000
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL   0x00060000
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE     0
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL   2
+#define AR_D_MISC_ARB_LOCKOUT_IGNORE  0x00080000
+#define AR_D_MISC_SEQ_NUM_INCR_DIS    0x00100000
+#define AR_D_MISC_POST_FR_BKOFF_DIS   0x00200000
+#define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000
+#define AR_D_MISC_BLOWN_IFS_RETRY_EN  0x00800000
+#define AR_D_MISC_RESV0               0xFF000000
+
+#define AR_D_SEQNUM      0x1140
+
+#define AR_D_GBL_IFS_SIFS         0x1030
+#define AR_D_GBL_IFS_SIFS_M       0x0000FFFF
+#define AR_D_GBL_IFS_SIFS_RESV0   0xFFFFFFFF
+
+#define AR_D_TXBLK_BASE            0x1038
+#define AR_D_TXBLK_WRITE_BITMASK    0x0000FFFF
+#define AR_D_TXBLK_WRITE_BITMASK_S  0
+#define AR_D_TXBLK_WRITE_SLICE      0x000F0000
+#define AR_D_TXBLK_WRITE_SLICE_S    16
+#define AR_D_TXBLK_WRITE_DCU        0x00F00000
+#define AR_D_TXBLK_WRITE_DCU_S      20
+#define AR_D_TXBLK_WRITE_COMMAND    0x0F000000
+#define AR_D_TXBLK_WRITE_COMMAND_S      24
+
+#define AR_D_GBL_IFS_SLOT         0x1070
+#define AR_D_GBL_IFS_SLOT_M       0x0000FFFF
+#define AR_D_GBL_IFS_SLOT_RESV0   0xFFFF0000
+
+#define AR_D_GBL_IFS_EIFS         0x10b0
+#define AR_D_GBL_IFS_EIFS_M       0x0000FFFF
+#define AR_D_GBL_IFS_EIFS_RESV0   0xFFFF0000
+#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO 363
+
+#define AR_D_GBL_IFS_MISC        0x10f0
+#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL        0x00000007
+#define AR_D_GBL_IFS_MISC_TURBO_MODE            0x00000008
+#define AR_D_GBL_IFS_MISC_USEC_DURATION         0x000FFC00
+#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY       0x00300000
+#define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000
+#define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN    0x06000000
+#define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000
+#define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF        0x10000000
+
+#define AR_D_FPCTL                  0x1230
+#define AR_D_FPCTL_DCU              0x0000000F
+#define AR_D_FPCTL_DCU_S            0
+#define AR_D_FPCTL_PREFETCH_EN      0x00000010
+#define AR_D_FPCTL_BURST_PREFETCH   0x00007FE0
+#define AR_D_FPCTL_BURST_PREFETCH_S 5
+
+#define AR_D_TXPSE                 0x1270
+#define AR_D_TXPSE_CTRL            0x000003FF
+#define AR_D_TXPSE_RESV0           0x0000FC00
+#define AR_D_TXPSE_STATUS          0x00010000
+#define AR_D_TXPSE_RESV1           0xFFFE0000
+
+#define AR_D_TXSLOTMASK            0x12f0
+#define AR_D_TXSLOTMASK_NUM        0x0000000F
+
+#define AR_CFG_LED                     0x1f04
+#define AR_CFG_SCLK_RATE_IND           0x00000003
+#define AR_CFG_SCLK_RATE_IND_S         0
+#define AR_CFG_SCLK_32MHZ              0x00000000
+#define AR_CFG_SCLK_4MHZ               0x00000001
+#define AR_CFG_SCLK_1MHZ               0x00000002
+#define AR_CFG_SCLK_32KHZ              0x00000003
+#define AR_CFG_LED_BLINK_SLOW          0x00000008
+#define AR_CFG_LED_BLINK_THRESH_SEL    0x00000070
+#define AR_CFG_LED_MODE_SEL            0x00000380
+#define AR_CFG_LED_MODE_SEL_S          7
+#define AR_CFG_LED_POWER               0x00000280
+#define AR_CFG_LED_POWER_S             7
+#define AR_CFG_LED_NETWORK             0x00000300
+#define AR_CFG_LED_NETWORK_S           7
+#define AR_CFG_LED_MODE_PROP           0x0
+#define AR_CFG_LED_MODE_RPROP          0x1
+#define AR_CFG_LED_MODE_SPLIT          0x2
+#define AR_CFG_LED_MODE_RAND           0x3
+#define AR_CFG_LED_MODE_POWER_OFF      0x4
+#define AR_CFG_LED_MODE_POWER_ON       0x5
+#define AR_CFG_LED_MODE_NETWORK_OFF    0x4
+#define AR_CFG_LED_MODE_NETWORK_ON     0x6
+#define AR_CFG_LED_ASSOC_CTL           0x00000c00
+#define AR_CFG_LED_ASSOC_CTL_S         10
+#define AR_CFG_LED_ASSOC_NONE          0x0
+#define AR_CFG_LED_ASSOC_ACTIVE        0x1
+#define AR_CFG_LED_ASSOC_PENDING       0x2
+
+#define AR_CFG_LED_BLINK_SLOW          0x00000008
+#define AR_CFG_LED_BLINK_SLOW_S        3
+
+#define AR_CFG_LED_BLINK_THRESH_SEL    0x00000070
+#define AR_CFG_LED_BLINK_THRESH_SEL_S  4
+
+#define AR_MAC_SLEEP                0x1f00
+#define AR_MAC_SLEEP_MAC_AWAKE      0x00000000
+#define AR_MAC_SLEEP_MAC_ASLEEP     0x00000001
+
+#define AR_RC                0x4000
+#define AR_RC_AHB            0x00000001
+#define AR_RC_APB            0x00000002
+#define AR_RC_HOSTIF         0x00000100
+
+#define AR_WA                  (AR_SREV_9340(ah) ? 0x40c4 : 0x4004)
+#define AR_WA_BIT6                     (1 << 6)
+#define AR_WA_BIT7                     (1 << 7)
+#define AR_WA_BIT23                    (1 << 23)
+#define AR_WA_D3_L1_DISABLE            (1 << 14)
+#define AR_WA_D3_TO_L1_DISABLE_REAL     (1 << 16)
+#define AR_WA_ASPM_TIMER_BASED_DISABLE  (1 << 17)
+#define AR_WA_RESET_EN                  (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
+#define AR_WA_ANALOG_SHIFT              (1 << 20)
+#define AR_WA_POR_SHORT                 (1 << 21) /* PCI-E Phy reset control */
+#define AR_WA_BIT22                    (1 << 22)
+#define AR9285_WA_DEFAULT              0x004a050b
+#define AR9280_WA_DEFAULT              0x0040073b
+#define AR_WA_DEFAULT                  0x0000073f
+
+
+#define AR_PM_STATE                 0x4008
+#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000
+
+#define AR_HOST_TIMEOUT             (AR_SREV_9340(ah) ? 0x4008 : 0x4018)
+#define AR_HOST_TIMEOUT_APB_CNTR    0x0000FFFF
+#define AR_HOST_TIMEOUT_APB_CNTR_S  0
+#define AR_HOST_TIMEOUT_LCL_CNTR    0xFFFF0000
+#define AR_HOST_TIMEOUT_LCL_CNTR_S  16
+
+#define AR_EEPROM                0x401c
+#define AR_EEPROM_ABSENT         0x00000100
+#define AR_EEPROM_CORRUPT        0x00000200
+#define AR_EEPROM_PROT_MASK      0x03FFFC00
+#define AR_EEPROM_PROT_MASK_S    10
+
+#define EEPROM_PROTECT_RP_0_31        0x0001
+#define EEPROM_PROTECT_WP_0_31        0x0002
+#define EEPROM_PROTECT_RP_32_63       0x0004
+#define EEPROM_PROTECT_WP_32_63       0x0008
+#define EEPROM_PROTECT_RP_64_127      0x0010
+#define EEPROM_PROTECT_WP_64_127      0x0020
+#define EEPROM_PROTECT_RP_128_191     0x0040
+#define EEPROM_PROTECT_WP_128_191     0x0080
+#define EEPROM_PROTECT_RP_192_255     0x0100
+#define EEPROM_PROTECT_WP_192_255     0x0200
+#define EEPROM_PROTECT_RP_256_511     0x0400
+#define EEPROM_PROTECT_WP_256_511     0x0800
+#define EEPROM_PROTECT_RP_512_1023    0x1000
+#define EEPROM_PROTECT_WP_512_1023    0x2000
+#define EEPROM_PROTECT_RP_1024_2047   0x4000
+#define EEPROM_PROTECT_WP_1024_2047   0x8000
+
+#define AR_SREV \
+       ((AR_SREV_9100(ah)) ? 0x0600 : (AR_SREV_9340(ah) \
+                                       ? 0x400c : 0x4020))
+
+#define AR_SREV_ID \
+       ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF)
+#define AR_SREV_VERSION                       0x000000F0
+#define AR_SREV_VERSION_S                     4
+#define AR_SREV_REVISION                      0x00000007
+
+#define AR_SREV_ID2                           0xFFFFFFFF
+#define AR_SREV_VERSION2                     0xFFFC0000
+#define AR_SREV_VERSION2_S                    18
+#define AR_SREV_TYPE2                        0x0003F000
+#define AR_SREV_TYPE2_S                       12
+#define AR_SREV_TYPE2_CHAIN                  0x00001000
+#define AR_SREV_TYPE2_HOST_MODE                      0x00002000
+#define AR_SREV_REVISION2                    0x00000F00
+#define AR_SREV_REVISION2_S                  8
+
+#define AR_SREV_VERSION_5416_PCI       0xD
+#define AR_SREV_VERSION_5416_PCIE      0xC
+#define AR_SREV_REVISION_5416_10       0
+#define AR_SREV_REVISION_5416_20       1
+#define AR_SREV_REVISION_5416_22       2
+#define AR_SREV_VERSION_9100           0x14
+#define AR_SREV_VERSION_9160           0x40
+#define AR_SREV_REVISION_9160_10       0
+#define AR_SREV_REVISION_9160_11       1
+#define AR_SREV_VERSION_9280           0x80
+#define AR_SREV_REVISION_9280_10       0
+#define AR_SREV_REVISION_9280_20       1
+#define AR_SREV_REVISION_9280_21       2
+#define AR_SREV_VERSION_9285           0xC0
+#define AR_SREV_REVISION_9285_10       0
+#define AR_SREV_REVISION_9285_11       1
+#define AR_SREV_REVISION_9285_12       2
+#define AR_SREV_VERSION_9287           0x180
+#define AR_SREV_REVISION_9287_10       0
+#define AR_SREV_REVISION_9287_11       1
+#define AR_SREV_REVISION_9287_12       2
+#define AR_SREV_REVISION_9287_13       3
+#define AR_SREV_VERSION_9271           0x140
+#define AR_SREV_REVISION_9271_10       0
+#define AR_SREV_REVISION_9271_11       1
+#define AR_SREV_VERSION_9300           0x1c0
+#define AR_SREV_REVISION_9300_20       2 /* 2.0 and 2.1 */
+#define AR_SREV_VERSION_9330           0x200
+#define AR_SREV_REVISION_9330_10       0
+#define AR_SREV_REVISION_9330_11       1
+#define AR_SREV_REVISION_9330_12       2
+#define AR_SREV_VERSION_9485           0x240
+#define AR_SREV_REVISION_9485_10       0
+#define AR_SREV_REVISION_9485_11        1
+#define AR_SREV_VERSION_9340           0x300
+#define AR_SREV_VERSION_9580           0x1C0
+#define AR_SREV_REVISION_9580_10       4 /* AR9580 1.0 */
+#define AR_SREV_VERSION_9462           0x280
+#define AR_SREV_REVISION_9462_20       2
+
+#define AR_SREV_5416(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
+        ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
+#define AR_SREV_5416_22_OR_LATER(_ah) \
+       (((AR_SREV_5416(_ah)) && \
+        ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
+        ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
+
+#define AR_SREV_9100(ah) \
+       ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100)
+#define AR_SREV_9100_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
+
+#define AR_SREV_9160(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160))
+#define AR_SREV_9160_10_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160))
+#define AR_SREV_9160_11(_ah) \
+       (AR_SREV_9160(_ah) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11))
+#define AR_SREV_9280(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
+#define AR_SREV_9280_20_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280))
+#define AR_SREV_9280_20(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
+
+#define AR_SREV_9285(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285))
+#define AR_SREV_9285_12_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
+
+#define AR_SREV_9287(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287))
+#define AR_SREV_9287_11_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287))
+#define AR_SREV_9287_11(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11))
+#define AR_SREV_9287_12(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12))
+#define AR_SREV_9287_12_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
+        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+         ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12)))
+#define AR_SREV_9287_13_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
+        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+         ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_13)))
+
+#define AR_SREV_9271(_ah) \
+    (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271)
+#define AR_SREV_9271_10(_ah) \
+    (AR_SREV_9271(_ah) && \
+     ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_10))
+#define AR_SREV_9271_11(_ah) \
+    (AR_SREV_9271(_ah) && \
+     ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11))
+
+#define AR_SREV_9300(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
+#define AR_SREV_9300_20_OR_LATER(_ah) \
+       ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300)
+
+#define AR_SREV_9330(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330))
+#define AR_SREV_9330_10(_ah) \
+       (AR_SREV_9330((_ah)) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_10))
+#define AR_SREV_9330_11(_ah) \
+       (AR_SREV_9330((_ah)) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_11))
+#define AR_SREV_9330_12(_ah) \
+       (AR_SREV_9330((_ah)) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12))
+
+#define AR_SREV_9485(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
+#define AR_SREV_9485_10(_ah) \
+       (AR_SREV_9485(_ah) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_10))
+#define AR_SREV_9485_11(_ah) \
+       (AR_SREV_9485(_ah) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11))
+#define AR_SREV_9485_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485))
+
+#define AR_SREV_9340(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340))
+
+#define AR_SREV_9285E_20(_ah) \
+    (AR_SREV_9285_12_OR_LATER(_ah) && \
+     ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
+
+#define AR_SREV_9462(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
+
+#define AR_SREV_9462_20(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
+       ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
+
+#define AR_SREV_9462_20_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
+       ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
+
+#define AR_SREV_9580(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
+       ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10))
+
+#define AR_SREV_9580_10(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
+       ((_ah)->hw_version.macRev == AR_SREV_REVISION_9580_10))
+
+/* NOTE: When adding chips newer than Peacock, add chip check here */
+#define AR_SREV_9580_10_OR_LATER(_ah) \
+       (AR_SREV_9580(_ah))
+
+enum ath_usb_dev {
+       AR9280_USB = 1, /* AR7010 + AR9280, UB94 */
+       AR9287_USB = 2, /* AR7010 + AR9287, UB95 */
+       STORAGE_DEVICE = 3,
+};
+
+#define AR_DEVID_7010(_ah) \
+       (((_ah)->hw_version.usbdev == AR9280_USB) || \
+        ((_ah)->hw_version.usbdev == AR9287_USB))
+
+#define AR_RADIO_SREV_MAJOR                   0xf0
+#define AR_RAD5133_SREV_MAJOR                 0xc0
+#define AR_RAD2133_SREV_MAJOR                 0xd0
+#define AR_RAD5122_SREV_MAJOR                 0xe0
+#define AR_RAD2122_SREV_MAJOR                 0xf0
+
+#define AR_AHB_MODE                           0x4024
+#define AR_AHB_EXACT_WR_EN                    0x00000000
+#define AR_AHB_BUF_WR_EN                      0x00000001
+#define AR_AHB_EXACT_RD_EN                    0x00000000
+#define AR_AHB_CACHELINE_RD_EN                0x00000002
+#define AR_AHB_PREFETCH_RD_EN                 0x00000004
+#define AR_AHB_PAGE_SIZE_1K                   0x00000000
+#define AR_AHB_PAGE_SIZE_2K                   0x00000008
+#define AR_AHB_PAGE_SIZE_4K                   0x00000010
+#define AR_AHB_CUSTOM_BURST_EN                0x000000C0
+#define AR_AHB_CUSTOM_BURST_EN_S              6
+#define AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL    3
+
+#define AR_INTR_RTC_IRQ                       0x00000001
+#define AR_INTR_MAC_IRQ                       0x00000002
+#define AR_INTR_EEP_PROT_ACCESS               0x00000004
+#define AR_INTR_MAC_AWAKE                     0x00020000
+#define AR_INTR_MAC_ASLEEP                    0x00040000
+#define AR_INTR_SPURIOUS                      0xFFFFFFFF
+
+
+#define AR_INTR_SYNC_CAUSE                    (AR_SREV_9340(ah) ? 0x4010 : 0x4028)
+#define AR_INTR_SYNC_CAUSE_CLR                (AR_SREV_9340(ah) ? 0x4010 : 0x4028)
+
+
+#define AR_INTR_SYNC_ENABLE                   (AR_SREV_9340(ah) ? 0x4014 : 0x402c)
+#define AR_INTR_SYNC_ENABLE_GPIO              0xFFFC0000
+#define AR_INTR_SYNC_ENABLE_GPIO_S            18
+
+enum {
+       AR_INTR_SYNC_RTC_IRQ = 0x00000001,
+       AR_INTR_SYNC_MAC_IRQ = 0x00000002,
+       AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004,
+       AR_INTR_SYNC_APB_TIMEOUT = 0x00000008,
+       AR_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010,
+       AR_INTR_SYNC_HOST1_FATAL = 0x00000020,
+       AR_INTR_SYNC_HOST1_PERR = 0x00000040,
+       AR_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080,
+       AR_INTR_SYNC_RADM_CPL_EP = 0x00000100,
+       AR_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200,
+       AR_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400,
+       AR_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800,
+       AR_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000,
+       AR_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000,
+       AR_INTR_SYNC_PM_ACCESS = 0x00004000,
+       AR_INTR_SYNC_MAC_AWAKE = 0x00008000,
+       AR_INTR_SYNC_MAC_ASLEEP = 0x00010000,
+       AR_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000,
+       AR_INTR_SYNC_ALL = 0x0003FFFF,
+
+
+       AR_INTR_SYNC_DEFAULT = (AR_INTR_SYNC_HOST1_FATAL |
+                               AR_INTR_SYNC_HOST1_PERR |
+                               AR_INTR_SYNC_RADM_CPL_EP |
+                               AR_INTR_SYNC_RADM_CPL_DLLP_ABORT |
+                               AR_INTR_SYNC_RADM_CPL_TLP_ABORT |
+                               AR_INTR_SYNC_RADM_CPL_ECRC_ERR |
+                               AR_INTR_SYNC_RADM_CPL_TIMEOUT |
+                               AR_INTR_SYNC_LOCAL_TIMEOUT |
+                               AR_INTR_SYNC_MAC_SLEEP_ACCESS),
+
+       AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF,
+
+};
+
+#define AR_INTR_ASYNC_MASK                       (AR_SREV_9340(ah) ? 0x4018 : 0x4030)
+#define AR_INTR_ASYNC_MASK_GPIO                  0xFFFC0000
+#define AR_INTR_ASYNC_MASK_GPIO_S                18
+#define AR_INTR_ASYNC_MASK_MCI                   0x00000080
+#define AR_INTR_ASYNC_MASK_MCI_S                 7
+
+#define AR_INTR_SYNC_MASK                        (AR_SREV_9340(ah) ? 0x401c : 0x4034)
+#define AR_INTR_SYNC_MASK_GPIO                   0xFFFC0000
+#define AR_INTR_SYNC_MASK_GPIO_S                 18
+
+#define AR_INTR_ASYNC_CAUSE_CLR                  (AR_SREV_9340(ah) ? 0x4020 : 0x4038)
+#define AR_INTR_ASYNC_CAUSE                      (AR_SREV_9340(ah) ? 0x4020 : 0x4038)
+#define AR_INTR_ASYNC_CAUSE_MCI                         0x00000080
+#define AR_INTR_ASYNC_USED                      (AR_INTR_MAC_IRQ | \
+                                                 AR_INTR_ASYNC_CAUSE_MCI)
+
+/* Asynchronous Interrupt Enable Register */
+#define AR_INTR_ASYNC_ENABLE_MCI         0x00000080
+#define AR_INTR_ASYNC_ENABLE_MCI_S       7
+
+
+#define AR_INTR_ASYNC_ENABLE                     (AR_SREV_9340(ah) ? 0x4024 : 0x403c)
+#define AR_INTR_ASYNC_ENABLE_GPIO                0xFFFC0000
+#define AR_INTR_ASYNC_ENABLE_GPIO_S              18
+
+#define AR_PCIE_SERDES                           0x4040
+#define AR_PCIE_SERDES2                          0x4044
+#define AR_PCIE_PM_CTRL                          (AR_SREV_9340(ah) ? 0x4004 : 0x4014)
+#define AR_PCIE_PM_CTRL_ENA                      0x00080000
+
+#define AR_NUM_GPIO                              14
+#define AR928X_NUM_GPIO                          10
+#define AR9285_NUM_GPIO                          12
+#define AR9287_NUM_GPIO                          11
+#define AR9271_NUM_GPIO                          16
+#define AR9300_NUM_GPIO                          17
+#define AR7010_NUM_GPIO                          16
+
+#define AR_GPIO_IN_OUT                           (AR_SREV_9340(ah) ? 0x4028 : 0x4048)
+#define AR_GPIO_IN_VAL                           0x0FFFC000
+#define AR_GPIO_IN_VAL_S                         14
+#define AR928X_GPIO_IN_VAL                       0x000FFC00
+#define AR928X_GPIO_IN_VAL_S                     10
+#define AR9285_GPIO_IN_VAL                       0x00FFF000
+#define AR9285_GPIO_IN_VAL_S                     12
+#define AR9287_GPIO_IN_VAL                       0x003FF800
+#define AR9287_GPIO_IN_VAL_S                     11
+#define AR9271_GPIO_IN_VAL                       0xFFFF0000
+#define AR9271_GPIO_IN_VAL_S                     16
+#define AR7010_GPIO_IN_VAL                       0x0000FFFF
+#define AR7010_GPIO_IN_VAL_S                     0
+
+#define AR_GPIO_IN                              (AR_SREV_9340(ah) ? 0x402c : 0x404c)
+#define AR9300_GPIO_IN_VAL                       0x0001FFFF
+#define AR9300_GPIO_IN_VAL_S                     0
+
+#define AR_GPIO_OE_OUT                           (AR_SREV_9340(ah) ? 0x4030 : \
+                                                 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c))
+#define AR_GPIO_OE_OUT_DRV                       0x3
+#define AR_GPIO_OE_OUT_DRV_NO                    0x0
+#define AR_GPIO_OE_OUT_DRV_LOW                   0x1
+#define AR_GPIO_OE_OUT_DRV_HI                    0x2
+#define AR_GPIO_OE_OUT_DRV_ALL                   0x3
+
+#define AR7010_GPIO_OE                           0x52000
+#define AR7010_GPIO_OE_MASK                      0x1
+#define AR7010_GPIO_OE_AS_OUTPUT                 0x0
+#define AR7010_GPIO_OE_AS_INPUT                  0x1
+#define AR7010_GPIO_IN                           0x52004
+#define AR7010_GPIO_OUT                          0x52008
+#define AR7010_GPIO_SET                          0x5200C
+#define AR7010_GPIO_CLEAR                        0x52010
+#define AR7010_GPIO_INT                          0x52014
+#define AR7010_GPIO_INT_TYPE                     0x52018
+#define AR7010_GPIO_INT_POLARITY                 0x5201C
+#define AR7010_GPIO_PENDING                      0x52020
+#define AR7010_GPIO_INT_MASK                     0x52024
+#define AR7010_GPIO_FUNCTION                     0x52028
+
+#define AR_GPIO_INTR_POL                         (AR_SREV_9340(ah) ? 0x4038 : \
+                                                 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050))
+#define AR_GPIO_INTR_POL_VAL                     0x0001FFFF
+#define AR_GPIO_INTR_POL_VAL_S                   0
+
+#define AR_GPIO_INPUT_EN_VAL                     (AR_SREV_9340(ah) ? 0x403c : \
+                                                 (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054))
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF     0x00000004
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S       2
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF    0x00000008
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S      3
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF       0x00000010
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S         4
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF        0x00000080
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S      7
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB      0x00000400
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S    10
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB        0x00001000
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S      12
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB         0x00008000
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S       15
+#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE        0x00010000
+#define AR_GPIO_JTAG_DISABLE                     0x00020000
+
+#define AR_GPIO_INPUT_MUX1                       (AR_SREV_9340(ah) ? 0x4040 : \
+                                                 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058))
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE             0x000f0000
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S           16
+#define AR_GPIO_INPUT_MUX1_BT_PRIORITY           0x00000f00
+#define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S         8
+
+#define AR_GPIO_INPUT_MUX2                       (AR_SREV_9340(ah) ? 0x4044 : \
+                                                 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c))
+#define AR_GPIO_INPUT_MUX2_CLK25                 0x0000000f
+#define AR_GPIO_INPUT_MUX2_CLK25_S               0
+#define AR_GPIO_INPUT_MUX2_RFSILENT              0x000000f0
+#define AR_GPIO_INPUT_MUX2_RFSILENT_S            4
+#define AR_GPIO_INPUT_MUX2_RTC_RESET             0x00000f00
+#define AR_GPIO_INPUT_MUX2_RTC_RESET_S           8
+
+#define AR_GPIO_OUTPUT_MUX1                      (AR_SREV_9340(ah) ? 0x4048 : \
+                                                 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060))
+#define AR_GPIO_OUTPUT_MUX2                      (AR_SREV_9340(ah) ? 0x404c : \
+                                                 (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064))
+#define AR_GPIO_OUTPUT_MUX3                      (AR_SREV_9340(ah) ? 0x4050 : \
+                                                 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068))
+
+#define AR_INPUT_STATE                           (AR_SREV_9340(ah) ? 0x4054 : \
+                                                 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c))
+
+#define AR_EEPROM_STATUS_DATA                    (AR_SREV_9340(ah) ? 0x40c8 : \
+                                                 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c))
+#define AR_EEPROM_STATUS_DATA_VAL                0x0000ffff
+#define AR_EEPROM_STATUS_DATA_VAL_S              0
+#define AR_EEPROM_STATUS_DATA_BUSY               0x00010000
+#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS        0x00020000
+#define AR_EEPROM_STATUS_DATA_PROT_ACCESS        0x00040000
+#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS      0x00080000
+
+#define AR_OBS                  (AR_SREV_9340(ah) ? 0x405c : \
+                                (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080))
+
+#define AR_GPIO_PDPU                             (AR_SREV_9300_20_OR_LATER(ah) ? 0x4090 : 0x4088)
+
+#define AR_PCIE_MSI                             (AR_SREV_9340(ah) ? 0x40d8 : \
+                                                (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094))
+#define AR_PCIE_MSI_ENABLE                       0x00000001
+
+#define AR_INTR_PRIO_SYNC_ENABLE  (AR_SREV_9340(ah) ? 0x4088 : 0x40c4)
+#define AR_INTR_PRIO_ASYNC_MASK   (AR_SREV_9340(ah) ? 0x408c : 0x40c8)
+#define AR_INTR_PRIO_SYNC_MASK    (AR_SREV_9340(ah) ? 0x4090 : 0x40cc)
+#define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
+#define AR_ENT_OTP               0x40d8
+#define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000
+#define AR_ENT_OTP_49GHZ_DISABLE               0x00100000
+#define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE                0x00800000
+
+#define AR_CH0_BB_DPLL1                 0x16180
+#define AR_CH0_BB_DPLL1_REFDIV  0xF8000000
+#define AR_CH0_BB_DPLL1_REFDIV_S 27
+#define AR_CH0_BB_DPLL1_NINI    0x07FC0000
+#define AR_CH0_BB_DPLL1_NINI_S  18
+#define AR_CH0_BB_DPLL1_NFRAC   0x0003FFFF
+#define AR_CH0_BB_DPLL1_NFRAC_S         0
+
+#define AR_CH0_BB_DPLL2                     0x16184
+#define AR_CH0_BB_DPLL2_LOCAL_PLL       0x40000000
+#define AR_CH0_BB_DPLL2_LOCAL_PLL_S     30
+#define AR_CH0_DPLL2_KI              0x3C000000
+#define AR_CH0_DPLL2_KI_S            26
+#define AR_CH0_DPLL2_KD              0x03F80000
+#define AR_CH0_DPLL2_KD_S            19
+#define AR_CH0_BB_DPLL2_EN_NEGTRIG   0x00040000
+#define AR_CH0_BB_DPLL2_EN_NEGTRIG_S 18
+#define AR_CH0_BB_DPLL2_PLL_PWD             0x00010000
+#define AR_CH0_BB_DPLL2_PLL_PWD_S    16
+#define AR_CH0_BB_DPLL2_OUTDIV      0x0000E000
+#define AR_CH0_BB_DPLL2_OUTDIV_S     13
+
+#define AR_CH0_BB_DPLL3          0x16188
+#define AR_CH0_BB_DPLL3_PHASE_SHIFT    0x3F800000
+#define AR_CH0_BB_DPLL3_PHASE_SHIFT_S  23
+
+#define AR_CH0_DDR_DPLL2         0x16244
+#define AR_CH0_DDR_DPLL3         0x16248
+#define AR_CH0_DPLL3_PHASE_SHIFT     0x3F800000
+#define AR_CH0_DPLL3_PHASE_SHIFT_S   23
+#define AR_PHY_CCA_NOM_VAL_2GHZ      -118
+
+#define AR_RTC_9300_PLL_DIV          0x000003ff
+#define AR_RTC_9300_PLL_DIV_S        0
+#define AR_RTC_9300_PLL_REFDIV       0x00003C00
+#define AR_RTC_9300_PLL_REFDIV_S     10
+#define AR_RTC_9300_PLL_CLKSEL       0x0000C000
+#define AR_RTC_9300_PLL_CLKSEL_S     14
+
+#define AR_RTC_9160_PLL_DIV    0x000003ff
+#define AR_RTC_9160_PLL_DIV_S   0
+#define AR_RTC_9160_PLL_REFDIV  0x00003C00
+#define AR_RTC_9160_PLL_REFDIV_S 10
+#define AR_RTC_9160_PLL_CLKSEL 0x0000C000
+#define AR_RTC_9160_PLL_CLKSEL_S 14
+
+#define AR_RTC_BASE             0x00020000
+#define AR_RTC_RC \
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000)
+#define AR_RTC_RC_M            0x00000003
+#define AR_RTC_RC_MAC_WARM      0x00000001
+#define AR_RTC_RC_MAC_COLD      0x00000002
+#define AR_RTC_RC_COLD_RESET    0x00000004
+#define AR_RTC_RC_WARM_RESET    0x00000008
+
+/* Crystal Control */
+#define AR_RTC_XTAL_CONTROL     0x7004
+
+/* Reg Control 0 */
+#define AR_RTC_REG_CONTROL0     0x7008
+
+/* Reg Control 1 */
+#define AR_RTC_REG_CONTROL1     0x700c
+#define AR_RTC_REG_CONTROL1_SWREG_PROGRAM       0x00000001
+
+#define AR_RTC_PLL_CONTROL \
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014)
+
+#define AR_RTC_PLL_CONTROL2    0x703c
+
+#define AR_RTC_PLL_DIV          0x0000001f
+#define AR_RTC_PLL_DIV_S        0
+#define AR_RTC_PLL_DIV2         0x00000020
+#define AR_RTC_PLL_REFDIV_5     0x000000c0
+#define AR_RTC_PLL_CLKSEL       0x00000300
+#define AR_RTC_PLL_CLKSEL_S     8
+#define AR_RTC_PLL_BYPASS      0x00010000
+
+#define PLL3 0x16188
+#define PLL3_DO_MEAS_MASK 0x40000000
+#define PLL4 0x1618c
+#define PLL4_MEAS_DONE    0x8
+#define SQSUM_DVC_MASK 0x007ffff8
+
+#define AR_RTC_RESET \
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040)
+#define AR_RTC_RESET_EN                (0x00000001)
+
+#define AR_RTC_STATUS \
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0044) : 0x7044)
+
+#define AR_RTC_STATUS_M \
+       ((AR_SREV_9100(ah)) ? 0x0000003f : 0x0000000f)
+
+#define AR_RTC_PM_STATUS_M      0x0000000f
+
+#define AR_RTC_STATUS_SHUTDOWN  0x00000001
+#define AR_RTC_STATUS_ON        0x00000002
+#define AR_RTC_STATUS_SLEEP     0x00000004
+#define AR_RTC_STATUS_WAKEUP    0x00000008
+
+#define AR_RTC_SLEEP_CLK \
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048)
+#define AR_RTC_FORCE_DERIVED_CLK    0x2
+#define AR_RTC_FORCE_SWREG_PRD      0x00000004
+
+#define AR_RTC_FORCE_WAKE \
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c)
+#define AR_RTC_FORCE_WAKE_EN        0x00000001
+#define AR_RTC_FORCE_WAKE_ON_INT    0x00000002
+
+
+#define AR_RTC_INTR_CAUSE \
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0050) : 0x7050)
+
+#define AR_RTC_INTR_ENABLE \
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0054) : 0x7054)
+
+#define AR_RTC_INTR_MASK \
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058)
+
+#define AR_RTC_KEEP_AWAKE      0x7034
+
+/* RTC_DERIVED_* - only for AR9100 */
+
+#define AR_RTC_DERIVED_CLK \
+       (AR_SREV_9100(ah) ? (AR_RTC_BASE + 0x0038) : 0x7038)
+#define AR_RTC_DERIVED_CLK_PERIOD    0x0000fffe
+#define AR_RTC_DERIVED_CLK_PERIOD_S  1
+
+#define        AR_SEQ_MASK     0x8060
+
+#define AR_AN_RF2G1_CH0         0x7810
+#define AR_AN_RF2G1_CH0_OB      0x03800000
+#define AR_AN_RF2G1_CH0_OB_S    23
+#define AR_AN_RF2G1_CH0_DB      0x1C000000
+#define AR_AN_RF2G1_CH0_DB_S    26
+
+#define AR_AN_RF5G1_CH0         0x7818
+#define AR_AN_RF5G1_CH0_OB5     0x00070000
+#define AR_AN_RF5G1_CH0_OB5_S   16
+#define AR_AN_RF5G1_CH0_DB5     0x00380000
+#define AR_AN_RF5G1_CH0_DB5_S   19
+
+#define AR_AN_RF2G1_CH1         0x7834
+#define AR_AN_RF2G1_CH1_OB      0x03800000
+#define AR_AN_RF2G1_CH1_OB_S    23
+#define AR_AN_RF2G1_CH1_DB      0x1C000000
+#define AR_AN_RF2G1_CH1_DB_S    26
+
+#define AR_AN_RF5G1_CH1         0x783C
+#define AR_AN_RF5G1_CH1_OB5     0x00070000
+#define AR_AN_RF5G1_CH1_OB5_S   16
+#define AR_AN_RF5G1_CH1_DB5     0x00380000
+#define AR_AN_RF5G1_CH1_DB5_S   19
+
+#define AR_AN_TOP1                  0x7890
+#define AR_AN_TOP1_DACIPMODE       0x00040000
+#define AR_AN_TOP1_DACIPMODE_S     18
+
+#define AR_AN_TOP2                  0x7894
+#define AR_AN_TOP2_XPABIAS_LVL      0xC0000000
+#define AR_AN_TOP2_XPABIAS_LVL_S    30
+#define AR_AN_TOP2_LOCALBIAS        0x00200000
+#define AR_AN_TOP2_LOCALBIAS_S      21
+#define AR_AN_TOP2_PWDCLKIND        0x00400000
+#define AR_AN_TOP2_PWDCLKIND_S      22
+
+#define AR_AN_SYNTH9            0x7868
+#define AR_AN_SYNTH9_REFDIVA    0xf8000000
+#define AR_AN_SYNTH9_REFDIVA_S  27
+
+#define AR9285_AN_RF2G1              0x7820
+#define AR9285_AN_RF2G1_ENPACAL      0x00000800
+#define AR9285_AN_RF2G1_ENPACAL_S    11
+#define AR9285_AN_RF2G1_PDPADRV1     0x02000000
+#define AR9285_AN_RF2G1_PDPADRV1_S   25
+#define AR9285_AN_RF2G1_PDPADRV2     0x01000000
+#define AR9285_AN_RF2G1_PDPADRV2_S   24
+#define AR9285_AN_RF2G1_PDPAOUT      0x00800000
+#define AR9285_AN_RF2G1_PDPAOUT_S    23
+
+
+#define AR9285_AN_RF2G2              0x7824
+#define AR9285_AN_RF2G2_OFFCAL       0x00001000
+#define AR9285_AN_RF2G2_OFFCAL_S     12
+
+#define AR9285_AN_RF2G3             0x7828
+#define AR9285_AN_RF2G3_PDVCCOMP    0x02000000
+#define AR9285_AN_RF2G3_PDVCCOMP_S  25
+#define AR9285_AN_RF2G3_OB_0    0x00E00000
+#define AR9285_AN_RF2G3_OB_0_S    21
+#define AR9285_AN_RF2G3_OB_1    0x001C0000
+#define AR9285_AN_RF2G3_OB_1_S    18
+#define AR9285_AN_RF2G3_OB_2    0x00038000
+#define AR9285_AN_RF2G3_OB_2_S    15
+#define AR9285_AN_RF2G3_OB_3    0x00007000
+#define AR9285_AN_RF2G3_OB_3_S    12
+#define AR9285_AN_RF2G3_OB_4    0x00000E00
+#define AR9285_AN_RF2G3_OB_4_S    9
+
+#define AR9285_AN_RF2G3_DB1_0    0x000001C0
+#define AR9285_AN_RF2G3_DB1_0_S    6
+#define AR9285_AN_RF2G3_DB1_1    0x00000038
+#define AR9285_AN_RF2G3_DB1_1_S    3
+#define AR9285_AN_RF2G3_DB1_2    0x00000007
+#define AR9285_AN_RF2G3_DB1_2_S    0
+#define AR9285_AN_RF2G4         0x782C
+#define AR9285_AN_RF2G4_DB1_3    0xE0000000
+#define AR9285_AN_RF2G4_DB1_3_S    29
+#define AR9285_AN_RF2G4_DB1_4    0x1C000000
+#define AR9285_AN_RF2G4_DB1_4_S    26
+
+#define AR9285_AN_RF2G4_DB2_0    0x03800000
+#define AR9285_AN_RF2G4_DB2_0_S    23
+#define AR9285_AN_RF2G4_DB2_1    0x00700000
+#define AR9285_AN_RF2G4_DB2_1_S    20
+#define AR9285_AN_RF2G4_DB2_2    0x000E0000
+#define AR9285_AN_RF2G4_DB2_2_S    17
+#define AR9285_AN_RF2G4_DB2_3    0x0001C000
+#define AR9285_AN_RF2G4_DB2_3_S    14
+#define AR9285_AN_RF2G4_DB2_4    0x00003800
+#define AR9285_AN_RF2G4_DB2_4_S    11
+
+#define AR9285_RF2G5                   0x7830
+#define AR9285_RF2G5_IC50TX            0xfffff8ff
+#define AR9285_RF2G5_IC50TX_SET                0x00000400
+#define AR9285_RF2G5_IC50TX_XE_SET     0x00000500
+#define AR9285_RF2G5_IC50TX_CLEAR      0x00000700
+#define AR9285_RF2G5_IC50TX_CLEAR_S    8
+
+/* AR9271 : 0x7828, 0x782c different setting from AR9285 */
+#define AR9271_AN_RF2G3_OB_cck         0x001C0000
+#define AR9271_AN_RF2G3_OB_cck_S       18
+#define AR9271_AN_RF2G3_OB_psk         0x00038000
+#define AR9271_AN_RF2G3_OB_psk_S       15
+#define AR9271_AN_RF2G3_OB_qam         0x00007000
+#define AR9271_AN_RF2G3_OB_qam_S       12
+
+#define AR9271_AN_RF2G3_DB_1           0x00E00000
+#define AR9271_AN_RF2G3_DB_1_S         21
+
+#define AR9271_AN_RF2G3_CCOMP          0xFFF
+#define AR9271_AN_RF2G3_CCOMP_S                0
+
+#define AR9271_AN_RF2G4_DB_2           0xE0000000
+#define AR9271_AN_RF2G4_DB_2_S         29
+
+#define AR9285_AN_RF2G6                 0x7834
+#define AR9285_AN_RF2G6_CCOMP           0x00007800
+#define AR9285_AN_RF2G6_CCOMP_S         11
+#define AR9285_AN_RF2G6_OFFS            0x03f00000
+#define AR9285_AN_RF2G6_OFFS_S          20
+
+#define AR9271_AN_RF2G6_OFFS            0x07f00000
+#define AR9271_AN_RF2G6_OFFS_S            20
+
+#define AR9285_AN_RF2G7                 0x7838
+#define AR9285_AN_RF2G7_PWDDB           0x00000002
+#define AR9285_AN_RF2G7_PWDDB_S         1
+#define AR9285_AN_RF2G7_PADRVGN2TAB0    0xE0000000
+#define AR9285_AN_RF2G7_PADRVGN2TAB0_S  29
+
+#define AR9285_AN_RF2G8                  0x783C
+#define AR9285_AN_RF2G8_PADRVGN2TAB0     0x0001C000
+#define AR9285_AN_RF2G8_PADRVGN2TAB0_S   14
+
+
+#define AR9285_AN_RF2G9          0x7840
+#define AR9285_AN_RXTXBB1              0x7854
+#define AR9285_AN_RXTXBB1_PDRXTXBB1    0x00000020
+#define AR9285_AN_RXTXBB1_PDRXTXBB1_S  5
+#define AR9285_AN_RXTXBB1_PDV2I        0x00000080
+#define AR9285_AN_RXTXBB1_PDV2I_S      7
+#define AR9285_AN_RXTXBB1_PDDACIF      0x00000100
+#define AR9285_AN_RXTXBB1_PDDACIF_S    8
+#define AR9285_AN_RXTXBB1_SPARE9       0x00000001
+#define AR9285_AN_RXTXBB1_SPARE9_S     0
+
+#define AR9285_AN_TOP2           0x7868
+
+#define AR9285_AN_TOP3                  0x786c
+#define AR9285_AN_TOP3_XPABIAS_LVL      0x0000000C
+#define AR9285_AN_TOP3_XPABIAS_LVL_S    2
+#define AR9285_AN_TOP3_PWDDAC           0x00800000
+#define AR9285_AN_TOP3_PWDDAC_S    23
+
+#define AR9285_AN_TOP4           0x7870
+#define AR9285_AN_TOP4_DEFAULT   0x10142c00
+
+#define AR9287_AN_RF2G3_CH0             0x7808
+#define AR9287_AN_RF2G3_CH1             0x785c
+#define AR9287_AN_RF2G3_DB1             0xE0000000
+#define AR9287_AN_RF2G3_DB1_S           29
+#define AR9287_AN_RF2G3_DB2             0x1C000000
+#define AR9287_AN_RF2G3_DB2_S           26
+#define AR9287_AN_RF2G3_OB_CCK          0x03800000
+#define AR9287_AN_RF2G3_OB_CCK_S        23
+#define AR9287_AN_RF2G3_OB_PSK          0x00700000
+#define AR9287_AN_RF2G3_OB_PSK_S        20
+#define AR9287_AN_RF2G3_OB_QAM          0x000E0000
+#define AR9287_AN_RF2G3_OB_QAM_S        17
+#define AR9287_AN_RF2G3_OB_PAL_OFF      0x0001C000
+#define AR9287_AN_RF2G3_OB_PAL_OFF_S    14
+
+#define AR9287_AN_TXPC0                 0x7898
+#define AR9287_AN_TXPC0_TXPCMODE        0x0000C000
+#define AR9287_AN_TXPC0_TXPCMODE_S      14
+#define AR9287_AN_TXPC0_TXPCMODE_NORMAL    0
+#define AR9287_AN_TXPC0_TXPCMODE_TEST      1
+#define AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE 2
+#define AR9287_AN_TXPC0_TXPCMODE_ATBTEST   3
+
+#define AR9287_AN_TOP2                  0x78b4
+#define AR9287_AN_TOP2_XPABIAS_LVL      0xC0000000
+#define AR9287_AN_TOP2_XPABIAS_LVL_S    30
+
+/* AR9271 specific stuff */
+#define AR9271_RESET_POWER_DOWN_CONTROL                0x50044
+#define AR9271_RADIO_RF_RST                    0x20
+#define AR9271_GATE_MAC_CTL                    0x4000
+
+#define AR_STA_ID0                 0x8000
+#define AR_STA_ID1                 0x8004
+#define AR_STA_ID1_SADH_MASK       0x0000FFFF
+#define AR_STA_ID1_STA_AP          0x00010000
+#define AR_STA_ID1_ADHOC           0x00020000
+#define AR_STA_ID1_PWR_SAV         0x00040000
+#define AR_STA_ID1_KSRCHDIS        0x00080000
+#define AR_STA_ID1_PCF             0x00100000
+#define AR_STA_ID1_USE_DEFANT      0x00200000
+#define AR_STA_ID1_DEFANT_UPDATE   0x00400000
+#define AR_STA_ID1_AR9100_BA_FIX   0x00400000
+#define AR_STA_ID1_RTS_USE_DEF     0x00800000
+#define AR_STA_ID1_ACKCTS_6MB      0x01000000
+#define AR_STA_ID1_BASE_RATE_11B   0x02000000
+#define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000
+#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000
+#define AR_STA_ID1_KSRCH_MODE      0x10000000
+#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000
+#define AR_STA_ID1_CBCIV_ENDIAN    0x40000000
+#define AR_STA_ID1_MCAST_KSRCH     0x80000000
+
+#define AR_BSS_ID0          0x8008
+#define AR_BSS_ID1          0x800C
+#define AR_BSS_ID1_U16       0x0000FFFF
+#define AR_BSS_ID1_AID       0x07FF0000
+#define AR_BSS_ID1_AID_S     16
+
+#define AR_BCN_RSSI_AVE      0x8010
+#define AR_BCN_RSSI_AVE_MASK 0x00000FFF
+
+#define AR_TIME_OUT         0x8014
+#define AR_TIME_OUT_ACK      0x00003FFF
+#define AR_TIME_OUT_ACK_S    0
+#define AR_TIME_OUT_CTS      0x3FFF0000
+#define AR_TIME_OUT_CTS_S    16
+
+#define AR_RSSI_THR          0x8018
+#define AR_RSSI_THR_MASK     0x000000FF
+#define AR_RSSI_THR_BM_THR   0x0000FF00
+#define AR_RSSI_THR_BM_THR_S 8
+#define AR_RSSI_BCN_WEIGHT   0x1F000000
+#define AR_RSSI_BCN_WEIGHT_S 24
+#define AR_RSSI_BCN_RSSI_RST 0x20000000
+
+#define AR_USEC              0x801c
+#define AR_USEC_USEC         0x0000007F
+#define AR_USEC_TX_LAT       0x007FC000
+#define AR_USEC_TX_LAT_S     14
+#define AR_USEC_RX_LAT       0x1F800000
+#define AR_USEC_RX_LAT_S     23
+#define AR_USEC_ASYNC_FIFO   0x12E00074
+
+#define AR_RESET_TSF        0x8020
+#define AR_RESET_TSF_ONCE   0x01000000
+
+#define AR_MAX_CFP_DUR      0x8038
+#define AR_CFP_VAL          0x0000FFFF
+
+#define AR_RX_FILTER        0x803C
+
+#define AR_MCAST_FIL0       0x8040
+#define AR_MCAST_FIL1       0x8044
+
+/*
+ * AR_DIAG_SW - Register which can be used for diagnostics and testing purposes.
+ *
+ * The force RX abort (AR_DIAG_RX_ABORT, bit 25) can be used in conjunction with
+ * RX block (AR_DIAG_RX_DIS, bit 5) to help fast channel change to shut down
+ * receive. The force RX abort bit will kill any frame which is currently being
+ * transferred between the MAC and baseband. The RX block bit (AR_DIAG_RX_DIS)
+ * will prevent any new frames from getting started.
+ */
+#define AR_DIAG_SW                  0x8048
+#define AR_DIAG_CACHE_ACK           0x00000001
+#define AR_DIAG_ACK_DIS             0x00000002
+#define AR_DIAG_CTS_DIS             0x00000004
+#define AR_DIAG_ENCRYPT_DIS         0x00000008
+#define AR_DIAG_DECRYPT_DIS         0x00000010
+#define AR_DIAG_RX_DIS              0x00000020 /* RX block */
+#define AR_DIAG_LOOP_BACK           0x00000040
+#define AR_DIAG_CORR_FCS            0x00000080
+#define AR_DIAG_CHAN_INFO           0x00000100
+#define AR_DIAG_SCRAM_SEED          0x0001FE00
+#define AR_DIAG_SCRAM_SEED_S        8
+#define AR_DIAG_FRAME_NV0           0x00020000
+#define AR_DIAG_OBS_PT_SEL1         0x000C0000
+#define AR_DIAG_OBS_PT_SEL1_S       18
+#define AR_DIAG_OBS_PT_SEL2         0x08000000
+#define AR_DIAG_OBS_PT_SEL2_S       27
+#define AR_DIAG_FORCE_RX_CLEAR      0x00100000 /* force rx_clear high */
+#define AR_DIAG_IGNORE_VIRT_CS      0x00200000
+#define AR_DIAG_FORCE_CH_IDLE_HIGH  0x00400000
+#define AR_DIAG_EIFS_CTRL_ENA       0x00800000
+#define AR_DIAG_DUAL_CHAIN_INFO     0x01000000
+#define AR_DIAG_RX_ABORT            0x02000000 /* Force RX abort */
+#define AR_DIAG_SATURATE_CYCLE_CNT  0x04000000
+#define AR_DIAG_OBS_PT_SEL2         0x08000000
+#define AR_DIAG_RX_CLEAR_CTL_LOW    0x10000000
+#define AR_DIAG_RX_CLEAR_EXT_LOW    0x20000000
+
+#define AR_TSF_L32          0x804c
+#define AR_TSF_U32          0x8050
+
+#define AR_TST_ADDAC        0x8054
+#define AR_DEF_ANTENNA      0x8058
+
+#define AR_AES_MUTE_MASK0       0x805c
+#define AR_AES_MUTE_MASK0_FC    0x0000FFFF
+#define AR_AES_MUTE_MASK0_QOS   0xFFFF0000
+#define AR_AES_MUTE_MASK0_QOS_S 16
+
+#define AR_AES_MUTE_MASK1       0x8060
+#define AR_AES_MUTE_MASK1_SEQ   0x0000FFFF
+#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000
+#define AR_AES_MUTE_MASK1_FC_MGMT_S 16
+
+#define AR_GATED_CLKS       0x8064
+#define AR_GATED_CLKS_TX    0x00000002
+#define AR_GATED_CLKS_RX    0x00000004
+#define AR_GATED_CLKS_REG   0x00000008
+
+#define AR_OBS_BUS_CTRL     0x8068
+#define AR_OBS_BUS_SEL_1    0x00040000
+#define AR_OBS_BUS_SEL_2    0x00080000
+#define AR_OBS_BUS_SEL_3    0x000C0000
+#define AR_OBS_BUS_SEL_4    0x08040000
+#define AR_OBS_BUS_SEL_5    0x08080000
+
+#define AR_OBS_BUS_1               0x806c
+#define AR_OBS_BUS_1_PCU           0x00000001
+#define AR_OBS_BUS_1_RX_END        0x00000002
+#define AR_OBS_BUS_1_RX_WEP        0x00000004
+#define AR_OBS_BUS_1_RX_BEACON     0x00000008
+#define AR_OBS_BUS_1_RX_FILTER     0x00000010
+#define AR_OBS_BUS_1_TX_HCF        0x00000020
+#define AR_OBS_BUS_1_QUIET_TIME    0x00000040
+#define AR_OBS_BUS_1_CHAN_IDLE     0x00000080
+#define AR_OBS_BUS_1_TX_HOLD       0x00000100
+#define AR_OBS_BUS_1_TX_FRAME      0x00000200
+#define AR_OBS_BUS_1_RX_FRAME      0x00000400
+#define AR_OBS_BUS_1_RX_CLEAR      0x00000800
+#define AR_OBS_BUS_1_WEP_STATE     0x0003F000
+#define AR_OBS_BUS_1_WEP_STATE_S   12
+#define AR_OBS_BUS_1_RX_STATE      0x01F00000
+#define AR_OBS_BUS_1_RX_STATE_S    20
+#define AR_OBS_BUS_1_TX_STATE      0x7E000000
+#define AR_OBS_BUS_1_TX_STATE_S    25
+
+#define AR_LAST_TSTP        0x8080
+#define AR_NAV              0x8084
+#define AR_RTS_OK           0x8088
+#define AR_RTS_FAIL         0x808c
+#define AR_ACK_FAIL         0x8090
+#define AR_FCS_FAIL         0x8094
+#define AR_BEACON_CNT       0x8098
+
+#define AR_SLEEP1               0x80d4
+#define AR_SLEEP1_ASSUME_DTIM   0x00080000
+#define AR_SLEEP1_CAB_TIMEOUT   0xFFE00000
+#define AR_SLEEP1_CAB_TIMEOUT_S 21
+
+#define AR_SLEEP2                   0x80d8
+#define AR_SLEEP2_BEACON_TIMEOUT    0xFFE00000
+#define AR_SLEEP2_BEACON_TIMEOUT_S  21
+
+#define AR_TPC                 0x80e8
+#define AR_TPC_ACK             0x0000003f
+#define AR_TPC_ACK_S           0
+#define AR_TPC_CTS             0x00003f00
+#define AR_TPC_CTS_S           8
+#define AR_TPC_CHIRP           0x003f0000
+#define AR_TPC_CHIRP_S         16
+
+#define AR_QUIET1          0x80fc
+#define AR_QUIET1_NEXT_QUIET_S         0
+#define AR_QUIET1_NEXT_QUIET_M         0x0000ffff
+#define AR_QUIET1_QUIET_ENABLE         0x00010000
+#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000
+#define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17
+#define AR_QUIET2          0x8100
+#define AR_QUIET2_QUIET_PERIOD_S       0
+#define AR_QUIET2_QUIET_PERIOD_M       0x0000ffff
+#define AR_QUIET2_QUIET_DUR_S     16
+#define AR_QUIET2_QUIET_DUR       0xffff0000
+
+#define AR_TSF_PARM        0x8104
+#define AR_TSF_INCREMENT_M     0x000000ff
+#define AR_TSF_INCREMENT_S     0x00
+
+#define AR_QOS_NO_ACK              0x8108
+#define AR_QOS_NO_ACK_TWO_BIT      0x0000000f
+#define AR_QOS_NO_ACK_TWO_BIT_S    0
+#define AR_QOS_NO_ACK_BIT_OFF      0x00000070
+#define AR_QOS_NO_ACK_BIT_OFF_S    4
+#define AR_QOS_NO_ACK_BYTE_OFF     0x00000180
+#define AR_QOS_NO_ACK_BYTE_OFF_S   7
+
+#define AR_PHY_ERR         0x810c
+
+#define AR_PHY_ERR_DCHIRP      0x00000008
+#define AR_PHY_ERR_RADAR       0x00000020
+#define AR_PHY_ERR_OFDM_TIMING 0x00020000
+#define AR_PHY_ERR_CCK_TIMING  0x02000000
+
+#define AR_RXFIFO_CFG          0x8114
+
+
+#define AR_MIC_QOS_CONTROL 0x8118
+#define AR_MIC_QOS_SELECT  0x811c
+
+#define AR_PCU_MISC                0x8120
+#define AR_PCU_FORCE_BSSID_MATCH   0x00000001
+#define AR_PCU_MIC_NEW_LOC_ENA     0x00000004
+#define AR_PCU_TX_ADD_TSF          0x00000008
+#define AR_PCU_CCK_SIFS_MODE       0x00000010
+#define AR_PCU_RX_ANT_UPDT         0x00000800
+#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000
+#define AR_PCU_MISS_BCN_IN_SLEEP   0x00004000
+#define AR_PCU_BUG_12306_FIX_ENA   0x00020000
+#define AR_PCU_FORCE_QUIET_COLL    0x00040000
+#define AR_PCU_TBTT_PROTECT        0x00200000
+#define AR_PCU_CLEAR_VMF           0x01000000
+#define AR_PCU_CLEAR_BA_VALID      0x04000000
+#define AR_PCU_ALWAYS_PERFORM_KEYSEARCH 0x10000000
+
+#define AR_PCU_BT_ANT_PREVENT_RX   0x00100000
+#define AR_PCU_BT_ANT_PREVENT_RX_S 20
+
+#define AR_FILT_OFDM           0x8124
+#define AR_FILT_OFDM_COUNT     0x00FFFFFF
+
+#define AR_FILT_CCK            0x8128
+#define AR_FILT_CCK_COUNT      0x00FFFFFF
+
+#define AR_PHY_ERR_1           0x812c
+#define AR_PHY_ERR_1_COUNT     0x00FFFFFF
+#define AR_PHY_ERR_MASK_1      0x8130
+
+#define AR_PHY_ERR_2           0x8134
+#define AR_PHY_ERR_2_COUNT     0x00FFFFFF
+#define AR_PHY_ERR_MASK_2      0x8138
+
+#define AR_PHY_COUNTMAX        (3 << 22)
+#define AR_MIBCNT_INTRMASK     (3 << 22)
+
+#define AR_TSFOOR_THRESHOLD       0x813c
+#define AR_TSFOOR_THRESHOLD_VAL   0x0000FFFF
+
+#define AR_PHY_ERR_EIFS_MASK   0x8144
+
+#define AR_PHY_ERR_3           0x8168
+#define AR_PHY_ERR_3_COUNT     0x00FFFFFF
+#define AR_PHY_ERR_MASK_3      0x816c
+
+#define AR_BT_COEX_MODE            0x8170
+#define AR_BT_TIME_EXTEND          0x000000ff
+#define AR_BT_TIME_EXTEND_S        0
+#define AR_BT_TXSTATE_EXTEND       0x00000100
+#define AR_BT_TXSTATE_EXTEND_S     8
+#define AR_BT_TX_FRAME_EXTEND      0x00000200
+#define AR_BT_TX_FRAME_EXTEND_S    9
+#define AR_BT_MODE                 0x00000c00
+#define AR_BT_MODE_S               10
+#define AR_BT_QUIET                0x00001000
+#define AR_BT_QUIET_S              12
+#define AR_BT_QCU_THRESH           0x0001e000
+#define AR_BT_QCU_THRESH_S         13
+#define AR_BT_RX_CLEAR_POLARITY    0x00020000
+#define AR_BT_RX_CLEAR_POLARITY_S  17
+#define AR_BT_PRIORITY_TIME        0x00fc0000
+#define AR_BT_PRIORITY_TIME_S      18
+#define AR_BT_FIRST_SLOT_TIME      0xff000000
+#define AR_BT_FIRST_SLOT_TIME_S    24
+
+#define AR_BT_COEX_WEIGHT          0x8174
+#define AR_BT_COEX_WGHT                   0xff55
+#define AR_STOMP_ALL_WLAN_WGHT    0xfcfc
+#define AR_STOMP_LOW_WLAN_WGHT    0xa8a8
+#define AR_STOMP_NONE_WLAN_WGHT           0x0000
+#define AR_BTCOEX_BT_WGHT          0x0000ffff
+#define AR_BTCOEX_BT_WGHT_S        0
+#define AR_BTCOEX_WL_WGHT          0xffff0000
+#define AR_BTCOEX_WL_WGHT_S        16
+
+#define AR_BT_COEX_WL_WEIGHTS0     0x8174
+#define AR_BT_COEX_WL_WEIGHTS1     0x81c4
+#define AR_MCI_COEX_WL_WEIGHTS(_i) (0x18b0 + (_i << 2))
+#define AR_BT_COEX_BT_WEIGHTS(_i)  (0x83ac + (_i << 2))
+
+#define AR9300_BT_WGHT             0xcccc4444
+
+#define AR_BT_COEX_MODE2           0x817c
+#define AR_BT_BCN_MISS_THRESH      0x000000ff
+#define AR_BT_BCN_MISS_THRESH_S    0
+#define AR_BT_BCN_MISS_CNT         0x0000ff00
+#define AR_BT_BCN_MISS_CNT_S       8
+#define AR_BT_HOLD_RX_CLEAR        0x00010000
+#define AR_BT_HOLD_RX_CLEAR_S      16
+#define AR_BT_DISABLE_BT_ANT       0x00100000
+#define AR_BT_DISABLE_BT_ANT_S     20
+
+#define AR_TXSIFS              0x81d0
+#define AR_TXSIFS_TIME         0x000000FF
+#define AR_TXSIFS_TX_LATENCY   0x00000F00
+#define AR_TXSIFS_TX_LATENCY_S 8
+#define AR_TXSIFS_ACK_SHIFT    0x00007000
+#define AR_TXSIFS_ACK_SHIFT_S  12
+
+#define AR_TXOP_X          0x81ec
+#define AR_TXOP_X_VAL      0x000000FF
+
+
+#define AR_TXOP_0_3    0x81f0
+#define AR_TXOP_4_7    0x81f4
+#define AR_TXOP_8_11   0x81f8
+#define AR_TXOP_12_15  0x81fc
+
+#define AR_NEXT_NDP2_TIMER                  0x8180
+#define AR_GEN_TIMER_BANK_1_LEN                        8
+#define AR_FIRST_NDP_TIMER                  7
+#define AR_NDP2_PERIOD                      0x81a0
+#define AR_NDP2_TIMER_MODE                  0x81c0
+
+#define AR_GEN_TIMERS(_i)                   (0x8200 + ((_i) << 2))
+#define AR_NEXT_TBTT_TIMER                  AR_GEN_TIMERS(0)
+#define AR_NEXT_DMA_BEACON_ALERT            AR_GEN_TIMERS(1)
+#define AR_NEXT_SWBA                        AR_GEN_TIMERS(2)
+#define AR_NEXT_CFP                         AR_GEN_TIMERS(2)
+#define AR_NEXT_HCF                         AR_GEN_TIMERS(3)
+#define AR_NEXT_TIM                         AR_GEN_TIMERS(4)
+#define AR_NEXT_DTIM                        AR_GEN_TIMERS(5)
+#define AR_NEXT_QUIET_TIMER                 AR_GEN_TIMERS(6)
+#define AR_NEXT_NDP_TIMER                   AR_GEN_TIMERS(7)
+
+#define AR_BEACON_PERIOD                    AR_GEN_TIMERS(8)
+#define AR_DMA_BEACON_PERIOD                AR_GEN_TIMERS(9)
+#define AR_SWBA_PERIOD                      AR_GEN_TIMERS(10)
+#define AR_HCF_PERIOD                       AR_GEN_TIMERS(11)
+#define AR_TIM_PERIOD                       AR_GEN_TIMERS(12)
+#define AR_DTIM_PERIOD                      AR_GEN_TIMERS(13)
+#define AR_QUIET_PERIOD                     AR_GEN_TIMERS(14)
+#define AR_NDP_PERIOD                       AR_GEN_TIMERS(15)
+
+#define AR_TIMER_MODE                       0x8240
+#define AR_TBTT_TIMER_EN                    0x00000001
+#define AR_DBA_TIMER_EN                     0x00000002
+#define AR_SWBA_TIMER_EN                    0x00000004
+#define AR_HCF_TIMER_EN                     0x00000008
+#define AR_TIM_TIMER_EN                     0x00000010
+#define AR_DTIM_TIMER_EN                    0x00000020
+#define AR_QUIET_TIMER_EN                   0x00000040
+#define AR_NDP_TIMER_EN                     0x00000080
+#define AR_TIMER_OVERFLOW_INDEX             0x00000700
+#define AR_TIMER_OVERFLOW_INDEX_S           8
+#define AR_TIMER_THRESH                     0xFFFFF000
+#define AR_TIMER_THRESH_S                   12
+
+#define AR_SLP32_MODE                  0x8244
+#define AR_SLP32_HALF_CLK_LATENCY      0x000FFFFF
+#define AR_SLP32_ENA                   0x00100000
+#define AR_SLP32_TSF_WRITE_STATUS      0x00200000
+
+#define AR_SLP32_WAKE              0x8248
+#define AR_SLP32_WAKE_XTL_TIME     0x0000FFFF
+
+#define AR_SLP32_INC               0x824c
+#define AR_SLP32_TST_INC           0x000FFFFF
+
+#define AR_SLP_CNT         0x8250
+#define AR_SLP_CYCLE_CNT   0x8254
+
+#define AR_SLP_MIB_CTRL    0x8258
+#define AR_SLP_MIB_CLEAR   0x00000001
+#define AR_SLP_MIB_PENDING 0x00000002
+
+#define AR_MAC_PCU_LOGIC_ANALYZER               0x8264
+#define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768   0x20000000
+
+
+#define AR_2040_MODE                0x8318
+#define AR_2040_JOINED_RX_CLEAR 0x00000001
+
+
+#define AR_EXTRCCNT         0x8328
+
+#define AR_SELFGEN_MASK         0x832c
+
+#define AR_PCU_TXBUF_CTRL               0x8340
+#define AR_PCU_TXBUF_CTRL_SIZE_MASK     0x7FF
+#define AR_PCU_TXBUF_CTRL_USABLE_SIZE   0x700
+#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE   0x380
+
+#define AR_PCU_MISC_MODE2               0x8344
+#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE           0x00000002
+#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT   0x00000004
+
+#define AR_PCU_MISC_MODE2_RESERVED                     0x00000038
+#define AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE     0x00000040
+#define AR_PCU_MISC_MODE2_CFP_IGNORE                   0x00000080
+#define AR_PCU_MISC_MODE2_MGMT_QOS                     0x0000FF00
+#define AR_PCU_MISC_MODE2_MGMT_QOS_S                   8
+#define AR_PCU_MISC_MODE2_ENABLE_LOAD_NAV_BEACON_DURATION 0x00010000
+#define AR_PCU_MISC_MODE2_ENABLE_AGGWEP                0x00020000
+#define AR_PCU_MISC_MODE2_HWWAR1                       0x00100000
+#define AR_PCU_MISC_MODE2_HWWAR2                       0x02000000
+#define AR_PCU_MISC_MODE2_RESERVED2                    0xFFFE0000
+
+#define AR_MAC_PCU_ASYNC_FIFO_REG3                     0x8358
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL                0x00000400
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET          0x80000000
+#define AR_MAC_PCU_GEN_TIMER_TSF_SEL                   0x83d8
+
+
+#define AR_AES_MUTE_MASK0       0x805c
+#define AR_AES_MUTE_MASK0_FC    0x0000FFFF
+#define AR_AES_MUTE_MASK0_QOS   0xFFFF0000
+#define AR_AES_MUTE_MASK0_QOS_S 16
+
+#define AR_AES_MUTE_MASK1              0x8060
+#define AR_AES_MUTE_MASK1_SEQ          0x0000FFFF
+#define AR_AES_MUTE_MASK1_SEQ_S        0
+#define AR_AES_MUTE_MASK1_FC_MGMT      0xFFFF0000
+#define AR_AES_MUTE_MASK1_FC_MGMT_S    16
+
+#define AR_RATE_DURATION_0      0x8700
+#define AR_RATE_DURATION_31     0x87CC
+#define AR_RATE_DURATION_32     0x8780
+#define AR_RATE_DURATION(_n)    (AR_RATE_DURATION_0 + ((_n)<<2))
+
+
+#define AR9271_CORE_CLOCK      117   /* clock to 117Mhz */
+#define AR9271_TARGET_BAUD_RATE        19200 /* 115200 */
+
+#define AR_AGG_WEP_ENABLE_FIX          0x00000008  /* This allows the use of AR_AGG_WEP_ENABLE */
+#define AR_ADHOC_MCAST_KEYID_ENABLE     0x00000040  /* This bit enables the Multicast search
+                                                    * based on both MAC Address and Key ID.
+                                                    * If bit is 0, then Multicast search is
+                                                    * based on MAC address only.
+                                                    * For Merlin and above only.
+                                                    */
+#define AR_AGG_WEP_ENABLE               0x00020000  /* This field enables AGG_WEP feature,
+                                                    * when it is enable, AGG_WEP would takes
+                                                    * charge of the encryption interface of
+                                                    * pcu_txsm.
+                                                    */
+
+#define AR9300_SM_BASE                         0xa200
+#define AR9002_PHY_AGC_CONTROL                 0x9860
+#define AR9003_PHY_AGC_CONTROL                 AR9300_SM_BASE + 0xc4
+#define AR_PHY_AGC_CONTROL                     (AR_SREV_9300_20_OR_LATER(ah) ? AR9003_PHY_AGC_CONTROL : AR9002_PHY_AGC_CONTROL)
+#define AR_PHY_AGC_CONTROL_CAL                 0x00000001  /* do internal calibration */
+#define AR_PHY_AGC_CONTROL_NF                  0x00000002  /* do noise-floor calibration */
+#define AR_PHY_AGC_CONTROL_OFFSET_CAL          0x00000800  /* allow offset calibration */
+#define AR_PHY_AGC_CONTROL_ENABLE_NF           0x00008000  /* enable noise floor calibration to happen */
+#define AR_PHY_AGC_CONTROL_FLTR_CAL            0x00010000  /* allow tx filter calibration */
+#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF                0x00020000  /* don't update noise floor automatically */
+#define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS     0x00040000  /* extend noise floor power measurement */
+#define AR_PHY_AGC_CONTROL_CLC_SUCCESS         0x00080000  /* carrier leak calibration done */
+#define AR_PHY_AGC_CONTROL_PKDET_CAL           0x00100000
+#define AR_PHY_AGC_CONTROL_YCOK_MAX            0x000003c0
+#define AR_PHY_AGC_CONTROL_YCOK_MAX_S          6
+
+/* MCI Registers */
+
+#define AR_MCI_COMMAND0                                0x1800
+#define AR_MCI_COMMAND0_HEADER                 0xFF
+#define AR_MCI_COMMAND0_HEADER_S               0
+#define AR_MCI_COMMAND0_LEN                    0x1f00
+#define AR_MCI_COMMAND0_LEN_S                  8
+#define AR_MCI_COMMAND0_DISABLE_TIMESTAMP      0x2000
+#define AR_MCI_COMMAND0_DISABLE_TIMESTAMP_S    13
+
+#define AR_MCI_COMMAND1                                0x1804
+
+#define AR_MCI_COMMAND2                                0x1808
+#define AR_MCI_COMMAND2_RESET_TX               0x01
+#define AR_MCI_COMMAND2_RESET_TX_S             0
+#define AR_MCI_COMMAND2_RESET_RX               0x02
+#define AR_MCI_COMMAND2_RESET_RX_S             1
+#define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES     0x3FC
+#define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES_S   2
+#define AR_MCI_COMMAND2_RESET_REQ_WAKEUP        0x400
+#define AR_MCI_COMMAND2_RESET_REQ_WAKEUP_S      10
+
+#define AR_MCI_RX_CTRL                         0x180c
+
+#define AR_MCI_TX_CTRL                         0x1810
+/* 0 = no division, 1 = divide by 2, 2 = divide by 4, 3 = divide by 8 */
+#define AR_MCI_TX_CTRL_CLK_DIV                 0x03
+#define AR_MCI_TX_CTRL_CLK_DIV_S               0
+#define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE      0x04
+#define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE_S    2
+#define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ                0xFFFFF8
+#define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ_S      3
+#define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM         0xF000000
+#define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM_S       24
+
+#define AR_MCI_MSG_ATTRIBUTES_TABLE                    0x1814
+#define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM           0xFFFF
+#define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM_S         0
+#define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR                0xFFFF0000
+#define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR_S      16
+
+#define AR_MCI_SCHD_TABLE_0                            0x1818
+#define AR_MCI_SCHD_TABLE_1                            0x181c
+#define AR_MCI_GPM_0                                   0x1820
+#define AR_MCI_GPM_1                                   0x1824
+#define AR_MCI_GPM_WRITE_PTR                           0xFFFF0000
+#define AR_MCI_GPM_WRITE_PTR_S                         16
+#define AR_MCI_GPM_BUF_LEN                             0x0000FFFF
+#define AR_MCI_GPM_BUF_LEN_S                           0
+
+#define AR_MCI_INTERRUPT_RAW                           0x1828
+#define AR_MCI_INTERRUPT_EN                            0x182c
+#define AR_MCI_INTERRUPT_SW_MSG_DONE                   0x00000001
+#define AR_MCI_INTERRUPT_SW_MSG_DONE_S                 0
+#define AR_MCI_INTERRUPT_CPU_INT_MSG                   0x00000002
+#define AR_MCI_INTERRUPT_CPU_INT_MSG_S                 1
+#define AR_MCI_INTERRUPT_RX_CKSUM_FAIL                 0x00000004
+#define AR_MCI_INTERRUPT_RX_CKSUM_FAIL_S               2
+#define AR_MCI_INTERRUPT_RX_INVALID_HDR                        0x00000008
+#define AR_MCI_INTERRUPT_RX_INVALID_HDR_S              3
+#define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL                        0x00000010
+#define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL_S              4
+#define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL                        0x00000020
+#define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL_S              5
+#define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL                        0x00000080
+#define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL_S              7
+#define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL                        0x00000100
+#define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL_S              8
+#define AR_MCI_INTERRUPT_RX_MSG                                0x00000200
+#define AR_MCI_INTERRUPT_RX_MSG_S                      9
+#define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE           0x00000400
+#define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE_S         10
+#define AR_MCI_INTERRUPT_BT_PRI                                0x07fff800
+#define AR_MCI_INTERRUPT_BT_PRI_S                      11
+#define AR_MCI_INTERRUPT_BT_PRI_THRESH                 0x08000000
+#define AR_MCI_INTERRUPT_BT_PRI_THRESH_S               27
+#define AR_MCI_INTERRUPT_BT_FREQ                       0x10000000
+#define AR_MCI_INTERRUPT_BT_FREQ_S                     28
+#define AR_MCI_INTERRUPT_BT_STOMP                      0x20000000
+#define AR_MCI_INTERRUPT_BT_STOMP_S                    29
+#define AR_MCI_INTERRUPT_BB_AIC_IRQ                    0x40000000
+#define AR_MCI_INTERRUPT_BB_AIC_IRQ_S                  30
+#define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT             0x80000000
+#define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT_S           31
+
+#define AR_MCI_INTERRUPT_DEFAULT    (AR_MCI_INTERRUPT_SW_MSG_DONE        | \
+                                    AR_MCI_INTERRUPT_RX_INVALID_HDR      | \
+                                    AR_MCI_INTERRUPT_RX_HW_MSG_FAIL      | \
+                                    AR_MCI_INTERRUPT_RX_SW_MSG_FAIL      | \
+                                    AR_MCI_INTERRUPT_TX_HW_MSG_FAIL      | \
+                                    AR_MCI_INTERRUPT_TX_SW_MSG_FAIL      | \
+                                    AR_MCI_INTERRUPT_RX_MSG              | \
+                                    AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE | \
+                                    AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)
+
+#define AR_MCI_INTERRUPT_MSG_FAIL_MASK (AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \
+                                       AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \
+                                       AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \
+                                       AR_MCI_INTERRUPT_TX_SW_MSG_FAIL)
+
+#define AR_MCI_REMOTE_CPU_INT                          0x1830
+#define AR_MCI_REMOTE_CPU_INT_EN                       0x1834
+#define AR_MCI_INTERRUPT_RX_MSG_RAW                    0x1838
+#define AR_MCI_INTERRUPT_RX_MSG_EN                     0x183c
+#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET           0x00000001
+#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S         0
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL            0x00000002
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S          1
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK              0x00000004
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S            2
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO              0x00000008
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S            3
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST               0x00000010
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S             4
+#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO              0x00000020
+#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S            5
+#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT                        0x00000040
+#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S              6
+#define AR_MCI_INTERRUPT_RX_MSG_GPM                    0x00000100
+#define AR_MCI_INTERRUPT_RX_MSG_GPM_S                  8
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO               0x00000200
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S             9
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING           0x00000400
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S         10
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING             0x00000800
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S           11
+#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE               0x00001000
+#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S             12
+#define AR_MCI_INTERRUPT_RX_HW_MSG_MASK         (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO  | \
+                                         AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL| \
+                                         AR_MCI_INTERRUPT_RX_MSG_LNA_INFO   | \
+                                         AR_MCI_INTERRUPT_RX_MSG_CONT_NACK  | \
+                                         AR_MCI_INTERRUPT_RX_MSG_CONT_INFO  | \
+                                         AR_MCI_INTERRUPT_RX_MSG_CONT_RST)
+
+#define AR_MCI_INTERRUPT_RX_MSG_DEFAULT (AR_MCI_INTERRUPT_RX_MSG_GPM    | \
+                                        AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET| \
+                                        AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING  | \
+                                        AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING| \
+                                        AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)
+
+#define AR_MCI_CPU_INT                                 0x1840
+
+#define AR_MCI_RX_STATUS                       0x1844
+#define AR_MCI_RX_LAST_SCHD_MSG_INDEX          0x00000F00
+#define AR_MCI_RX_LAST_SCHD_MSG_INDEX_S                8
+#define AR_MCI_RX_REMOTE_SLEEP                 0x00001000
+#define AR_MCI_RX_REMOTE_SLEEP_S               12
+#define AR_MCI_RX_MCI_CLK_REQ                  0x00002000
+#define AR_MCI_RX_MCI_CLK_REQ_S                        13
+
+#define AR_MCI_CONT_STATUS                     0x1848
+#define AR_MCI_CONT_RSSI_POWER                 0x000000FF
+#define AR_MCI_CONT_RSSI_POWER_S               0
+#define AR_MCI_CONT_PRIORITY                   0x0000FF00
+#define AR_MCI_CONT_PRIORITY_S                 8
+#define AR_MCI_CONT_TXRX                       0x00010000
+#define AR_MCI_CONT_TXRX_S                     16
+
+#define AR_MCI_BT_PRI0                         0x184c
+#define AR_MCI_BT_PRI1                         0x1850
+#define AR_MCI_BT_PRI2                         0x1854
+#define AR_MCI_BT_PRI3                         0x1858
+#define AR_MCI_BT_PRI                          0x185c
+#define AR_MCI_WL_FREQ0                                0x1860
+#define AR_MCI_WL_FREQ1                                0x1864
+#define AR_MCI_WL_FREQ2                                0x1868
+#define AR_MCI_GAIN                            0x186c
+#define AR_MCI_WBTIMER1                                0x1870
+#define AR_MCI_WBTIMER2                                0x1874
+#define AR_MCI_WBTIMER3                                0x1878
+#define AR_MCI_WBTIMER4                                0x187c
+#define AR_MCI_MAXGAIN                         0x1880
+#define AR_MCI_HW_SCHD_TBL_CTL                 0x1884
+#define AR_MCI_HW_SCHD_TBL_D0                  0x1888
+#define AR_MCI_HW_SCHD_TBL_D1                  0x188c
+#define AR_MCI_HW_SCHD_TBL_D2                  0x1890
+#define AR_MCI_HW_SCHD_TBL_D3                  0x1894
+#define AR_MCI_TX_PAYLOAD0                     0x1898
+#define AR_MCI_TX_PAYLOAD1                     0x189c
+#define AR_MCI_TX_PAYLOAD2                     0x18a0
+#define AR_MCI_TX_PAYLOAD3                     0x18a4
+#define AR_BTCOEX_WBTIMER                      0x18a8
+
+#define AR_BTCOEX_CTRL                                 0x18ac
+#define AR_BTCOEX_CTRL_AR9462_MODE                     0x00000001
+#define AR_BTCOEX_CTRL_AR9462_MODE_S                   0
+#define AR_BTCOEX_CTRL_WBTIMER_EN                      0x00000002
+#define AR_BTCOEX_CTRL_WBTIMER_EN_S                    1
+#define AR_BTCOEX_CTRL_MCI_MODE_EN                     0x00000004
+#define AR_BTCOEX_CTRL_MCI_MODE_EN_S                   2
+#define AR_BTCOEX_CTRL_LNA_SHARED                      0x00000008
+#define AR_BTCOEX_CTRL_LNA_SHARED_S                    3
+#define AR_BTCOEX_CTRL_PA_SHARED                       0x00000010
+#define AR_BTCOEX_CTRL_PA_SHARED_S                     4
+#define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN          0x00000020
+#define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN_S                5
+#define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN       0x00000040
+#define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN_S     6
+#define AR_BTCOEX_CTRL_NUM_ANTENNAS                    0x00000180
+#define AR_BTCOEX_CTRL_NUM_ANTENNAS_S                  7
+#define AR_BTCOEX_CTRL_RX_CHAIN_MASK                   0x00000E00
+#define AR_BTCOEX_CTRL_RX_CHAIN_MASK_S                 9
+#define AR_BTCOEX_CTRL_AGGR_THRESH                     0x00007000
+#define AR_BTCOEX_CTRL_AGGR_THRESH_S                   12
+#define AR_BTCOEX_CTRL_1_CHAIN_BCN                     0x00080000
+#define AR_BTCOEX_CTRL_1_CHAIN_BCN_S                   19
+#define AR_BTCOEX_CTRL_1_CHAIN_ACK                     0x00100000
+#define AR_BTCOEX_CTRL_1_CHAIN_ACK_S                   20
+#define AR_BTCOEX_CTRL_WAIT_BA_MARGIN                  0x1FE00000
+#define AR_BTCOEX_CTRL_WAIT_BA_MARGIN_S                        28
+#define AR_BTCOEX_CTRL_REDUCE_TXPWR                    0x20000000
+#define AR_BTCOEX_CTRL_REDUCE_TXPWR_S                  29
+#define AR_BTCOEX_CTRL_SPDT_ENABLE_10                  0x40000000
+#define AR_BTCOEX_CTRL_SPDT_ENABLE_10_S                        30
+#define AR_BTCOEX_CTRL_SPDT_POLARITY                   0x80000000
+#define AR_BTCOEX_CTRL_SPDT_POLARITY_S                 31
+
+#define AR_BTCOEX_MAX_TXPWR(_x)                                (0x18c0 + ((_x) << 2))
+#define AR_BTCOEX_WL_LNA                               0x1940
+#define AR_BTCOEX_RFGAIN_CTRL                          0x1944
+
+#define AR_BTCOEX_CTRL2                                        0x1948
+#define AR_BTCOEX_CTRL2_TXPWR_THRESH                   0x0007F800
+#define AR_BTCOEX_CTRL2_TXPWR_THRESH_S                 11
+#define AR_BTCOEX_CTRL2_TX_CHAIN_MASK                  0x00380000
+#define AR_BTCOEX_CTRL2_TX_CHAIN_MASK_S                        19
+#define AR_BTCOEX_CTRL2_RX_DEWEIGHT                    0x00400000
+#define AR_BTCOEX_CTRL2_RX_DEWEIGHT_S                  22
+#define AR_BTCOEX_CTRL2_GPIO_OBS_SEL                   0x00800000
+#define AR_BTCOEX_CTRL2_GPIO_OBS_SEL_S                 23
+#define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL                 0x01000000
+#define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL_S               24
+#define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE                0x02000000
+#define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE_S      25
+
+#define AR_BTCOEX_CTRL_SPDT_ENABLE          0x00000001
+#define AR_BTCOEX_CTRL_SPDT_ENABLE_S        0
+#define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL     0x00000002
+#define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL_S   1
+#define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT   0x00000004
+#define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT_S 2
+#define AR_GLB_WLAN_UART_INTF_EN            0x00020000
+#define AR_GLB_WLAN_UART_INTF_EN_S          17
+#define AR_GLB_DS_JTAG_DISABLE              0x00040000
+#define AR_GLB_DS_JTAG_DISABLE_S            18
+
+#define AR_BTCOEX_RC                    0x194c
+#define AR_BTCOEX_MAX_RFGAIN(_x)        (0x1950 + ((_x) << 2))
+#define AR_BTCOEX_DBG                   0x1a50
+#define AR_MCI_LAST_HW_MSG_HDR          0x1a54
+#define AR_MCI_LAST_HW_MSG_BDY          0x1a58
+
+#define AR_MCI_SCHD_TABLE_2             0x1a5c
+#define AR_MCI_SCHD_TABLE_2_MEM_BASED   0x00000001
+#define AR_MCI_SCHD_TABLE_2_MEM_BASED_S 0
+#define AR_MCI_SCHD_TABLE_2_HW_BASED    0x00000002
+#define AR_MCI_SCHD_TABLE_2_HW_BASED_S  1
+
+#define AR_BTCOEX_CTRL3               0x1a60
+#define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT      0x00000fff
+#define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT_S    0
+
+#define AR_GLB_SWREG_DISCONT_MODE         0x2002c
+#define AR_GLB_SWREG_DISCONT_EN_BT_WLAN   0x3
+
+#endif
diff --git a/drivers/net/wireless/ath/ath9k_btcoex/xmit.c b/drivers/net/wireless/ath/ath9k_btcoex/xmit.c
new file mode 100644 (file)
index 0000000..ff0b786
--- /dev/null
@@ -0,0 +1,2509 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/dma-mapping.h>
+#include "ath9k.h"
+#include "ar9003_mac.h"
+
+#define BITS_PER_BYTE           8
+#define OFDM_PLCP_BITS          22
+#define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
+#define L_STF                   8
+#define L_LTF                   8
+#define L_SIG                   4
+#define HT_SIG                  8
+#define HT_STF                  4
+#define HT_LTF(_ns)             (4 * (_ns))
+#define SYMBOL_TIME(_ns)        ((_ns) << 2) /* ns * 4 us */
+#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5)  /* ns * 3.6 us */
+#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
+#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
+
+
+static u16 bits_per_symbol[][2] = {
+       /* 20MHz 40MHz */
+       {    26,   54 },     /*  0: BPSK */
+       {    52,  108 },     /*  1: QPSK 1/2 */
+       {    78,  162 },     /*  2: QPSK 3/4 */
+       {   104,  216 },     /*  3: 16-QAM 1/2 */
+       {   156,  324 },     /*  4: 16-QAM 3/4 */
+       {   208,  432 },     /*  5: 64-QAM 2/3 */
+       {   234,  486 },     /*  6: 64-QAM 3/4 */
+       {   260,  540 },     /*  7: 64-QAM 5/6 */
+};
+
+#define IS_HT_RATE(_rate)     ((_rate) & 0x80)
+
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+                              struct ath_atx_tid *tid, struct sk_buff *skb);
+static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+                           int tx_flags, struct ath_txq *txq);
+static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+                               struct ath_txq *txq, struct list_head *bf_q,
+                               struct ath_tx_status *ts, int txok);
+static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+                            struct list_head *head, bool internal);
+static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+                            struct ath_tx_status *ts, int nframes, int nbad,
+                            int txok);
+static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+                             int seqno);
+static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+                                          struct ath_txq *txq,
+                                          struct ath_atx_tid *tid,
+                                          struct sk_buff *skb,
+                                          bool dequeue);
+
+enum {
+       MCS_HT20,
+       MCS_HT20_SGI,
+       MCS_HT40,
+       MCS_HT40_SGI,
+};
+
+static int ath_max_4ms_framelen[4][32] = {
+       [MCS_HT20] = {
+               3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
+               6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
+               9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
+               12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
+       },
+       [MCS_HT20_SGI] = {
+               3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
+               7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
+               10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
+               14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
+       },
+       [MCS_HT40] = {
+               6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
+               13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
+               20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
+               26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
+       },
+       [MCS_HT40_SGI] = {
+               7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
+               14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
+               22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
+               29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
+       }
+};
+
+/*********************/
+/* Aggregation logic */
+/*********************/
+
+static void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
+       __acquires(&txq->axq_lock)
+{
+       spin_lock_bh(&txq->axq_lock);
+}
+
+static void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
+       __releases(&txq->axq_lock)
+{
+       spin_unlock_bh(&txq->axq_lock);
+}
+
+static void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
+       __releases(&txq->axq_lock)
+{
+       struct sk_buff_head q;
+       struct sk_buff *skb;
+
+       __skb_queue_head_init(&q);
+       skb_queue_splice_init(&txq->complete_q, &q);
+       spin_unlock_bh(&txq->axq_lock);
+
+       while ((skb = __skb_dequeue(&q)))
+               ieee80211_tx_status(sc->hw, skb);
+}
+
+static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
+{
+       struct ath_atx_ac *ac = tid->ac;
+
+       if (tid->paused)
+               return;
+
+       if (tid->sched)
+               return;
+
+       tid->sched = true;
+       list_add_tail(&tid->list, &ac->tid_q);
+
+       if (ac->sched)
+               return;
+
+       ac->sched = true;
+       list_add_tail(&ac->list, &txq->axq_acq);
+}
+
+static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+{
+       struct ath_txq *txq = tid->ac->txq;
+
+       WARN_ON(!tid->paused);
+
+       ath_txq_lock(sc, txq);
+       tid->paused = false;
+
+       if (skb_queue_empty(&tid->buf_q))
+               goto unlock;
+
+       ath_tx_queue_tid(txq, tid);
+       ath_txq_schedule(sc, txq);
+unlock:
+       ath_txq_unlock_complete(sc, txq);
+}
+
+static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       BUILD_BUG_ON(sizeof(struct ath_frame_info) >
+                    sizeof(tx_info->rate_driver_data));
+       return (struct ath_frame_info *) &tx_info->rate_driver_data[0];
+}
+
+static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
+{
+       ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno,
+                          seqno << IEEE80211_SEQ_SEQ_SHIFT);
+}
+
+static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+{
+       struct ath_txq *txq = tid->ac->txq;
+       struct sk_buff *skb;
+       struct ath_buf *bf;
+       struct list_head bf_head;
+       struct ath_tx_status ts;
+       struct ath_frame_info *fi;
+       bool sendbar = false;
+
+       INIT_LIST_HEAD(&bf_head);
+
+       memset(&ts, 0, sizeof(ts));
+
+       while ((skb = __skb_dequeue(&tid->buf_q))) {
+               fi = get_frame_info(skb);
+               bf = fi->bf;
+
+               if (bf && fi->retries) {
+                       list_add_tail(&bf->list, &bf_head);
+                       ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+                       sendbar = true;
+               } else {
+                       ath_tx_send_normal(sc, txq, NULL, skb);
+               }
+       }
+
+       if (tid->baw_head == tid->baw_tail) {
+               tid->state &= ~AGGR_ADDBA_COMPLETE;
+               tid->state &= ~AGGR_CLEANUP;
+       }
+
+       if (sendbar) {
+               ath_txq_unlock(sc, txq);
+               ath_send_bar(tid, tid->seq_start);
+               ath_txq_lock(sc, txq);
+       }
+}
+
+static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+                             int seqno)
+{
+       int index, cindex;
+
+       index  = ATH_BA_INDEX(tid->seq_start, seqno);
+       cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
+
+       __clear_bit(cindex, tid->tx_buf);
+
+       while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) {
+               INCR(tid->seq_start, IEEE80211_SEQ_MAX);
+               INCR(tid->baw_head, ATH_TID_MAX_BUFS);
+               if (tid->bar_index >= 0)
+                       tid->bar_index--;
+       }
+}
+
+static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+                            u16 seqno)
+{
+       int index, cindex;
+
+       index  = ATH_BA_INDEX(tid->seq_start, seqno);
+       cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
+       __set_bit(cindex, tid->tx_buf);
+
+       if (index >= ((tid->baw_tail - tid->baw_head) &
+               (ATH_TID_MAX_BUFS - 1))) {
+               tid->baw_tail = cindex;
+               INCR(tid->baw_tail, ATH_TID_MAX_BUFS);
+       }
+}
+
+/*
+ * TODO: For frame(s) that are in the retry state, we will reuse the
+ * sequence number(s) without setting the retry bit. The
+ * alternative is to give up on these and BAR the receiver's window
+ * forward.
+ */
+static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
+                         struct ath_atx_tid *tid)
+
+{
+       struct sk_buff *skb;
+       struct ath_buf *bf;
+       struct list_head bf_head;
+       struct ath_tx_status ts;
+       struct ath_frame_info *fi;
+
+       memset(&ts, 0, sizeof(ts));
+       INIT_LIST_HEAD(&bf_head);
+
+       while ((skb = __skb_dequeue(&tid->buf_q))) {
+               fi = get_frame_info(skb);
+               bf = fi->bf;
+
+               if (!bf) {
+                       ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
+                       continue;
+               }
+
+               list_add_tail(&bf->list, &bf_head);
+
+               if (fi->retries)
+                       ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
+
+               ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+       }
+
+       tid->seq_next = tid->seq_start;
+       tid->baw_tail = tid->baw_head;
+       tid->bar_index = -1;
+}
+
+static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
+                            struct sk_buff *skb, int count)
+{
+       struct ath_frame_info *fi = get_frame_info(skb);
+       struct ath_buf *bf = fi->bf;
+       struct ieee80211_hdr *hdr;
+       int prev = fi->retries;
+
+       TX_STAT_INC(txq->axq_qnum, a_retries);
+       fi->retries += count;
+
+       if (prev > 0)
+               return;
+
+       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
+       dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+               sizeof(*hdr), DMA_TO_DEVICE);
+}
+
+static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
+{
+       struct ath_buf *bf = NULL;
+
+       spin_lock_bh(&sc->tx.txbuflock);
+
+       if (unlikely(list_empty(&sc->tx.txbuf))) {
+               spin_unlock_bh(&sc->tx.txbuflock);
+               return NULL;
+       }
+
+       bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+       list_del(&bf->list);
+
+       spin_unlock_bh(&sc->tx.txbuflock);
+
+       return bf;
+}
+
+static void ath_tx_return_buffer(struct ath_softc *sc, struct ath_buf *bf)
+{
+       spin_lock_bh(&sc->tx.txbuflock);
+       list_add_tail(&bf->list, &sc->tx.txbuf);
+       spin_unlock_bh(&sc->tx.txbuflock);
+}
+
+static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
+{
+       struct ath_buf *tbf;
+
+       tbf = ath_tx_get_buffer(sc);
+       if (WARN_ON(!tbf))
+               return NULL;
+
+       ATH_TXBUF_RESET(tbf);
+
+       tbf->bf_mpdu = bf->bf_mpdu;
+       tbf->bf_buf_addr = bf->bf_buf_addr;
+       memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
+       tbf->bf_state = bf->bf_state;
+
+       return tbf;
+}
+
+static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
+                               struct ath_tx_status *ts, int txok,
+                               int *nframes, int *nbad)
+{
+       struct ath_frame_info *fi;
+       u16 seq_st = 0;
+       u32 ba[WME_BA_BMP_SIZE >> 5];
+       int ba_index;
+       int isaggr = 0;
+
+       *nbad = 0;
+       *nframes = 0;
+
+       isaggr = bf_isaggr(bf);
+       if (isaggr) {
+               seq_st = ts->ts_seqnum;
+               memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
+       }
+
+       while (bf) {
+               fi = get_frame_info(bf->bf_mpdu);
+               ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno);
+
+               (*nframes)++;
+               if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
+                       (*nbad)++;
+
+               bf = bf->bf_next;
+       }
+}
+
+
+static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
+                                struct ath_buf *bf, struct list_head *bf_q,
+                                struct ath_tx_status *ts, int txok, bool retry)
+{
+       struct ath_node *an = NULL;
+       struct sk_buff *skb;
+       struct ieee80211_sta *sta;
+       struct ieee80211_hw *hw = sc->hw;
+       struct ieee80211_hdr *hdr;
+       struct ieee80211_tx_info *tx_info;
+       struct ath_atx_tid *tid = NULL;
+       struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
+       struct list_head bf_head;
+       struct sk_buff_head bf_pending;
+       u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
+       u32 ba[WME_BA_BMP_SIZE >> 5];
+       int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
+       bool rc_update = true;
+       struct ieee80211_tx_rate rates[4];
+       struct ath_frame_info *fi;
+       int nframes;
+       u8 tidno;
+       bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
+       int i, retries;
+       int bar_index = -1;
+
+       skb = bf->bf_mpdu;
+       hdr = (struct ieee80211_hdr *)skb->data;
+
+       tx_info = IEEE80211_SKB_CB(skb);
+
+       memcpy(rates, tx_info->control.rates, sizeof(rates));
+
+       retries = ts->ts_longretry + 1;
+       for (i = 0; i < ts->ts_rateindex; i++)
+               retries += rates[i].count;
+
+       rcu_read_lock();
+
+       sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
+       if (!sta) {
+               rcu_read_unlock();
+
+               INIT_LIST_HEAD(&bf_head);
+               while (bf) {
+                       bf_next = bf->bf_next;
+
+                       if (!bf->bf_stale || bf_next != NULL)
+                               list_move_tail(&bf->list, &bf_head);
+
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0);
+
+                       bf = bf_next;
+               }
+               return;
+       }
+
+       an = (struct ath_node *)sta->drv_priv;
+       tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
+       tid = ATH_AN_2_TID(an, tidno);
+       seq_first = tid->seq_start;
+
+       /*
+        * The hardware occasionally sends a tx status for the wrong TID.
+        * In this case, the BA status cannot be considered valid and all
+        * subframes need to be retransmitted
+        */
+       if (tidno != ts->tid)
+               txok = false;
+
+       isaggr = bf_isaggr(bf);
+       memset(ba, 0, WME_BA_BMP_SIZE >> 3);
+
+       if (isaggr && txok) {
+               if (ts->ts_flags & ATH9K_TX_BA) {
+                       seq_st = ts->ts_seqnum;
+                       memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
+               } else {
+                       /*
+                        * AR5416 can become deaf/mute when BA
+                        * issue happens. Chip needs to be reset.
+                        * But AP code may have sychronization issues
+                        * when perform internal reset in this routine.
+                        * Only enable reset in STA mode for now.
+                        */
+                       if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION)
+                               needreset = 1;
+               }
+       }
+
+       __skb_queue_head_init(&bf_pending);
+
+       ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
+       while (bf) {
+               u16 seqno = bf->bf_state.seqno;
+
+               txfail = txpending = sendbar = 0;
+               bf_next = bf->bf_next;
+
+               skb = bf->bf_mpdu;
+               tx_info = IEEE80211_SKB_CB(skb);
+               fi = get_frame_info(skb);
+
+               if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
+                       /* transmit completion, subframe is
+                        * acked by block ack */
+                       acked_cnt++;
+               } else if (!isaggr && txok) {
+                       /* transmit completion */
+                       acked_cnt++;
+               } else if ((tid->state & AGGR_CLEANUP) || !retry) {
+                       /*
+                        * cleanup in progress, just fail
+                        * the un-acked sub-frames
+                        */
+                       txfail = 1;
+               } else if (flush) {
+                       txpending = 1;
+               } else if (fi->retries < ATH_MAX_SW_RETRIES) {
+                       if (txok || !an->sleeping)
+                               ath_tx_set_retry(sc, txq, bf->bf_mpdu,
+                                                retries);
+
+                       txpending = 1;
+               } else {
+                       txfail = 1;
+                       txfail_cnt++;
+                       bar_index = max_t(int, bar_index,
+                               ATH_BA_INDEX(seq_first, seqno));
+               }
+
+               /*
+                * Make sure the last desc is reclaimed if it
+                * not a holding desc.
+                */
+               INIT_LIST_HEAD(&bf_head);
+               if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
+                   bf_next != NULL || !bf_last->bf_stale)
+                       list_move_tail(&bf->list, &bf_head);
+
+               if (!txpending || (tid->state & AGGR_CLEANUP)) {
+                       /*
+                        * complete the acked-ones/xretried ones; update
+                        * block-ack window
+                        */
+                       ath_tx_update_baw(sc, tid, seqno);
+
+                       if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
+                               memcpy(tx_info->control.rates, rates, sizeof(rates));
+                               ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok);
+                               rc_update = false;
+                       }
+
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+                               !txfail);
+               } else {
+                       /* retry the un-acked ones */
+                       if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
+                           bf->bf_next == NULL && bf_last->bf_stale) {
+                               struct ath_buf *tbf;
+
+                               tbf = ath_clone_txbuf(sc, bf_last);
+                               /*
+                                * Update tx baw and complete the
+                                * frame with failed status if we
+                                * run out of tx buf.
+                                */
+                               if (!tbf) {
+                                       ath_tx_update_baw(sc, tid, seqno);
+
+                                       ath_tx_complete_buf(sc, bf, txq,
+                                                           &bf_head, ts, 0);
+                                       bar_index = max_t(int, bar_index,
+                                               ATH_BA_INDEX(seq_first, seqno));
+                                       break;
+                               }
+
+                               fi->bf = tbf;
+                       }
+
+                       /*
+                        * Put this buffer to the temporary pending
+                        * queue to retain ordering
+                        */
+                       __skb_queue_tail(&bf_pending, skb);
+               }
+
+               bf = bf_next;
+       }
+
+       /* prepend un-acked frames to the beginning of the pending frame queue */
+       if (!skb_queue_empty(&bf_pending)) {
+               if (an->sleeping)
+                       ieee80211_sta_set_buffered(sta, tid->tidno, true);
+
+               skb_queue_splice(&bf_pending, &tid->buf_q);
+               if (!an->sleeping) {
+                       ath_tx_queue_tid(txq, tid);
+
+                       if (ts->ts_status & ATH9K_TXERR_FILT)
+                               tid->ac->clear_ps_filter = true;
+               }
+       }
+
+       if (bar_index >= 0) {
+               u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
+
+               if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
+                       tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
+
+               ath_txq_unlock(sc, txq);
+               ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
+               ath_txq_lock(sc, txq);
+       }
+
+       if (tid->state & AGGR_CLEANUP)
+               ath_tx_flush_tid(sc, tid);
+
+       rcu_read_unlock();
+
+       if (needreset) {
+               RESET_STAT_INC(sc, RESET_TYPE_TX_ERROR);
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+       }
+}
+
+static bool ath_lookup_legacy(struct ath_buf *bf)
+{
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *tx_info;
+       struct ieee80211_tx_rate *rates;
+       int i;
+
+       skb = bf->bf_mpdu;
+       tx_info = IEEE80211_SKB_CB(skb);
+       rates = tx_info->control.rates;
+
+       for (i = 0; i < 4; i++) {
+               if (!rates[i].count || rates[i].idx < 0)
+                       break;
+
+               if (!(rates[i].flags & IEEE80211_TX_RC_MCS))
+                       return true;
+       }
+
+       return false;
+}
+
+static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
+                          struct ath_atx_tid *tid)
+{
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *tx_info;
+       struct ieee80211_tx_rate *rates;
+       u32 max_4ms_framelen, frmlen;
+       u16 aggr_limit, bt_aggr_limit, legacy = 0;
+       int i;
+
+       skb = bf->bf_mpdu;
+       tx_info = IEEE80211_SKB_CB(skb);
+       rates = tx_info->control.rates;
+
+       /*
+        * Find the lowest frame length among the rate series that will have a
+        * 4ms transmit duration.
+        * TODO - TXOP limit needs to be considered.
+        */
+       max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
+
+       for (i = 0; i < 4; i++) {
+               int modeidx;
+
+               if (!rates[i].count)
+                       continue;
+
+               if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) {
+                       legacy = 1;
+                       break;
+               }
+
+               if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+                       modeidx = MCS_HT40;
+               else
+                       modeidx = MCS_HT20;
+
+               if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
+                       modeidx++;
+
+               frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
+               max_4ms_framelen = min(max_4ms_framelen, frmlen);
+       }
+
+       /*
+        * limit aggregate size by the minimum rate if rate selected is
+        * not a probe rate, if rate selected is a probe rate then
+        * avoid aggregation of this packet.
+        */
+       if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
+               return 0;
+
+       aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_MAX);
+
+       /*
+        * Override the default aggregation limit for BTCOEX.
+        */
+       bt_aggr_limit = ath9k_btcoex_aggr_limit(sc, max_4ms_framelen);
+       if (bt_aggr_limit)
+               aggr_limit = bt_aggr_limit;
+
+       /*
+        * h/w can accept aggregates up to 16 bit lengths (65535).
+        * The IE, however can hold up to 65536, which shows up here
+        * as zero. Ignore 65536 since we  are constrained by hw.
+        */
+       if (tid->an->maxampdu)
+               aggr_limit = min(aggr_limit, tid->an->maxampdu);
+
+       return aggr_limit;
+}
+
+/*
+ * Returns the number of delimiters to be added to
+ * meet the minimum required mpdudensity.
+ */
+static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
+                                 struct ath_buf *bf, u16 frmlen,
+                                 bool first_subfrm)
+{
+#define FIRST_DESC_NDELIMS 60
+       struct sk_buff *skb = bf->bf_mpdu;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       u32 nsymbits, nsymbols;
+       u16 minlen;
+       u8 flags, rix;
+       int width, streams, half_gi, ndelim, mindelim;
+       struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
+
+       /* Select standard number of delimiters based on frame length alone */
+       ndelim = ATH_AGGR_GET_NDELIM(frmlen);
+
+       /*
+        * If encryption enabled, hardware requires some more padding between
+        * subframes.
+        * TODO - this could be improved to be dependent on the rate.
+        *      The hardware can keep up at lower rates, but not higher rates
+        */
+       if ((fi->keyix != ATH9K_TXKEYIX_INVALID) &&
+           !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))
+               ndelim += ATH_AGGR_ENCRYPTDELIM;
+
+       /*
+        * Add delimiter when using RTS/CTS with aggregation
+        * and non enterprise AR9003 card
+        */
+       if (first_subfrm && !AR_SREV_9580_10_OR_LATER(sc->sc_ah) &&
+           (sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE))
+               ndelim = max(ndelim, FIRST_DESC_NDELIMS);
+
+       /*
+        * Convert desired mpdu density from microeconds to bytes based
+        * on highest rate in rate series (i.e. first rate) to determine
+        * required minimum length for subframe. Take into account
+        * whether high rate is 20 or 40Mhz and half or full GI.
+        *
+        * If there is no mpdu density restriction, no further calculation
+        * is needed.
+        */
+
+       if (tid->an->mpdudensity == 0)
+               return ndelim;
+
+       rix = tx_info->control.rates[0].idx;
+       flags = tx_info->control.rates[0].flags;
+       width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
+       half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
+
+       if (half_gi)
+               nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(tid->an->mpdudensity);
+       else
+               nsymbols = NUM_SYMBOLS_PER_USEC(tid->an->mpdudensity);
+
+       if (nsymbols == 0)
+               nsymbols = 1;
+
+       streams = HT_RC_2_STREAMS(rix);
+       nsymbits = bits_per_symbol[rix % 8][width] * streams;
+       minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
+
+       if (frmlen < minlen) {
+               mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ;
+               ndelim = max(mindelim, ndelim);
+       }
+
+       return ndelim;
+}
+
+static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
+                                            struct ath_txq *txq,
+                                            struct ath_atx_tid *tid,
+                                            struct list_head *bf_q,
+                                            int *aggr_len)
+{
+#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
+       struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
+       int rl = 0, nframes = 0, ndelim, prev_al = 0;
+       u16 aggr_limit = 0, al = 0, bpad = 0,
+               al_delta, h_baw = tid->baw_size / 2;
+       enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
+       struct ieee80211_tx_info *tx_info;
+       struct ath_frame_info *fi;
+       struct sk_buff *skb;
+       u16 seqno;
+
+       do {
+               skb = skb_peek(&tid->buf_q);
+               fi = get_frame_info(skb);
+               bf = fi->bf;
+               if (!fi->bf)
+                       bf = ath_tx_setup_buffer(sc, txq, tid, skb, true);
+
+               if (!bf)
+                       continue;
+
+               bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
+               seqno = bf->bf_state.seqno;
+
+               /* do not step over block-ack window */
+               if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
+                       status = ATH_AGGR_BAW_CLOSED;
+                       break;
+               }
+
+               if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
+                       struct ath_tx_status ts = {};
+                       struct list_head bf_head;
+
+                       INIT_LIST_HEAD(&bf_head);
+                       list_add(&bf->list, &bf_head);
+                       __skb_unlink(skb, &tid->buf_q);
+                       ath_tx_update_baw(sc, tid, seqno);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+                       continue;
+               }
+
+               if (!bf_first)
+                       bf_first = bf;
+
+               if (!rl) {
+                       aggr_limit = ath_lookup_rate(sc, bf, tid);
+                       rl = 1;
+               }
+
+               /* do not exceed aggregation limit */
+               al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;
+
+               if (nframes &&
+                   ((aggr_limit < (al + bpad + al_delta + prev_al)) ||
+                    ath_lookup_legacy(bf))) {
+                       status = ATH_AGGR_LIMITED;
+                       break;
+               }
+
+               tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
+               if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
+                       break;
+
+               /* do not exceed subframe limit */
+               if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
+                       status = ATH_AGGR_LIMITED;
+                       break;
+               }
+
+               /* add padding for previous frame to aggregation length */
+               al += bpad + al_delta;
+
+               /*
+                * Get the delimiters needed to meet the MPDU
+                * density for this node.
+                */
+               ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen,
+                                               !nframes);
+               bpad = PADBYTES(al_delta) + (ndelim << 2);
+
+               nframes++;
+               bf->bf_next = NULL;
+
+               /* link buffers of this frame to the aggregate */
+               if (!fi->retries)
+                       ath_tx_addto_baw(sc, tid, seqno);
+               bf->bf_state.ndelim = ndelim;
+
+               __skb_unlink(skb, &tid->buf_q);
+               list_add_tail(&bf->list, bf_q);
+               if (bf_prev)
+                       bf_prev->bf_next = bf;
+
+               bf_prev = bf;
+
+       } while (!skb_queue_empty(&tid->buf_q));
+
+       *aggr_len = al;
+
+       return status;
+#undef PADBYTES
+}
+
+/*
+ * rix - rate index
+ * pktlen - total bytes (delims + data + fcs + pads + pad delims)
+ * width  - 0 for 20 MHz, 1 for 40 MHz
+ * half_gi - to use 4us v/s 3.6 us for symbol time
+ */
+static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
+                           int width, int half_gi, bool shortPreamble)
+{
+       u32 nbits, nsymbits, duration, nsymbols;
+       int streams;
+
+       /* find number of symbols: PLCP + data */
+       streams = HT_RC_2_STREAMS(rix);
+       nbits = (pktlen << 3) + OFDM_PLCP_BITS;
+       nsymbits = bits_per_symbol[rix % 8][width] * streams;
+       nsymbols = (nbits + nsymbits - 1) / nsymbits;
+
+       if (!half_gi)
+               duration = SYMBOL_TIME(nsymbols);
+       else
+               duration = SYMBOL_TIME_HALFGI(nsymbols);
+
+       /* addup duration for legacy/ht training and signal fields */
+       duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
+
+       return duration;
+}
+
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
+                            struct ath_tx_info *info, int len)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *tx_info;
+       struct ieee80211_tx_rate *rates;
+       const struct ieee80211_rate *rate;
+       struct ieee80211_hdr *hdr;
+       struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
+       int i;
+       u8 rix = 0;
+
+       skb = bf->bf_mpdu;
+       tx_info = IEEE80211_SKB_CB(skb);
+       rates = tx_info->control.rates;
+       hdr = (struct ieee80211_hdr *)skb->data;
+
+       /* set dur_update_en for l-sig computation except for PS-Poll frames */
+       info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
+       info->rtscts_rate = fi->rtscts_rate;
+
+       for (i = 0; i < 4; i++) {
+               bool is_40, is_sgi, is_sp;
+               int phy;
+
+               if (!rates[i].count || (rates[i].idx < 0))
+                       continue;
+
+               rix = rates[i].idx;
+               info->rates[i].Tries = rates[i].count;
+
+                   if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+                       info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+                       info->flags |= ATH9K_TXDESC_RTSENA;
+               } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+                       info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+                       info->flags |= ATH9K_TXDESC_CTSENA;
+               }
+
+               if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+                       info->rates[i].RateFlags |= ATH9K_RATESERIES_2040;
+               if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
+                       info->rates[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
+
+               is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
+               is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
+               is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
+
+               if (rates[i].flags & IEEE80211_TX_RC_MCS) {
+                       /* MCS rates */
+                       info->rates[i].Rate = rix | 0x80;
+                       info->rates[i].ChSel = ath_txchainmask_reduction(sc,
+                                       ah->txchainmask, info->rates[i].Rate);
+                       info->rates[i].PktDuration = ath_pkt_duration(sc, rix, len,
+                                is_40, is_sgi, is_sp);
+                       if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
+                               info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
+                       continue;
+               }
+
+               /* legacy rates */
+               rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
+               if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
+                   !(rate->flags & IEEE80211_RATE_ERP_G))
+                       phy = WLAN_RC_PHY_CCK;
+               else
+                       phy = WLAN_RC_PHY_OFDM;
+
+               info->rates[i].Rate = rate->hw_value;
+               if (rate->hw_value_short) {
+                       if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+                               info->rates[i].Rate |= rate->hw_value_short;
+               } else {
+                       is_sp = false;
+               }
+
+               if (bf->bf_state.bfs_paprd)
+                       info->rates[i].ChSel = ah->txchainmask;
+               else
+                       info->rates[i].ChSel = ath_txchainmask_reduction(sc,
+                                       ah->txchainmask, info->rates[i].Rate);
+
+               info->rates[i].PktDuration = ath9k_btcoex_ath9k_hw_computetxtime(sc->sc_ah,
+                       phy, rate->bitrate * 100, len, rix, is_sp);
+       }
+
+       /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
+       if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
+               info->flags &= ~ATH9K_TXDESC_RTSENA;
+
+       /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
+       if (info->flags & ATH9K_TXDESC_RTSENA)
+               info->flags &= ~ATH9K_TXDESC_CTSENA;
+}
+
+static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr;
+       enum ath9k_pkt_type htype;
+       __le16 fc;
+
+       hdr = (struct ieee80211_hdr *)skb->data;
+       fc = hdr->frame_control;
+
+       if (ieee80211_is_beacon(fc))
+               htype = ATH9K_PKT_TYPE_BEACON;
+       else if (ieee80211_is_probe_resp(fc))
+               htype = ATH9K_PKT_TYPE_PROBE_RESP;
+       else if (ieee80211_is_atim(fc))
+               htype = ATH9K_PKT_TYPE_ATIM;
+       else if (ieee80211_is_pspoll(fc))
+               htype = ATH9K_PKT_TYPE_PSPOLL;
+       else
+               htype = ATH9K_PKT_TYPE_NORMAL;
+
+       return htype;
+}
+
+static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
+                            struct ath_txq *txq, int len)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
+       struct ath_buf *bf_first = bf;
+       struct ath_tx_info info;
+       bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR);
+
+       memset(&info, 0, sizeof(info));
+       info.is_first = true;
+       info.is_last = true;
+       info.txpower = MAX_RATE_POWER;
+       info.qcu = txq->axq_qnum;
+
+       info.flags = ATH9K_TXDESC_INTREQ;
+       if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
+               info.flags |= ATH9K_TXDESC_NOACK;
+       if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
+               info.flags |= ATH9K_TXDESC_LDPC;
+
+       ath_buf_set_rate(sc, bf, &info, len);
+
+       if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
+               info.flags |= ATH9K_TXDESC_CLRDMASK;
+
+       if (bf->bf_state.bfs_paprd)
+               info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S;
+
+
+       while (bf) {
+               struct sk_buff *skb = bf->bf_mpdu;
+               struct ath_frame_info *fi = get_frame_info(skb);
+
+               info.type = get_hw_packet_type(skb);
+               if (bf->bf_next)
+                       info.link = bf->bf_next->bf_daddr;
+               else
+                       info.link = 0;
+
+               info.buf_addr[0] = bf->bf_buf_addr;
+               info.buf_len[0] = skb->len;
+               info.pkt_len = fi->framelen;
+               info.keyix = fi->keyix;
+               info.keytype = fi->keytype;
+
+               if (aggr) {
+                       if (bf == bf_first)
+                               info.aggr = AGGR_BUF_FIRST;
+                       else if (!bf->bf_next)
+                               info.aggr = AGGR_BUF_LAST;
+                       else
+                               info.aggr = AGGR_BUF_MIDDLE;
+
+                       info.ndelim = bf->bf_state.ndelim;
+                       info.aggr_len = len;
+               }
+
+               ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
+               bf = bf->bf_next;
+       }
+}
+
+static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
+                             struct ath_atx_tid *tid)
+{
+       struct ath_buf *bf;
+       enum ATH_AGGR_STATUS status;
+       struct ieee80211_tx_info *tx_info;
+       struct list_head bf_q;
+       int aggr_len;
+
+       do {
+               if (skb_queue_empty(&tid->buf_q))
+                       return;
+
+               INIT_LIST_HEAD(&bf_q);
+
+               status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len);
+
+               /*
+                * no frames picked up to be aggregated;
+                * block-ack window is not open.
+                */
+               if (list_empty(&bf_q))
+                       break;
+
+               bf = list_first_entry(&bf_q, struct ath_buf, list);
+               bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
+               tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
+
+               if (tid->ac->clear_ps_filter) {
+                       tid->ac->clear_ps_filter = false;
+                       tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+               } else {
+                       tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
+               }
+
+               /* if only one frame, send as non-aggregate */
+               if (bf == bf->bf_lastbf) {
+                       aggr_len = get_frame_info(bf->bf_mpdu)->framelen;
+                       bf->bf_state.bf_type = BUF_AMPDU;
+               } else {
+                       TX_STAT_INC(txq->axq_qnum, a_aggr);
+               }
+
+               ath_tx_fill_desc(sc, bf, txq, aggr_len);
+               ath_tx_txqaddbuf(sc, txq, &bf_q, false);
+       } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
+                status != ATH_AGGR_BAW_CLOSED);
+}
+
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+                     u16 tid, u16 *ssn)
+{
+       struct ath_atx_tid *txtid;
+       struct ath_node *an;
+       u8 density;
+
+       an = (struct ath_node *)sta->drv_priv;
+       txtid = ATH_AN_2_TID(an, tid);
+
+       if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
+               return -EAGAIN;
+
+       /* update ampdu factor/density, they may have changed. This may happen
+        * in HT IBSS when a beacon with HT-info is received after the station
+        * has already been added.
+        */
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+               an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
+                                    sta->ht_cap.ampdu_factor);
+               density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
+               an->mpdudensity = density;
+       }
+
+       txtid->state |= AGGR_ADDBA_PROGRESS;
+       txtid->paused = true;
+       *ssn = txtid->seq_start = txtid->seq_next;
+       txtid->bar_index = -1;
+
+       memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
+       txtid->baw_head = txtid->baw_tail = 0;
+
+       return 0;
+}
+
+void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+{
+       struct ath_node *an = (struct ath_node *)sta->drv_priv;
+       struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
+       struct ath_txq *txq = txtid->ac->txq;
+
+       if (txtid->state & AGGR_CLEANUP)
+               return;
+
+       if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
+               txtid->state &= ~AGGR_ADDBA_PROGRESS;
+               return;
+       }
+
+       ath_txq_lock(sc, txq);
+       txtid->paused = true;
+
+       /*
+        * If frames are still being transmitted for this TID, they will be
+        * cleaned up during tx completion. To prevent race conditions, this
+        * TID can only be reused after all in-progress subframes have been
+        * completed.
+        */
+       if (txtid->baw_head != txtid->baw_tail)
+               txtid->state |= AGGR_CLEANUP;
+       else
+               txtid->state &= ~AGGR_ADDBA_COMPLETE;
+
+       ath_tx_flush_tid(sc, txtid);
+       ath_txq_unlock_complete(sc, txq);
+}
+
+void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
+                      struct ath_node *an)
+{
+       struct ath_atx_tid *tid;
+       struct ath_atx_ac *ac;
+       struct ath_txq *txq;
+       bool buffered;
+       int tidno;
+
+       for (tidno = 0, tid = &an->tid[tidno];
+            tidno < WME_NUM_TID; tidno++, tid++) {
+
+               if (!tid->sched)
+                       continue;
+
+               ac = tid->ac;
+               txq = ac->txq;
+
+               ath_txq_lock(sc, txq);
+
+               buffered = !skb_queue_empty(&tid->buf_q);
+
+               tid->sched = false;
+               list_del(&tid->list);
+
+               if (ac->sched) {
+                       ac->sched = false;
+                       list_del(&ac->list);
+               }
+
+               ath_txq_unlock(sc, txq);
+
+               ieee80211_sta_set_buffered(sta, tidno, buffered);
+       }
+}
+
+void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
+{
+       struct ath_atx_tid *tid;
+       struct ath_atx_ac *ac;
+       struct ath_txq *txq;
+       int tidno;
+
+       for (tidno = 0, tid = &an->tid[tidno];
+            tidno < WME_NUM_TID; tidno++, tid++) {
+
+               ac = tid->ac;
+               txq = ac->txq;
+
+               ath_txq_lock(sc, txq);
+               ac->clear_ps_filter = true;
+
+               if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
+                       ath_tx_queue_tid(txq, tid);
+                       ath_txq_schedule(sc, txq);
+               }
+
+               ath_txq_unlock_complete(sc, txq);
+       }
+}
+
+void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+{
+       struct ath_atx_tid *txtid;
+       struct ath_node *an;
+
+       an = (struct ath_node *)sta->drv_priv;
+
+       txtid = ATH_AN_2_TID(an, tid);
+       txtid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
+       txtid->state |= AGGR_ADDBA_COMPLETE;
+       txtid->state &= ~AGGR_ADDBA_PROGRESS;
+       ath_tx_resume_tid(sc, txtid);
+}
+
+/********************/
+/* Queue Management */
+/********************/
+
+static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
+                                         struct ath_txq *txq)
+{
+       struct ath_atx_ac *ac, *ac_tmp;
+       struct ath_atx_tid *tid, *tid_tmp;
+
+       list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
+               list_del(&ac->list);
+               ac->sched = false;
+               list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
+                       list_del(&tid->list);
+                       tid->sched = false;
+                       ath_tid_drain(sc, txq, tid);
+               }
+       }
+}
+
+struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath9k_tx_queue_info qi;
+       static const int subtype_txq_to_hwq[] = {
+               [WME_AC_BE] = ATH_TXQ_AC_BE,
+               [WME_AC_BK] = ATH_TXQ_AC_BK,
+               [WME_AC_VI] = ATH_TXQ_AC_VI,
+               [WME_AC_VO] = ATH_TXQ_AC_VO,
+       };
+       int axq_qnum, i;
+
+       memset(&qi, 0, sizeof(qi));
+       qi.tqi_subtype = subtype_txq_to_hwq[subtype];
+       qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
+       qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
+       qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
+       qi.tqi_physCompBuf = 0;
+
+       /*
+        * Enable interrupts only for EOL and DESC conditions.
+        * We mark tx descriptors to receive a DESC interrupt
+        * when a tx queue gets deep; otherwise waiting for the
+        * EOL to reap descriptors.  Note that this is done to
+        * reduce interrupt load and this only defers reaping
+        * descriptors, never transmitting frames.  Aside from
+        * reducing interrupts this also permits more concurrency.
+        * The only potential downside is if the tx queue backs
+        * up in which case the top half of the kernel may backup
+        * due to a lack of tx descriptors.
+        *
+        * The UAPSD queue is an exception, since we take a desc-
+        * based intr on the EOSP frames.
+        */
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               qi.tqi_qflags = TXQ_FLAG_TXINT_ENABLE;
+       } else {
+               if (qtype == ATH9K_TX_QUEUE_UAPSD)
+                       qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
+               else
+                       qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
+                                       TXQ_FLAG_TXDESCINT_ENABLE;
+       }
+       axq_qnum = ath9k_btcoex_ath9k_hw_setuptxqueue(ah, qtype, &qi);
+       if (axq_qnum == -1) {
+               /*
+                * NB: don't print a message, this happens
+                * normally on parts with too few tx queues
+                */
+               return NULL;
+       }
+       if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
+               struct ath_txq *txq = &sc->tx.txq[axq_qnum];
+
+               txq->axq_qnum = axq_qnum;
+               txq->mac80211_qnum = -1;
+               txq->axq_link = NULL;
+               __skb_queue_head_init(&txq->complete_q);
+               INIT_LIST_HEAD(&txq->axq_q);
+               INIT_LIST_HEAD(&txq->axq_acq);
+               spin_lock_init(&txq->axq_lock);
+               txq->axq_depth = 0;
+               txq->axq_ampdu_depth = 0;
+               txq->axq_tx_inprogress = false;
+               sc->tx.txqsetup |= 1<<axq_qnum;
+
+               txq->txq_headidx = txq->txq_tailidx = 0;
+               for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
+                       INIT_LIST_HEAD(&txq->txq_fifo[i]);
+       }
+       return &sc->tx.txq[axq_qnum];
+}
+
+int ath_txq_update(struct ath_softc *sc, int qnum,
+                  struct ath9k_tx_queue_info *qinfo)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       int error = 0;
+       struct ath9k_tx_queue_info qi;
+
+       BUG_ON(sc->tx.txq[qnum].axq_qnum != qnum);
+
+       ath9k_btcoex_ath9k_hw_get_txq_props(ah, qnum, &qi);
+       qi.tqi_aifs = qinfo->tqi_aifs;
+       qi.tqi_cwmin = qinfo->tqi_cwmin;
+       qi.tqi_cwmax = qinfo->tqi_cwmax;
+       qi.tqi_burstTime = qinfo->tqi_burstTime;
+       qi.tqi_readyTime = qinfo->tqi_readyTime;
+
+       if (!ath9k_btcoex_ath9k_hw_set_txq_props(ah, qnum, &qi)) {
+               ath_err(ath9k_hw_common(sc->sc_ah),
+                       "Unable to update hardware queue %u!\n", qnum);
+               error = -EIO;
+       } else {
+               ath9k_btcoex_ath9k_hw_resettxqueue(ah, qnum);
+       }
+
+       return error;
+}
+
+int ath_cabq_update(struct ath_softc *sc)
+{
+       struct ath9k_tx_queue_info qi;
+       struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+       int qnum = sc->beacon.cabq->axq_qnum;
+
+       ath9k_btcoex_ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
+       /*
+        * Ensure the readytime % is within the bounds.
+        */
+       if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND)
+               sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND;
+       else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
+               sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
+
+       qi.tqi_readyTime = (cur_conf->beacon_interval *
+                           sc->config.cabqReadytime) / 100;
+       ath_txq_update(sc, qnum, &qi);
+
+       return 0;
+}
+
+static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
+{
+    struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
+    return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
+}
+
+static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
+                              struct list_head *list, bool retry_tx)
+{
+       struct ath_buf *bf, *lastbf;
+       struct list_head bf_head;
+       struct ath_tx_status ts;
+
+       memset(&ts, 0, sizeof(ts));
+       ts.ts_status = ATH9K_TX_FLUSH;
+       INIT_LIST_HEAD(&bf_head);
+
+       while (!list_empty(list)) {
+               bf = list_first_entry(list, struct ath_buf, list);
+
+               if (bf->bf_stale) {
+                       list_del(&bf->list);
+
+                       ath_tx_return_buffer(sc, bf);
+                       continue;
+               }
+
+               lastbf = bf->bf_lastbf;
+               list_cut_position(&bf_head, list, &lastbf->list);
+
+               txq->axq_depth--;
+               if (bf_is_ampdu_not_probing(bf))
+                       txq->axq_ampdu_depth--;
+
+               if (bf_isampdu(bf))
+                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
+                                            retry_tx);
+               else
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+       }
+}
+
+/*
+ * Drain a given TX queue (could be Beacon or Data)
+ *
+ * This assumes output has been stopped and
+ * we do not need to block ath_tx_tasklet.
+ */
+void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+{
+       ath_txq_lock(sc, txq);
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               int idx = txq->txq_tailidx;
+
+               while (!list_empty(&txq->txq_fifo[idx])) {
+                       ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
+                                          retry_tx);
+
+                       INCR(idx, ATH_TXFIFO_DEPTH);
+               }
+               txq->txq_tailidx = idx;
+       }
+
+       txq->axq_link = NULL;
+       txq->axq_tx_inprogress = false;
+       ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
+
+       /* flush any pending frames if aggregation is enabled */
+       if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !retry_tx)
+               ath_txq_drain_pending_buffers(sc, txq);
+
+       ath_txq_unlock_complete(sc, txq);
+}
+
+bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_txq *txq;
+       int i;
+       u32 npend = 0;
+
+       if (test_bit(SC_OP_INVALID, &sc->sc_flags))
+               return true;
+
+       ath9k_btcoex_ath9k_hw_abort_tx_dma(ah);
+
+       /* Check if any queue remains active */
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (!ATH_TXQ_SETUP(sc, i))
+                       continue;
+
+               if (ath9k_btcoex_ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
+                       npend |= BIT(i);
+       }
+
+       if (npend)
+               ath_err(common, "Failed to stop TX DMA, queues=0x%03x!\n", npend);
+
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (!ATH_TXQ_SETUP(sc, i))
+                       continue;
+
+               /*
+                * The caller will resume queues with ieee80211_wake_queues.
+                * Mark the queue as not stopped to prevent ath_tx_complete
+                * from waking the queue too early.
+                */
+               txq = &sc->tx.txq[i];
+               txq->stopped = false;
+               ath_draintxq(sc, txq, retry_tx);
+       }
+
+       return !npend;
+}
+
+void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
+{
+       ath9k_btcoex_ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
+       sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
+}
+
+/* For each axq_acq entry, for each tid, try to schedule packets
+ * for transmit until ampdu_depth has reached min Q depth.
+ */
+void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
+{
+       struct ath_atx_ac *ac, *ac_tmp, *last_ac;
+       struct ath_atx_tid *tid, *last_tid;
+
+       if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
+           txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+               return;
+
+       ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
+       last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
+
+       list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
+               last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
+               list_del(&ac->list);
+               ac->sched = false;
+
+               while (!list_empty(&ac->tid_q)) {
+                       tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
+                                              list);
+                       list_del(&tid->list);
+                       tid->sched = false;
+
+                       if (tid->paused)
+                               continue;
+
+                       ath_tx_sched_aggr(sc, txq, tid);
+
+                       /*
+                        * add tid to round-robin queue if more frames
+                        * are pending for the tid
+                        */
+                       if (!skb_queue_empty(&tid->buf_q))
+                               ath_tx_queue_tid(txq, tid);
+
+                       if (tid == last_tid ||
+                           txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+                               break;
+               }
+
+               if (!list_empty(&ac->tid_q) && !ac->sched) {
+                       ac->sched = true;
+                       list_add_tail(&ac->list, &txq->axq_acq);
+               }
+
+               if (ac == last_ac ||
+                   txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+                       return;
+       }
+}
+
+/***********/
+/* TX, DMA */
+/***********/
+
+/*
+ * Insert a chain of ath_buf (descriptors) on a txq and
+ * assume the descriptors are already chained together by caller.
+ */
+static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+                            struct list_head *head, bool internal)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_buf *bf, *bf_last;
+       bool puttxbuf = false;
+       bool edma;
+
+       /*
+        * Insert the frame on the outbound list and
+        * pass it on to the hardware.
+        */
+
+       if (list_empty(head))
+               return;
+
+       edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+       bf = list_first_entry(head, struct ath_buf, list);
+       bf_last = list_entry(head->prev, struct ath_buf, list);
+
+       ath_dbg(common, QUEUE, "qnum: %d, txq depth: %d\n",
+               txq->axq_qnum, txq->axq_depth);
+
+       if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
+               list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
+               INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
+               puttxbuf = true;
+       } else {
+               list_splice_tail_init(head, &txq->axq_q);
+
+               if (txq->axq_link) {
+                       ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
+                       ath_dbg(common, XMIT, "link[%u] (%p)=%llx (%p)\n",
+                               txq->axq_qnum, txq->axq_link,
+                               ito64(bf->bf_daddr), bf->bf_desc);
+               } else if (!edma)
+                       puttxbuf = true;
+
+               txq->axq_link = bf_last->bf_desc;
+       }
+
+       if (puttxbuf) {
+               TX_STAT_INC(txq->axq_qnum, puttxbuf);
+               ath9k_btcoex_ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+               ath_dbg(common, XMIT, "TXDP[%u] = %llx (%p)\n",
+                       txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+       }
+
+       if (!edma) {
+               TX_STAT_INC(txq->axq_qnum, txstart);
+               ath9k_btcoex_ath9k_hw_txstart(ah, txq->axq_qnum);
+       }
+
+       if (!internal) {
+               txq->axq_depth++;
+               if (bf_is_ampdu_not_probing(bf))
+                       txq->axq_ampdu_depth++;
+       }
+}
+
+static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
+                             struct sk_buff *skb, struct ath_tx_control *txctl)
+{
+       struct ath_frame_info *fi = get_frame_info(skb);
+       struct list_head bf_head;
+       struct ath_buf *bf;
+
+       /*
+        * Do not queue to h/w when any of the following conditions is true:
+        * - there are pending frames in software queue
+        * - the TID is currently paused for ADDBA/BAR request
+        * - seqno is not within block-ack window
+        * - h/w queue depth exceeds low water mark
+        */
+       if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
+           !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) ||
+           txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
+               /*
+                * Add this frame to software queue for scheduling later
+                * for aggregation.
+                */
+               TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
+               __skb_queue_tail(&tid->buf_q, skb);
+               if (!txctl->an || !txctl->an->sleeping)
+                       ath_tx_queue_tid(txctl->txq, tid);
+               return;
+       }
+
+       bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
+       if (!bf)
+               return;
+
+       bf->bf_state.bf_type = BUF_AMPDU;
+       INIT_LIST_HEAD(&bf_head);
+       list_add(&bf->list, &bf_head);
+
+       /* Add sub-frame to BAW */
+       ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
+
+       /* Queue to h/w without aggregation */
+       TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
+       bf->bf_lastbf = bf;
+       ath_tx_fill_desc(sc, bf, txctl->txq, fi->framelen);
+       ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
+}
+
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+                              struct ath_atx_tid *tid, struct sk_buff *skb)
+{
+       struct ath_frame_info *fi = get_frame_info(skb);
+       struct list_head bf_head;
+       struct ath_buf *bf;
+
+       bf = fi->bf;
+       if (!bf)
+               bf = ath_tx_setup_buffer(sc, txq, tid, skb, false);
+
+       if (!bf)
+               return;
+
+       INIT_LIST_HEAD(&bf_head);
+       list_add_tail(&bf->list, &bf_head);
+       bf->bf_state.bf_type = 0;
+
+       bf->bf_lastbf = bf;
+       ath_tx_fill_desc(sc, bf, txq, fi->framelen);
+       ath_tx_txqaddbuf(sc, txq, &bf_head, false);
+       TX_STAT_INC(txq->axq_qnum, queued);
+}
+
+static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
+                            int framelen)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_sta *sta = tx_info->control.sta;
+       struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       const struct ieee80211_rate *rate;
+       struct ath_frame_info *fi = get_frame_info(skb);
+       struct ath_node *an = NULL;
+       enum ath9k_key_type keytype;
+       bool short_preamble = false;
+
+       /*
+        * We check if Short Preamble is needed for the CTS rate by
+        * checking the BSS's global flag.
+        * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
+        */
+       if (tx_info->control.vif &&
+           tx_info->control.vif->bss_conf.use_short_preamble)
+               short_preamble = true;
+
+       rate = ieee80211_get_rts_cts_rate(hw, tx_info);
+       keytype = ath9k_btcoex_ath9k_cmn_get_hw_crypto_keytype(skb);
+
+       if (sta)
+               an = (struct ath_node *) sta->drv_priv;
+
+       memset(fi, 0, sizeof(*fi));
+       if (hw_key)
+               fi->keyix = hw_key->hw_key_idx;
+       else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
+               fi->keyix = an->ps_key;
+       else
+               fi->keyix = ATH9K_TXKEYIX_INVALID;
+       fi->keytype = keytype;
+       fi->framelen = framelen;
+       fi->rtscts_rate = rate->hw_value;
+       if (short_preamble)
+               fi->rtscts_rate |= rate->hw_value_short;
+}
+
+u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath9k_channel *curchan = ah->curchan;
+       if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) &&
+           (curchan->channelFlags & CHANNEL_5GHZ) &&
+           (chainmask == 0x7) && (rate < 0x90))
+               return 0x3;
+       else
+               return chainmask;
+}
+
+/*
+ * Assign a descriptor (and sequence number if necessary,
+ * and map buffer for DMA. Frees skb on error
+ */
+static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+                                          struct ath_txq *txq,
+                                          struct ath_atx_tid *tid,
+                                          struct sk_buff *skb,
+                                          bool dequeue)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_frame_info *fi = get_frame_info(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ath_buf *bf;
+       int fragno;
+       u16 seqno;
+
+       bf = ath_tx_get_buffer(sc);
+       if (!bf) {
+               ath_dbg(common, XMIT, "TX buffers are full\n");
+               goto error;
+       }
+
+       ATH_TXBUF_RESET(bf);
+
+       if (tid) {
+               fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
+               seqno = tid->seq_next;
+               hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
+
+               if (fragno)
+                       hdr->seq_ctrl |= cpu_to_le16(fragno);
+
+               if (!ieee80211_has_morefrags(hdr->frame_control))
+                       INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+
+               bf->bf_state.seqno = seqno;
+       }
+
+       bf->bf_mpdu = skb;
+
+       bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+                                        skb->len, DMA_TO_DEVICE);
+       if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
+               bf->bf_mpdu = NULL;
+               bf->bf_buf_addr = 0;
+               ath_err(ath9k_hw_common(sc->sc_ah),
+                       "dma_mapping_error() on TX\n");
+               ath_tx_return_buffer(sc, bf);
+               goto error;
+       }
+
+       fi->bf = bf;
+
+       return bf;
+
+error:
+       if (dequeue)
+               __skb_unlink(skb, &tid->buf_q);
+       dev_kfree_skb_any(skb);
+       return NULL;
+}
+
+/* FIXME: tx power */
+static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
+                            struct ath_tx_control *txctl)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ath_atx_tid *tid = NULL;
+       struct ath_buf *bf;
+       u8 tidno;
+
+       if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && txctl->an &&
+               ieee80211_is_data_qos(hdr->frame_control)) {
+               tidno = ieee80211_get_qos_ctl(hdr)[0] &
+                       IEEE80211_QOS_CTL_TID_MASK;
+               tid = ATH_AN_2_TID(txctl->an, tidno);
+
+               WARN_ON(tid->ac->txq != txctl->txq);
+       }
+
+       if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+               /*
+                * Try aggregation if it's a unicast data frame
+                * and the destination is HT capable.
+                */
+               ath_tx_send_ampdu(sc, tid, skb, txctl);
+       } else {
+               bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
+               if (!bf)
+                       return;
+
+               bf->bf_state.bfs_paprd = txctl->paprd;
+
+               if (txctl->paprd)
+                       bf->bf_state.bfs_paprd_timestamp = jiffies;
+
+               ath_tx_send_normal(sc, txctl->txq, tid, skb);
+       }
+}
+
+/* Upon failure caller should free skb */
+int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
+                struct ath_tx_control *txctl)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_sta *sta = info->control.sta;
+       struct ieee80211_vif *vif = info->control.vif;
+       struct ath_softc *sc = hw->priv;
+       struct ath_txq *txq = txctl->txq;
+       int padpos, padsize;
+       int frmlen = skb->len + FCS_LEN;
+       int q;
+
+       /* NOTE:  sta can be NULL according to net/mac80211.h */
+       if (sta)
+               txctl->an = (struct ath_node *)sta->drv_priv;
+
+       if (info->control.hw_key)
+               frmlen += info->control.hw_key->icv_len;
+
+       /*
+        * As a temporary workaround, assign seq# here; this will likely need
+        * to be cleaned up to work better with Beacon transmission and virtual
+        * BSSes.
+        */
+       if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+               if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+                       sc->tx.seq_no += 0x10;
+               hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+               hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
+       }
+
+       /* Add the padding after the header if this is not already done */
+       padpos = ath9k_btcoex_ath9k_cmn_padpos(hdr->frame_control);
+       padsize = padpos & 3;
+       if (padsize && skb->len > padpos) {
+               if (skb_headroom(skb) < padsize)
+                       return -ENOMEM;
+
+               skb_push(skb, padsize);
+               memmove(skb->data, skb->data + padsize, padpos);
+               hdr = (struct ieee80211_hdr *) skb->data;
+       }
+
+       if ((vif && vif->type != NL80211_IFTYPE_AP &&
+                   vif->type != NL80211_IFTYPE_AP_VLAN) ||
+           !ieee80211_is_data(hdr->frame_control))
+               info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+
+       setup_frame_info(hw, skb, frmlen);
+
+       /*
+        * At this point, the vif, hw_key and sta pointers in the tx control
+        * info are no longer valid (overwritten by the ath_frame_info data.
+        */
+
+       q = skb_get_queue_mapping(skb);
+
+       ath_txq_lock(sc, txq);
+       if (txq == sc->tx.txq_map[q] &&
+           ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
+               ieee80211_stop_queue(sc->hw, q);
+               txq->stopped = true;
+       }
+
+       ath_tx_start_dma(sc, skb, txctl);
+
+       ath_txq_unlock(sc, txq);
+
+       return 0;
+}
+
+/*****************/
+/* TX Completion */
+/*****************/
+
+static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+                           int tx_flags, struct ath_txq *txq)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
+       int q, padpos, padsize;
+
+       ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
+
+       if (!(tx_flags & ATH_TX_ERROR))
+               /* Frame was ACKed */
+               tx_info->flags |= IEEE80211_TX_STAT_ACK;
+
+       padpos = ath9k_btcoex_ath9k_cmn_padpos(hdr->frame_control);
+       padsize = padpos & 3;
+       if (padsize && skb->len>padpos+padsize) {
+               /*
+                * Remove MAC header padding before giving the frame back to
+                * mac80211.
+                */
+               memmove(skb->data + padsize, skb->data, padpos);
+               skb_pull(skb, padsize);
+       }
+
+       if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) {
+               sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
+               ath_dbg(common, PS,
+                       "Going back to sleep after having received TX status (0x%lx)\n",
+                       sc->ps_flags & (PS_WAIT_FOR_BEACON |
+                                       PS_WAIT_FOR_CAB |
+                                       PS_WAIT_FOR_PSPOLL_DATA |
+                                       PS_WAIT_FOR_TX_ACK));
+       }
+
+       q = skb_get_queue_mapping(skb);
+       if (txq == sc->tx.txq_map[q]) {
+               if (WARN_ON(--txq->pending_frames < 0))
+                       txq->pending_frames = 0;
+
+               if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
+                       ieee80211_wake_queue(sc->hw, q);
+                       txq->stopped = false;
+               }
+       }
+
+       __skb_queue_tail(&txq->complete_q, skb);
+}
+
+static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+                               struct ath_txq *txq, struct list_head *bf_q,
+                               struct ath_tx_status *ts, int txok)
+{
+       struct sk_buff *skb = bf->bf_mpdu;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       unsigned long flags;
+       int tx_flags = 0;
+
+       if (!txok)
+               tx_flags |= ATH_TX_ERROR;
+
+       if (ts->ts_status & ATH9K_TXERR_FILT)
+               tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+
+       dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
+       bf->bf_buf_addr = 0;
+
+       if (bf->bf_state.bfs_paprd) {
+               if (time_after(jiffies,
+                               bf->bf_state.bfs_paprd_timestamp +
+                               msecs_to_jiffies(ATH_PAPRD_TIMEOUT)))
+                       dev_kfree_skb_any(skb);
+               else
+                       complete(&sc->paprd_complete);
+       } else {
+               ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
+               ath_tx_complete(sc, skb, tx_flags, txq);
+       }
+       /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
+        * accidentally reference it later.
+        */
+       bf->bf_mpdu = NULL;
+
+       /*
+        * Return the list of ath_buf of this mpdu to free queue
+        */
+       spin_lock_irqsave(&sc->tx.txbuflock, flags);
+       list_splice_tail_init(bf_q, &sc->tx.txbuf);
+       spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
+}
+
+static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+                            struct ath_tx_status *ts, int nframes, int nbad,
+                            int txok)
+{
+       struct sk_buff *skb = bf->bf_mpdu;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hw *hw = sc->hw;
+       struct ath_hw *ah = sc->sc_ah;
+       u8 i, tx_rateindex;
+
+       if (txok)
+               tx_info->status.ack_signal = ts->ts_rssi;
+
+       tx_rateindex = ts->ts_rateindex;
+       WARN_ON(tx_rateindex >= hw->max_rates);
+
+       if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+               tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+
+               BUG_ON(nbad > nframes);
+       }
+       tx_info->status.ampdu_len = nframes;
+       tx_info->status.ampdu_ack_len = nframes - nbad;
+
+       if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
+           (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
+               /*
+                * If an underrun error is seen assume it as an excessive
+                * retry only if max frame trigger level has been reached
+                * (2 KB for single stream, and 4 KB for dual stream).
+                * Adjust the long retry as if the frame was tried
+                * hw->max_rate_tries times to affect how rate control updates
+                * PER for the failed rate.
+                * In case of congestion on the bus penalizing this type of
+                * underruns should help hardware actually transmit new frames
+                * successfully by eventually preferring slower rates.
+                * This itself should also alleviate congestion on the bus.
+                */
+               if (unlikely(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
+                                            ATH9K_TX_DELIM_UNDERRUN)) &&
+                   ieee80211_is_data(hdr->frame_control) &&
+                   ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)
+                       tx_info->status.rates[tx_rateindex].count =
+                               hw->max_rate_tries;
+       }
+
+       for (i = tx_rateindex + 1; i < hw->max_rates; i++) {
+               tx_info->status.rates[i].count = 0;
+               tx_info->status.rates[i].idx = -1;
+       }
+
+       tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
+}
+
+static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
+                                 struct ath_tx_status *ts, struct ath_buf *bf,
+                                 struct list_head *bf_head)
+{
+       int txok;
+
+       txq->axq_depth--;
+       txok = !(ts->ts_status & ATH9K_TXERR_MASK);
+       txq->axq_tx_inprogress = false;
+       if (bf_is_ampdu_not_probing(bf))
+               txq->axq_ampdu_depth--;
+
+       if (!bf_isampdu(bf)) {
+               ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
+               ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
+       } else
+               ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
+               ath_txq_schedule(sc, txq);
+}
+
+static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_buf *bf, *lastbf, *bf_held = NULL;
+       struct list_head bf_head;
+       struct ath_desc *ds;
+       struct ath_tx_status ts;
+       int status;
+
+       ath_dbg(common, QUEUE, "tx queue %d (%x), link %p\n",
+               txq->axq_qnum, ath9k_btcoex_ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
+               txq->axq_link);
+
+       ath_txq_lock(sc, txq);
+       for (;;) {
+               if (work_pending(&sc->hw_reset_work))
+                       break;
+
+               if (list_empty(&txq->axq_q)) {
+                       txq->axq_link = NULL;
+                       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
+                               ath_txq_schedule(sc, txq);
+                       break;
+               }
+               bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
+
+               /*
+                * There is a race condition that a BH gets scheduled
+                * after sw writes TxE and before hw re-load the last
+                * descriptor to get the newly chained one.
+                * Software must keep the last DONE descriptor as a
+                * holding descriptor - software does so by marking
+                * it with the STALE flag.
+                */
+               bf_held = NULL;
+               if (bf->bf_stale) {
+                       bf_held = bf;
+                       if (list_is_last(&bf_held->list, &txq->axq_q))
+                               break;
+
+                       bf = list_entry(bf_held->list.next, struct ath_buf,
+                                       list);
+               }
+
+               lastbf = bf->bf_lastbf;
+               ds = lastbf->bf_desc;
+
+               memset(&ts, 0, sizeof(ts));
+               status = ath9k_hw_txprocdesc(ah, ds, &ts);
+               if (status == -EINPROGRESS)
+                       break;
+
+               TX_STAT_INC(txq->axq_qnum, txprocdesc);
+
+               /*
+                * Remove ath_buf's of the same transmit unit from txq,
+                * however leave the last descriptor back as the holding
+                * descriptor for hw.
+                */
+               lastbf->bf_stale = true;
+               INIT_LIST_HEAD(&bf_head);
+               if (!list_is_singular(&lastbf->list))
+                       list_cut_position(&bf_head,
+                               &txq->axq_q, lastbf->list.prev);
+
+               if (bf_held) {
+                       list_del(&bf_held->list);
+                       ath_tx_return_buffer(sc, bf_held);
+               }
+
+               ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
+       }
+       ath_txq_unlock_complete(sc, txq);
+}
+
+static void ath_tx_complete_poll_work(struct work_struct *work)
+{
+       struct ath_softc *sc = container_of(work, struct ath_softc,
+                       tx_complete_work.work);
+       struct ath_txq *txq;
+       int i;
+       bool needreset = false;
+#ifdef CONFIG_ATH9K_DEBUGFS
+       sc->tx_complete_poll_work_seen++;
+#endif
+
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+               if (ATH_TXQ_SETUP(sc, i)) {
+                       txq = &sc->tx.txq[i];
+                       ath_txq_lock(sc, txq);
+                       if (txq->axq_depth) {
+                               if (txq->axq_tx_inprogress) {
+                                       needreset = true;
+                                       ath_txq_unlock(sc, txq);
+                                       break;
+                               } else {
+                                       txq->axq_tx_inprogress = true;
+                               }
+                       }
+                       ath_txq_unlock_complete(sc, txq);
+               }
+
+       if (needreset) {
+               ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
+                       "tx hung, resetting the chip\n");
+               RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+       }
+
+       ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+                       msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
+}
+
+
+
+void ath_tx_tasklet(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1) & ah->intr_txqs;
+       int i;
+
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
+                       ath_tx_processq(sc, &sc->tx.txq[i]);
+       }
+}
+
+void ath_tx_edma_tasklet(struct ath_softc *sc)
+{
+       struct ath_tx_status ts;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_txq *txq;
+       struct ath_buf *bf, *lastbf;
+       struct list_head bf_head;
+       int status;
+
+       for (;;) {
+               if (work_pending(&sc->hw_reset_work))
+                       break;
+
+               status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
+               if (status == -EINPROGRESS)
+                       break;
+               if (status == -EIO) {
+                       ath_dbg(common, XMIT, "Error processing tx status\n");
+                       break;
+               }
+
+               /* Process beacon completions separately */
+               if (ts.qid == sc->beacon.beaconq) {
+                       sc->beacon.tx_processed = true;
+                       sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
+                       continue;
+               }
+
+               txq = &sc->tx.txq[ts.qid];
+
+               ath_txq_lock(sc, txq);
+
+               if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+                       ath_txq_unlock(sc, txq);
+                       return;
+               }
+
+               bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
+                                     struct ath_buf, list);
+               lastbf = bf->bf_lastbf;
+
+               INIT_LIST_HEAD(&bf_head);
+               list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
+                                 &lastbf->list);
+
+               if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+                       INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
+
+                       if (!list_empty(&txq->axq_q)) {
+                               struct list_head bf_q;
+
+                               INIT_LIST_HEAD(&bf_q);
+                               txq->axq_link = NULL;
+                               list_splice_tail_init(&txq->axq_q, &bf_q);
+                               ath_tx_txqaddbuf(sc, txq, &bf_q, true);
+                       }
+               }
+
+               ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
+               ath_txq_unlock_complete(sc, txq);
+       }
+}
+
+/*****************/
+/* Init, Cleanup */
+/*****************/
+
+static int ath_txstatus_setup(struct ath_softc *sc, int size)
+{
+       struct ath_descdma *dd = &sc->txsdma;
+       u8 txs_len = sc->sc_ah->caps.txs_len;
+
+       dd->dd_desc_len = size * txs_len;
+       dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
+                                        &dd->dd_desc_paddr, GFP_KERNEL);
+       if (!dd->dd_desc)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int ath_tx_edma_init(struct ath_softc *sc)
+{
+       int err;
+
+       err = ath_txstatus_setup(sc, ATH_TXSTATUS_RING_SIZE);
+       if (!err)
+               ath9k_btcoex_ath9k_hw_setup_statusring(sc->sc_ah, sc->txsdma.dd_desc,
+                                         sc->txsdma.dd_desc_paddr,
+                                         ATH_TXSTATUS_RING_SIZE);
+
+       return err;
+}
+
+static void ath_tx_edma_cleanup(struct ath_softc *sc)
+{
+       struct ath_descdma *dd = &sc->txsdma;
+
+       dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
+                         dd->dd_desc_paddr);
+}
+
+int ath_tx_init(struct ath_softc *sc, int nbufs)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       int error = 0;
+
+       spin_lock_init(&sc->tx.txbuflock);
+
+       error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
+                                 "tx", nbufs, 1, 1);
+       if (error != 0) {
+               ath_err(common,
+                       "Failed to allocate tx descriptors: %d\n", error);
+               goto err;
+       }
+
+       error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
+                                 "beacon", ATH_BCBUF, 1, 1);
+       if (error != 0) {
+               ath_err(common,
+                       "Failed to allocate beacon descriptors: %d\n", error);
+               goto err;
+       }
+
+       INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               error = ath_tx_edma_init(sc);
+               if (error)
+                       goto err;
+       }
+
+err:
+       if (error != 0)
+               ath_tx_cleanup(sc);
+
+       return error;
+}
+
+void ath_tx_cleanup(struct ath_softc *sc)
+{
+       if (sc->beacon.bdma.dd_desc_len != 0)
+               ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
+
+       if (sc->tx.txdma.dd_desc_len != 0)
+               ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+               ath_tx_edma_cleanup(sc);
+}
+
+void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
+{
+       struct ath_atx_tid *tid;
+       struct ath_atx_ac *ac;
+       int tidno, acno;
+
+       for (tidno = 0, tid = &an->tid[tidno];
+            tidno < WME_NUM_TID;
+            tidno++, tid++) {
+               tid->an        = an;
+               tid->tidno     = tidno;
+               tid->seq_start = tid->seq_next = 0;
+               tid->baw_size  = WME_MAX_BA;
+               tid->baw_head  = tid->baw_tail = 0;
+               tid->sched     = false;
+               tid->paused    = false;
+               tid->state &= ~AGGR_CLEANUP;
+               __skb_queue_head_init(&tid->buf_q);
+               acno = TID_TO_WME_AC(tidno);
+               tid->ac = &an->ac[acno];
+               tid->state &= ~AGGR_ADDBA_COMPLETE;
+               tid->state &= ~AGGR_ADDBA_PROGRESS;
+       }
+
+       for (acno = 0, ac = &an->ac[acno];
+            acno < WME_NUM_AC; acno++, ac++) {
+               ac->sched    = false;
+               ac->txq = sc->tx.txq_map[acno];
+               INIT_LIST_HEAD(&ac->tid_q);
+       }
+}
+
+void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
+{
+       struct ath_atx_ac *ac;
+       struct ath_atx_tid *tid;
+       struct ath_txq *txq;
+       int tidno;
+
+       for (tidno = 0, tid = &an->tid[tidno];
+            tidno < WME_NUM_TID; tidno++, tid++) {
+
+               ac = tid->ac;
+               txq = ac->txq;
+
+               ath_txq_lock(sc, txq);
+
+               if (tid->sched) {
+                       list_del(&tid->list);
+                       tid->sched = false;
+               }
+
+               if (ac->sched) {
+                       list_del(&ac->list);
+                       tid->ac->sched = false;
+               }
+
+               ath_tid_drain(sc, txq, tid);
+               tid->state &= ~AGGR_ADDBA_COMPLETE;
+               tid->state &= ~AGGR_CLEANUP;
+
+               ath_txq_unlock(sc, txq);
+       }
+}